admin.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. module.exports = function(crowi, app) {
  2. 'use strict';
  3. var debug = require('debug')('crowi:routes:admin')
  4. , models = crowi.models
  5. , Page = models.Page
  6. , User = models.User
  7. , Config = models.Config
  8. , MAX_PAGE_LIST = 5
  9. , actions = {};
  10. function createPager(currentPage, pageCount, itemCount, maxPageList) {
  11. var pager = {};
  12. pager.currentPage = currentPage;
  13. pager.pageCount = pageCount;
  14. pager.itemCount = itemCount;
  15. pager.previous = null;
  16. if (currentPage > 1) {
  17. pager.previous = currentPage - 1;
  18. }
  19. pager.next = null;
  20. if (currentPage < pageCount) {
  21. pager.next = currentPage + 1;
  22. }
  23. pager.pages = [];
  24. var pagerMin = Math.max(1, Math.ceil(currentPage - maxPageList/2));
  25. var pagerMax = Math.min(pageCount, Math.floor(currentPage + maxPageList/2));
  26. if (pagerMin == 1) {
  27. if (MAX_PAGE_LIST < pageCount) {
  28. pagerMax = MAX_PAGE_LIST;
  29. } else {
  30. pagerMax = pageCount;
  31. }
  32. }
  33. if (pagerMax == pageCount) {
  34. if ((pagerMax - MAX_PAGE_LIST) < 1) {
  35. pagerMin = 1;
  36. } else {
  37. pagerMin = pagerMax - MAX_PAGE_LIST;
  38. }
  39. }
  40. pager.previousDots = null;
  41. if (pagerMin > 1) {
  42. pager.previousDots = true;
  43. }
  44. pager.nextDots = null;
  45. if (pagerMax < pageCount) {
  46. pager.nextDots = true;
  47. }
  48. for (var i = pagerMin;
  49. i <= pagerMax;
  50. i++) {
  51. pager.pages.push(i);
  52. }
  53. return pager;
  54. }
  55. actions.index = function(req, res) {
  56. return res.render('admin/index');
  57. };
  58. actions.app = {};
  59. actions.app.index = function(req, res) {
  60. var settingForm;
  61. settingForm = Config.setupCofigFormData('crowi', req.config);
  62. return res.render('admin/app', {
  63. settingForm: settingForm,
  64. });
  65. };
  66. actions.app.settingUpdate = function(req, res) {
  67. };
  68. // app.get('/admin/notification' , admin.notification.index);
  69. actions.notification = {};
  70. actions.notification.index = function(req, res) {
  71. var config = crowi.getConfig();
  72. var slackSetting = Config.setupCofigFormData('notification', config);
  73. var hasSlackConfig = Config.hasSlackConfig(config);
  74. var hasSlackToken = Config.hasSlackToken(config);
  75. var slack = crowi.slack;
  76. var slackAuthUrl = '';
  77. if (!Config.hasSlackConfig(req.config)) {
  78. slackSetting['slack:clientId'] = '';
  79. slackSetting['slack:clientSecret'] = '';
  80. } else {
  81. slackAuthUrl = slack.getAuthorizeURL();
  82. }
  83. if (req.session.slackSetting) {
  84. slackSetting = req.session.slackSetting;
  85. req.session.slackSetting = null;
  86. }
  87. return res.render('admin/notification', {
  88. slackSetting,
  89. hasSlackConfig,
  90. hasSlackToken,
  91. slackAuthUrl
  92. });
  93. };
  94. // app.post('/admin/notification/slackSetting' , admin.notification.slackauth);
  95. actions.notification.slackSetting = function(req, res) {
  96. var slackSetting = req.form.slackSetting;
  97. req.session.slackSetting = slackSetting;
  98. if (req.form.isValid) {
  99. Config.updateNamespaceByArray('notification', slackSetting, function(err, config) {
  100. Config.updateConfigCache('notification', config);
  101. req.session.slackSetting = null;
  102. crowi.setupSlack().then(function() {
  103. return res.redirect('/admin/notification');
  104. });
  105. });
  106. } else {
  107. req.flash('errorMessage', req.form.errors);
  108. return res.redirect('/admin/notification');
  109. }
  110. };
  111. // app.get('/admin/notification/slackAuth' , admin.notification.slackauth);
  112. actions.notification.slackAuth = function(req, res) {
  113. var code = req.query.code;
  114. var config = crowi.getConfig();
  115. if (!code || !Config.hasSlackConfig(req.config)) {
  116. return res.redirect('/admin/notification');
  117. }
  118. var slack = crowi.slack;
  119. var bot = slack.createBot();
  120. bot.api.oauth.access({code}, function(err, data) {
  121. debug('oauth response', err, data);
  122. if (!data.ok || !data.access_token) {
  123. req.flash('errorMessage', ['Failed to fetch access_token. Please do connect again.']);
  124. return res.redirect('/admin/notification');
  125. } else {
  126. Config.updateNamespaceByArray('notification', {'slack:token': data.access_token}, function(err, config) {
  127. if (err) {
  128. req.flash('errorMessage', ['Failed to save access_token. Please try again.']);
  129. } else {
  130. Config.updateConfigCache('notification', config);
  131. req.flash('successMessage', ['Successfully Connected!']);
  132. }
  133. slack.createBot();
  134. return res.redirect('/admin/notification');
  135. });
  136. }
  137. });
  138. };
  139. actions.user = {};
  140. actions.user.index = function(req, res) {
  141. var page = parseInt(req.query.page) || 1;
  142. User.findUsersWithPagination({page: page}, function(err, users, pageCount, itemCount) {
  143. var pager = createPager(page, pageCount, itemCount, MAX_PAGE_LIST);
  144. return res.render('admin/users', {
  145. users: users,
  146. pager: pager
  147. });
  148. });
  149. };
  150. actions.user.invite = function(req, res) {
  151. var form = req.form.inviteForm;
  152. var toSendEmail = form.sendEmail || false;
  153. if (req.form.isValid) {
  154. User.createUsersByInvitation(form.emailList.split('\n'), toSendEmail, function(err, userList) {
  155. if (err) {
  156. req.flash('errorMessage', req.form.errors.join('\n'));
  157. } else {
  158. req.flash('createdUser', userList);
  159. }
  160. return res.redirect('/admin/users');
  161. });
  162. } else {
  163. req.flash('errorMessage', req.form.errors.join('\n'));
  164. return res.redirect('/admin/users');
  165. }
  166. };
  167. actions.user.makeAdmin = function(req, res) {
  168. var id = req.params.id;
  169. User.findById(id, function(err, userData) {
  170. userData.makeAdmin(function(err, userData) {
  171. if (err === null) {
  172. req.flash('successMessage', userData.name + 'さんのアカウントを管理者に設定しました。');
  173. } else {
  174. req.flash('errorMessage', '更新に失敗しました。');
  175. debug(err, userData);
  176. }
  177. return res.redirect('/admin/users');
  178. });
  179. });
  180. };
  181. actions.user.removeFromAdmin = function(req, res) {
  182. var id = req.params.id;
  183. User.findById(id, function(err, userData) {
  184. userData.removeFromAdmin(function(err, userData) {
  185. if (err === null) {
  186. req.flash('successMessage', userData.name + 'さんのアカウントを管理者から外しました。');
  187. } else {
  188. req.flash('errorMessage', '更新に失敗しました。');
  189. debug(err, userData);
  190. }
  191. return res.redirect('/admin/users');
  192. });
  193. });
  194. };
  195. actions.user.activate = function(req, res) {
  196. var id = req.params.id;
  197. User.findById(id, function(err, userData) {
  198. userData.statusActivate(function(err, userData) {
  199. if (err === null) {
  200. req.flash('successMessage', userData.name + 'さんのアカウントを承認しました');
  201. } else {
  202. req.flash('errorMessage', '更新に失敗しました。');
  203. debug(err, userData);
  204. }
  205. return res.redirect('/admin/users');
  206. });
  207. });
  208. };
  209. actions.user.suspend = function(req, res) {
  210. var id = req.params.id;
  211. User.findById(id, function(err, userData) {
  212. userData.statusSuspend(function(err, userData) {
  213. if (err === null) {
  214. req.flash('successMessage', userData.name + 'さんのアカウントを利用停止にしました');
  215. } else {
  216. req.flash('errorMessage', '更新に失敗しました。');
  217. debug(err, userData);
  218. }
  219. return res.redirect('/admin/users');
  220. });
  221. });
  222. };
  223. actions.user.remove= function(req, res) {
  224. // 未実装
  225. return res.redirect('/admin/users');
  226. };
  227. actions.user.removeCompletely = function(req, res) {
  228. // ユーザーの物理削除
  229. var id = req.params.id;
  230. User.removeCompletelyById(id, function(err, removed) {
  231. if (err) {
  232. debug('Error while removing user.', err, id);
  233. req.flash('errorMessage', '完全な削除に失敗しました。');
  234. } else {
  235. req.flash('successMessage', '削除しました');
  236. }
  237. return res.redirect('/admin/users');
  238. });
  239. };
  240. actions.slackauth = function(req, res) {
  241. //debug(req.query.code);
  242. //var Botkit = require('botkit');
  243. //var controller = Botkit.slackbot({debug: true});
  244. //var config = crowi.getConfig();
  245. //controller.configureSlackApp({
  246. // clientId: '2462768682.25922619424',
  247. // clientSecret: '2bbbc1c5d355e128ffd009a5d57629b9',
  248. // redirectUri: config.crowi['app:url'] + '/slackauth',
  249. // scopes: ['chat:write:bot']
  250. //});
  251. //var bot = controller.spawn();
  252. //bot.api.oauth.access({code: req.query.code}, function (err, response) {
  253. // debug(err, response);
  254. //});
  255. //var accessToken = 'xoxp-2462768682-2462768686-25940861495-3e4cc9168a';
  256. //var accessToken = 'xoxp-2462768682-2462768686-26103706022-46943fb5ec';
  257. //
  258. // access_token: '',
  259. // scope: 'identify,chat:write:bot',
  260. // team_name: '',
  261. // team_id: '' }
  262. //var bot = controller.spawn({token: accessToken});
  263. //bot.api.chat.postMessage({
  264. // channel: '#xtest2',
  265. // username: 'Crowi',
  266. // text: '/hoge/fuga/piyo is updated.',
  267. // attachments: [
  268. // {
  269. // color: '#263a3c',
  270. // author_name: '@sotarok',
  271. // author_link: 'http://localhost:3000/user/sotarok',
  272. // author_icon: 'https://crowi-strk-dev.s3.amazonaws.com/user/56c9dbf860ab5bc62647d84a.png',
  273. // title: "/hoge/fuga/piyo",
  274. // title_link: "http://localhost:3000/hoge/fuga/piyo",
  275. // text: '*# sotarok*\n\nshellに続き、初心者が頑張って理解していくノート的記事です。\nGitHubが常識と化してきた今日この頃、チャレンジしてみたものの、そもそもGitってなんなのかわからないと使いこなせない、っていうか挫折すると思います。私はしました。\nなので、起き上がってまずGitについて本当に一から理解を試みました。\n\n***\n \n*## Gitって何?*\n\nGitとは、**[バージョン管理システム](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)**のひとつです。\n バージョン管理‥? :open_mouth: \nバージョンすなわち変更履歴の管理です。\n\n例えばなにかファイルの書き換えをするとき、元データを失わないためにどのような工夫をするでしょうか。ほとんどの場合、保存用にコピーを作成しておくというのが定番の方法だと思います。\nですが、誰しもこんな経験があるのでは。\n\n - 元データの保管が面倒\n - \'meeting_3月.txt\'、\'meeting_最新.txt\'といった名前のデータが複数できてしまう\n - チームで触っていて、最後に書き換えたのが誰なのかわからない\n - 先輩も同時に編集していたのに、知らずにタッチの差で上書きしてしまった\n - 書き換えたよ~と言われても(あるいは自分でも)、どこを換えたかわからない\n - 何回か前の更新状態の方が良かった、戻したい…\n \n ある~~~!!\n こんな事態を解消してくれるのが**Gitというバージョン管理システム**です。',
  276. // mrkdwn_in: ["text"],
  277. // },
  278. // ],
  279. //});
  280. //var code = req.query.);
  281. res.render('admin/slackauth', {});
  282. };
  283. actions.api = {};
  284. actions.api.appSetting = function(req, res) {
  285. var form = req.form.settingForm;
  286. if (req.form.isValid) {
  287. debug('form content', form);
  288. // mail setting ならここで validation
  289. if (form['mail:from']) {
  290. validateMailSetting(req, form, function(err, data) {
  291. debug('Error validate mail setting: ', err, data);
  292. if (err) {
  293. req.form.errors.push('SMTPを利用したテストメール送信に失敗しました。設定をみなおしてください。');
  294. return res.json({status: false, message: req.form.errors.join('\n')});
  295. }
  296. return saveSetting(req, res, form);
  297. });
  298. } else {
  299. return saveSetting(req, res, form);
  300. }
  301. } else {
  302. return res.json({status: false, message: req.form.errors.join('\n')});
  303. }
  304. };
  305. // app.post('/_api/admin/notifications.add' , admin.api.notificationAdd);
  306. actions.api.notificationAdd = function(req, res) {
  307. };
  308. // app.post('/_api/admin/notifications.remove' , admin.api.notificationRemove);
  309. actions.api.notificationRemove = function(req, res) {
  310. };
  311. function saveSetting(req, res, form)
  312. {
  313. Config.updateNamespaceByArray('crowi', form, function(err, config) {
  314. Config.updateConfigCache('crowi', config);
  315. return res.json({status: true});
  316. });
  317. }
  318. function validateMailSetting(req, form, callback)
  319. {
  320. var mailer = crowi.mailer;
  321. var option = {
  322. host: form['mail:smtpHost'],
  323. port: form['mail:smtpPort'],
  324. };
  325. if (form['mail:smtpUser'] && form['mail:smtpPassword']) {
  326. option.auth = {
  327. user: form['mail:smtpUser'],
  328. pass: form['mail:smtpPassword'],
  329. };
  330. }
  331. if (option.port === 465) {
  332. option.secure = true;
  333. }
  334. var smtpClient = mailer.createSMTPClient(option);
  335. debug('mailer setup for validate SMTP setting', smtpClient);
  336. smtpClient.sendMail({
  337. to: req.user.email,
  338. subject: 'Wiki管理設定のアップデートによるメール通知',
  339. text: 'このメールは、WikiのSMTP設定のアップデートにより送信されています。'
  340. }, callback);
  341. }
  342. return actions;
  343. };