OSDN Git Service

df5804cf04d9c0e78a2e6a84101c8221e33d49d8
[webchat/WebChat.git] / profile.js
1 var config = require("./configure.js");\r
2 var resource = require("./resources.js");\r
3 var util = require("util");\r
4 var async = require("async");\r
5 var security = require("./security.js");\r
6 var ejs = require("ejs");\r
7 require("date-utils");\r
8 \r
9 var collection = new ProfileCollection();\r
10 \r
11 module.exports = function(app){\r
12         app.get("/profile",list_proc);\r
13         app.get("/profile/admin",admin_proc);\r
14         app.post("/profile/admin",admin_postproc);\r
15         app.get("/profile/detail",detail_proc);\r
16         app.post("/profile/detail",detail_postproc);\r
17         app.post("/profile/edit",edit_postproc); \r
18         app.get("/profile/registor",registor_proc); \r
19         app.post("/profile/registor",registor_postproc); \r
20 };\r
21 \r
22 function admin_proc(req, res)\r
23 {\r
24         var info = new security.SessionInfomation(true);\r
25         req.session.items = info;\r
26         async.waterfall([\r
27                 function(callback){\r
28                         PrepaerListAsync(req,callback);\r
29                 }\r
30         ],function(err,result){\r
31                 if(err != null)\r
32                         RenderMessage(res,err,info);\r
33                 else{\r
34                         result.token = req.session._csrf;\r
35                         res.setHeader("X-FRAME-OPTIONS","DENY");\r
36                         res.render("profile/admin",result);\r
37                 }\r
38         });\r
39 }\r
40 \r
41 function admin_postproc(req,res)\r
42 {\r
43         async.waterfall([\r
44                 function(cb){\r
45                         if(typeof(req.body.removeall) != "undefined")\r
46                                 collection.ClearAsync(cb);\r
47                         if(typeof(req.body.remove) != "undefined")\r
48                                 collection.RemoveRangeAsync(req.body.names,cb);\r
49                 }\r
50         ],function(err,result){\r
51                 if(err != null)\r
52                         RenderMessage(res,err,req.session.items);\r
53                 else\r
54                         RenderMessage(res,resource.success_remove,req.session.items);\r
55         });\r
56 }\r
57 \r
58 function list_proc(req, res)\r
59 {\r
60         if(typeof(req.session.items) != "undefined")\r
61                 req.session.items.admin = false;\r
62         async.waterfall([\r
63                 function(cb){\r
64                         PrepaerListAsync(req,cb);\r
65                 }\r
66         ],function(err,result){\r
67                 if(err != null)\r
68                         RenderMessage(res,err,req.session.items);\r
69                 else\r
70                         res.render("profile/list",result);\r
71         });\r
72 }\r
73 \r
74 function PrepaerListAsync(req,callback)\r
75 {\r
76         var limit = config.db_limit;\r
77         var start = 0;\r
78         var parttern = "";\r
79         if(typeof(req.query.start) != "undefined")\r
80                 start = parseInt(req.query.start);\r
81         if(typeof(req.query.limit) != "undefined")\r
82                 limit = parseInt(req.query.limit);\r
83 \r
84         async.waterfall([\r
85                 function(cb){\r
86                         if(typeof(req.query.search) != "undefined")\r
87                         {\r
88                                 parttern = req.query.search;\r
89                                 collection.FindByNameAsync(parttern,start,limit,cb);\r
90                         }else{\r
91                                 collection.ToArrayAsync(start,limit,cb);\r
92                         }\r
93                 }\r
94         ],function(err,result){\r
95                 if(err != null){\r
96                         callback(err,null);\r
97                 }else{\r
98                         var next = start + limit;\r
99                         var prev = start - limit;\r
100                         if(prev < 0)\r
101                                 prev = 0;\r
102                         for(var i = 0; i < result.length; i++)\r
103                                 result[i].lastmodified = result[i].lastmodified.toFormat("YYYY/MM/DD HH:MI:SS");\r
104                         callback(null,{list:result,search:parttern,next:next,prev:prev,limit:limit});\r
105                 }\r
106         });\r
107 }\r
108 \r
109 function detail_proc(req, res)\r
110 {\r
111         if(typeof(req.query.name) == "undefined")\r
112         {\r
113                 RenderMessage(res,resource.invaild_parameter,req.session.items);\r
114                 return;\r
115         }\r
116 \r
117         if(typeof(req.session.items) == "undefined")\r
118                 req.session.items = new security.SessionInfomation(false);\r
119 \r
120         async.waterfall([\r
121                 function(cb){\r
122                         collection.GetAsync(req.query.name,cb);\r
123                 },\r
124         ],function(err,result){\r
125                 if(err != null)\r
126                         RenderMessage(res,err,req.session.items);\r
127                 else if(result.length == 0)\r
128                         RenderMessage(res,resource.notfound_name,req.session.items);\r
129                 else{\r
130                         res.setHeader("X-FRAME-OPTIONS","DENY");\r
131                         res.render("profile/detail",{list:result,alias:config.alias,token:req.session._csrf,admin:req.session.items.admin});\r
132                 }\r
133         });\r
134 }\r
135 \r
136 function detail_postproc(req, res)\r
137 {\r
138         if(typeof(req.body.remove) != "undefined"){\r
139                 async.waterfall([\r
140                         function(cb){\r
141                                 if(typeof(req.session.items) != "undefined" && req.session.items.admin)\r
142                                         cb(null,true);\r
143                                 else\r
144                                         collection.AuthAsync(req.body.name,req.body.password,cb);\r
145                         },\r
146                         function(result,cb){\r
147                                 if(result)\r
148                                         collection.RemoveAsync(req.body.name,cb);\r
149                                 else\r
150                                         cb(null,null);\r
151                         }\r
152                 ],function(err,result){\r
153                         if(err != null)\r
154                                 RenderMessage(res,err,req.session.items);\r
155                         else if(result == null)\r
156                                 RenderMessage(res,resource.unmatch_password,req.session.items);\r
157                         else\r
158                                 RenderMessage(res,resource.success_remove,req.session.items);\r
159                 });\r
160         }else if(typeof(req.body.edit) != "undefined"){\r
161                 async.waterfall([\r
162                         function(cb){\r
163                                 if(typeof(req.session.items) != "undefined" && req.session.items.admin)\r
164                                         cb(null,true);\r
165                                 else\r
166                                         collection.AuthAsync(req.body.name,req.body.password,cb);\r
167                         },\r
168                         function(result,cb){\r
169                                 if(result)\r
170                                         collection.GetAsync(req.body.name,cb);\r
171                                 else\r
172                                         cb(null,null);\r
173                         }\r
174                 ],function(err,result){\r
175                         if(err != null){\r
176                                 RenderMessage(res,err,req.session.items);\r
177                         }else if(result != null){\r
178                                 res.setHeader("X-FRAME-OPTIONS","DENY");\r
179                                 res.render("profile/edit",{list:result,token:req.session._csrf,alias:config.alias});\r
180                         }else{\r
181                                 RenderMessage(res,resource.unmatch_password,req.session.items);\r
182                         }\r
183                 });\r
184         }else{\r
185                 RenderMessage(res,resource.invaild_parameter,req.session.items);\r
186         }\r
187 }\r
188 \r
189 function edit_postproc(req, res)\r
190 {\r
191         if(typeof(req.body.name) == "undefined")\r
192         {\r
193                 RenderMessage(res,resource.invaild_parameter,req.session.items);\r
194                 return;\r
195         }else if(typeof(req.body.edit) != "undefined"){\r
196                 var validator = new Validator();\r
197                 if(validator.Validate(req.body,config.alias))\r
198                 {\r
199                         RenderMessage(validator.Message,req.session.items);\r
200                         return;\r
201                 }\r
202                 async.waterfall([\r
203                         function(cb){\r
204                                 if(req.body.updatepassword == false)\r
205                                         collection.UpdatAsync(req.body.name,req.body,null,cb);\r
206                                 else\r
207                                         collection.UpdatAsync(req.body.name,req.body,req.body.password,cb);\r
208                         },\r
209                 ],function(err,result){\r
210                         if(err != null)\r
211                                 RenderMessage(res,err,req.session.items);\r
212                         else\r
213                                 RenderMessage(res,resource.success_edit,req.session.items);\r
214                 });\r
215         }else{\r
216                 RenderMessage(res,resource.invaild_parameter,req.session.items);\r
217         }\r
218 }\r
219 \r
220 function registor_postproc(req, res)\r
221 {\r
222         if(typeof(req.body.registor) != "undefined"){\r
223                 var validator = new Validator();\r
224                 if(validator.Validate(req.body,config.alias))\r
225                 {\r
226                         RenderMessage(res,validator.Message,req.session.items);\r
227                         return;\r
228                 }\r
229                 async.waterfall([\r
230                         function(cb){\r
231                                 collection.AddAsync(req.body,cb);\r
232                         }\r
233                 ],function(err,result){\r
234                         if(err != null)\r
235                                 RenderMessage(res,err,req.session.items);\r
236                         else\r
237                                 RenderMessage(res,resource.success_registor,req.session.items);\r
238                 });\r
239         }else{\r
240                 RenderMessage(resource.invaild_parameter,req.session.items);\r
241         }\r
242 }\r
243 \r
244 function registor_proc(req, res)\r
245 {\r
246         if(typeof(req.session.items) == "undefined")\r
247                 req.session.items = new security.SessionInfomation(false);\r
248 \r
249         res.setHeader("X-FRAME-OPTIONS","DENY");\r
250         res.render("profile/registor",{token:req.session._csrf,alias:config.alias});\r
251 }\r
252 \r
253 function RenderMessage(res,msg,info)\r
254 {\r
255         if(typeof(info) == "undefined" || typeof(info.admin) == "undefined")\r
256                 res.render("profile/message",{message:msg,admin:false});\r
257         else\r
258                 res.render("profile/message",{message:msg,admin:info.admin});\r
259 }\r
260 \r
261 //\r
262 // ProfileCollectionクラス\r
263 //\r
264 function ProfileCollection()\r
265 {\r
266         var MySQLPool = new require("./mysql_pool.js");\r
267         var murmurhash = require("murmurhash");\r
268         var pool = new MySQLPool({\r
269                                 host     : config.db_host,\r
270                                 user     : config.db_user,\r
271                                 password : config.db_password,\r
272                                 port     : config.db_port,\r
273                                 database : "webchat",\r
274                         });\r
275         this.AuthAsync = function(name,password,cb){\r
276                 async.waterfall([\r
277                         function(next){\r
278                                 pool.query("SELECT password FROM list WHERE name_hash = ? and name = ?",[murmurhash.v3(name),name],next);\r
279                         },\r
280                         function(result,next){\r
281                                 if(result[0].password == md5_hex(password))\r
282                                         next(null,true);\r
283                                 else\r
284                                         next(null,false);\r
285                         }\r
286                 ],cb);\r
287         }\r
288         this.GetAsync = function(name,cb){\r
289                 pool.query("SELECT * FROM list WHERE name_hash = ? and name = ?",[murmurhash.v3(name),name],cb);\r
290         }\r
291         this.AddAsync = function(data,cb){\r
292                 var item = GetItem(data);;\r
293                 pool.query("INSERT INTO list SET ?",[item],cb);\r
294         }\r
295         this.UpdatAsync = function(name,data,newpassword,cb){\r
296                 var item = GetItem(data);\r
297                 if(newpassword != null)\r
298                         item.password = md5_hex(newpassword);\r
299                 pool.query("UPDATE list SET ? WHERE name = ?",[item,name],cb);\r
300         }\r
301         this.ClearAsync = function(cb){\r
302                 pool.query("TRUNCATE TABLE list",null,cb);\r
303         }\r
304         this.RemoveRangeAsync = function(names,cb){\r
305                 pool.query("DELETE FROM list WHERE name IN (?)",[names],cb);\r
306         }\r
307         this.RemoveAsync = function(name,cb){\r
308                 pool.query("DELETE FROM list WHERE name_hash = ? and name = ?",[murmurhash.v3(name),name],cb);\r
309         }\r
310         this.FindByNameAsync = function(pattern,start,count,cb){\r
311                 pool.query("SELECT * FROM list WHERE name LIKE ? LIMIT ?,?",[pattern+"%",start,count],cb);\r
312         }\r
313         this.ToArrayAsync = function(start,count,cb){\r
314                 pool.query("SELECT name,lastmodified FROM list LIMIT ?,?",[start,count],cb);\r
315         }\r
316 \r
317         var crypto = require("crypto");\r
318         function md5_hex(src)\r
319         {\r
320                 var md5 = crypto.createHash('md5');\r
321                 md5.update(src, 'utf8');\r
322         return md5.digest('hex');\r
323         }\r
324 \r
325         function GetItem(data)\r
326         {\r
327                 var item = {\r
328                         name_hash:murmurhash.v3(data.name),\r
329                         lastmodified:new Date(),\r
330                 };\r
331                 for(var key in config.alias)\r
332                 {\r
333                         if(key == "password")\r
334                         {\r
335                                 item[key] = md5_hex(data[key]);\r
336                         }\r
337                         else if(config.alias[key].visible_edit)\r
338                         {\r
339                                 if(data[key] == "")\r
340                                         item[key] = config.alias[key].defaultvalue;\r
341                                 else\r
342                                         item[key] = data[key];\r
343                         }\r
344                 }\r
345                 return item;\r
346         }\r
347 }\r
348 \r
349 //\r
350 // Validatorクラス\r
351 //\r
352 function Validator()\r
353 {\r
354         //\r
355         // バリテーションを行う。\r
356         // エラーがあった場合は真。そうでない場合は偽を返す\r
357         //\r
358         // @body バリテーションの対象となる連想配列\r
359         // @alias バリテーションを行う要素のリスト\r
360         this.Validate = function(body,alias){\r
361                 var result = false;\r
362                 this.Message = "";\r
363                 for(var key in alias)\r
364                 {\r
365                         if(alias[key].visible_edit == false)\r
366                                 continue;\r
367                         var message;\r
368                         if(typeof(alias[key].isnotempty) != "undefined" &&\r
369                                 alias[key].isnotempty && body[key] == "")\r
370                                         message = resource.is_not_empty;\r
371                         message = IsValidate(body[key],alias[key].type,alias[key].rule);\r
372                         if(message != null)\r
373                         {\r
374                                 this.Message += "<p>" + alias[key].name + ":" + message + "</p>\n";\r
375                                 result = true;\r
376                         }\r
377                 }\r
378                 return result;\r
379         }\r
380         // バリテーション時にエラーがあった場合、メッセージが記録される\r
381         this.Message = "";\r
382         function IsValidate(data,type,rule){\r
383                 if(typeof(data) == "undefined")\r
384                         throw "data is undefined";\r
385                 if(typeof(type) == "undefined")\r
386                         throw "type is undefined";\r
387 \r
388                 var result = null;\r
389 \r
390                 switch(type)\r
391                 {\r
392                         case "text":\r
393                         case "textarea":\r
394                         case "password":\r
395                                 if(typeof(data) != "string")\r
396                                         result = resource.is_not_string;\r
397                                 break;\r
398                         case "number":\r
399                                 if(data.match(/[^0-9]/g))\r
400                                         result = resource.is_not_number;\r
401                                 break;\r
402                         case "mail":\r
403                                 if(data != "" && !data.match(/^[A-Za-z0-9]+[\w\-\+]+@[\w\.-]+\.\w{2,}$/))\r
404                                         result = resource.is_not_mail;\r
405                                 break;\r
406                 }\r
407 \r
408                 if(typeof(rule) == "function")\r
409                         result = rule(data,type);\r
410 \r
411                 return result;\r
412         }\r
413 }\r