1 module vibelog.dbcontroller; 2 3 public import vibelog.config; 4 public import vibelog.post; 5 public import vibelog.user; 6 7 import vibe.db.mongo.mongo; 8 import vibe.core.log; 9 import vibe.data.bson; 10 11 import std.exception; 12 13 14 class DBController { 15 private { 16 MongoDB m_db; 17 string m_dbname; 18 MongoCollection m_configs; 19 MongoCollection m_users; 20 MongoCollection m_posts; 21 } 22 23 this(string host, ushort port, string dbname) 24 { 25 m_db = connectMongoDB(host, port); 26 m_dbname = dbname; 27 m_configs = m_db[m_dbname~"."~"configs"]; 28 m_users = m_db[m_dbname~"."~"users"]; 29 m_posts = m_db[m_dbname~"."~"posts"]; 30 } 31 32 Config getConfig(string name, bool createdefault = false) 33 { 34 auto configbson = m_configs.findOne(["name": Bson(name)]); 35 if( !configbson.isNull() ) 36 return Config.fromBson(configbson); 37 enforce(createdefault, "Configuration does not exist."); 38 auto cfg = new Config; 39 cfg.name = name; 40 m_configs.insert(cfg.toBson()); 41 return cfg; 42 } 43 44 void setConfig(Config cfg) 45 { 46 Bson update = cfg.toBson(); 47 m_configs.update(["name": Bson(cfg.name)], update); 48 } 49 50 void deleteConfig(string name) 51 { 52 m_configs.remove(["name": Bson(name)]); 53 } 54 55 Config[] getAllConfigs() 56 { 57 Bson[string] query; 58 Config[] ret; 59 foreach( config; m_configs.find(query) ){ 60 auto c = Config.fromBson(config); 61 ret ~= c; 62 } 63 return ret; 64 } 65 66 User[string] getAllUsers() 67 { 68 Bson[string] query; 69 User[string] ret; 70 foreach( user; m_users.find(query) ){ 71 auto u = User.fromBson(user); 72 ret[u.username] = u; 73 } 74 if( ret.length == 0 ){ 75 auto initial_admin = new User; 76 initial_admin.username = "admin"; 77 initial_admin.password = generatePasswordHash("admin"); 78 initial_admin.name = "Default Administrator"; 79 initial_admin.groups ~= "admin"; 80 m_users.insert(initial_admin); 81 ret["admin"] = initial_admin; 82 } 83 return ret; 84 } 85 86 User getUser(BsonObjectID userid) 87 { 88 auto userbson = m_users.findOne(["_id": Bson(userid)]); 89 return User.fromBson(userbson); 90 } 91 92 User getUser(string name) 93 { 94 auto userbson = m_users.findOne(["username": Bson(name)]); 95 if( userbson.isNull() ){ 96 auto id = BsonObjectID.fromHexString(name); 97 logDebug("%s <-> %s", name, id.toString()); 98 assert(id.toString() == name); 99 userbson = m_users.findOne(["_id": Bson(id)]); 100 } 101 //auto userbson = m_users.findOne(Bson(["name" : Bson(name)])); 102 return User.fromBson(userbson); 103 } 104 105 BsonObjectID addUser(User user) 106 { 107 auto id = BsonObjectID.generate(); 108 Bson userbson = user.toBson(); 109 userbson["_id"] = Bson(id); 110 m_users.insert(userbson); 111 return id; 112 } 113 114 void modifyUser(User user) 115 { 116 assert(user._id.valid); 117 Bson update = user.toBson(); 118 m_users.update(["_id": Bson(user._id)], update); 119 } 120 121 void deleteUser(BsonObjectID id) 122 { 123 assert(id.valid); 124 m_users.remove(["_id": Bson(id)]); 125 } 126 127 int countPostsForCategory(string[] categories) 128 { 129 int cnt; 130 getPostsForCategory(categories, 0, (size_t, Post p){ if( p.isPublic ) cnt++; return true; }); 131 return cnt; 132 } 133 134 void getPostsForCategory(string[] categories, int nskip, bool delegate(size_t idx, Post post) del) 135 { 136 auto cats = new Bson[categories.length]; 137 foreach( i; 0 .. categories.length ) cats[i] = Bson(categories[i]); 138 Bson category = Bson(["$in" : Bson(cats)]); 139 Bson[string] query = ["query" : Bson(["category" : category]), "orderby" : Bson(["_id" : Bson(-1)])]; 140 foreach( idx, post; m_posts.find(query, null, QueryFlags.None, nskip) ){ 141 if( !del(idx, Post.fromBson(post)) ) 142 break; 143 } 144 } 145 146 void getPublicPostsForCategory(string[] categories, int nskip, bool delegate(size_t idx, Post post) del) 147 { 148 auto cats = new Bson[categories.length]; 149 foreach( i; 0 .. categories.length ) cats[i] = Bson(categories[i]); 150 Bson category = Bson(["$in" : Bson(cats)]); 151 Bson[string] query = ["query" : Bson(["category" : category, "isPublic": Bson(true)]), "orderby" : Bson(["_id" : Bson(-1)])]; 152 foreach( idx, post; m_posts.find(query, null, QueryFlags.None, nskip) ){ 153 if( !del(idx, Post.fromBson(post)) ) 154 break; 155 } 156 } 157 158 void getAllPosts(int nskip, bool delegate(size_t idx, Post post) del) 159 { 160 Bson[string] query; 161 Bson[string] extquery = ["query" : Bson(query), "orderby" : Bson(["_id" : Bson(-1)])]; 162 foreach( idx, post; m_posts.find(extquery, null, QueryFlags.None, nskip) ){ 163 if( !del(idx, Post.fromBson(post)) ) 164 break; 165 } 166 } 167 168 169 Post getPost(BsonObjectID postid) 170 { 171 auto postbson = m_posts.findOne(["_id": Bson(postid)]); 172 return Post.fromBson(postbson); 173 } 174 175 Post getPost(string name) 176 { 177 auto postbson = m_posts.findOne(["slug": Bson(name)]); 178 if( postbson.isNull() ) 179 postbson = m_posts.findOne(["_id" : Bson(BsonObjectID.fromHexString(name))]); 180 return Post.fromBson(postbson); 181 } 182 183 bool hasPost(string name) 184 { 185 return !m_posts.findOne(["slug": Bson(name)]).isNull(); 186 187 } 188 189 BsonObjectID addPost(Post post) 190 { 191 auto id = BsonObjectID.generate(); 192 Bson postbson = post.toBson(); 193 postbson["_id"] = Bson(id); 194 m_posts.insert(postbson); 195 return id; 196 } 197 198 void modifyPost(Post post) 199 { 200 assert(post.id.valid); 201 Bson update = post.toBson(); 202 m_posts.update(["_id": Bson(post.id)], update); 203 } 204 205 void deletePost(BsonObjectID id) 206 { 207 assert(id.valid); 208 m_posts.remove(["_id": Bson(id)]); 209 } 210 211 212 void addComment(BsonObjectID post, Comment comment) 213 { 214 Bson cmtbson = comment.toBson(); 215 m_posts.update(["_id": Bson(post)], Bson(["$push" : Bson(["comments" : cmtbson])])); 216 } 217 }