| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- const loggerFactory = require('@alias/logger');
- // eslint-disable-next-line no-unused-vars
- const logger = loggerFactory('growi:routes:apiv3:notification-setting');
- const express = require('express');
- const router = express.Router();
- const { body } = require('express-validator');
- const ErrorV3 = require('../../models/vo/error-apiv3');
- const removeNullPropertyFromObject = require('../../../lib/util/removeNullPropertyFromObject');
- const validator = {
- slackConfiguration: [
- body('webhookUrl').if(value => value != null).isString().trim(),
- body('isIncomingWebhookPrioritized').isBoolean(),
- body('slackToken').if(value => value != null).isString().trim(),
- ],
- userNotification: [
- body('pathPattern').isString().trim(),
- body('channel').isString().trim(),
- ],
- globalNotification: [
- body('triggerPath').isString().trim().not()
- .isEmpty(),
- body('notifyToType').isString().trim().isIn(['mail', 'slack']),
- body('toEmail').trim().custom((value, { req }) => {
- return (req.body.notifyToType === 'mail') ? (!!value && value.match(/.+@.+\..+/)) : true;
- }),
- body('slackChannels').trim().custom((value, { req }) => {
- return (req.body.notifyToType === 'slack') ? !!value : true;
- }),
- ],
- notifyForPageGrant: [
- body('isNotificationForOwnerPageEnabled').if(value => value != null).isBoolean(),
- body('isNotificationForGroupPageEnabled').if(value => value != null).isBoolean(),
- ],
- };
- /**
- * @swagger
- * tags:
- * name: NotificationSetting
- */
- /**
- * @swagger
- *
- * components:
- * schemas:
- * SlackConfigurationParams:
- * type: object
- * properties:
- * webhookUrl:
- * type: string
- * description: incoming webhooks url
- * isIncomingWebhookPrioritized:
- * type: boolean
- * description: use incoming webhooks even if Slack App settings are enabled
- * slackToken:
- * type: string
- * description: OAuth access token
- * UserNotificationParams:
- * type: object
- * properties:
- * pathPattern:
- * type: string
- * description: path name of wiki
- * channel:
- * type: string
- * description: slack channel name without '#'
- * NotifyForPageGrant:
- * type: object
- * properties:
- * isNotificationForOwnerPageEnabled:
- * type: string
- * description: Whether to notify on owner page
- * isNotificationForGroupPageEnabled:
- * type: string
- * description: Whether to notify on group page
- * GlobalNotificationParams:
- * type: object
- * properties:
- * notifyToType:
- * type: string
- * description: What is type for notify
- * toEmail:
- * type: string
- * description: email for notify
- * slackChannels:
- * type: string
- * description: channels for notify
- * triggerPath:
- * type: string
- * description: trigger path for notify
- * triggerEvents:
- * type: array
- * items:
- * type: string
- * description: trigger events for notify
- */
- module.exports = (crowi) => {
- const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
- const adminRequired = require('../../middlewares/admin-required')(crowi);
- const csrf = require('../../middlewares/csrf')(crowi);
- const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
- const UpdatePost = crowi.model('UpdatePost');
- const GlobalNotificationSetting = crowi.model('GlobalNotificationSetting');
- const GlobalNotificationMailSetting = crowi.models.GlobalNotificationMailSetting;
- const GlobalNotificationSlackSetting = crowi.models.GlobalNotificationSlackSetting;
- /**
- * @swagger
- *
- * /notification-setting/:
- * get:
- * tags: [NotificationSetting]
- * description: Get notification paramators
- * responses:
- * 200:
- * description: params of notification
- * content:
- * application/json:
- * schema:
- * properties:
- * notificationParams:
- * type: object
- * description: notification params
- */
- router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
- const notificationParams = {
- webhookUrl: await crowi.configManager.getConfig('notification', 'slack:incomingWebhookUrl'),
- isIncomingWebhookPrioritized: await crowi.configManager.getConfig('notification', 'slack:isIncomingWebhookPrioritized'),
- slackToken: await crowi.configManager.getConfig('notification', 'slack:token'),
- userNotifications: await UpdatePost.findAll(),
- isNotificationForOwnerPageEnabled: await crowi.configManager.getConfig('notification', 'notification:owner-page:isEnabled'),
- isNotificationForGroupPageEnabled: await crowi.configManager.getConfig('notification', 'notification:group-page:isEnabled'),
- globalNotifications: await GlobalNotificationSetting.findAll(),
- };
- return res.apiv3({ notificationParams });
- });
- /**
- * @swagger
- *
- * /notification-setting/slack-configuration:
- * put:
- * tags: [NotificationSetting]
- * description: Update slack configuration setting
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/SlackConfigurationParams'
- * responses:
- * 200:
- * description: Succeeded to update slack configuration setting
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/SlackConfigurationParams'
- */
- router.put('/slack-configuration', loginRequiredStrictly, adminRequired, csrf, validator.slackConfiguration, apiV3FormValidator, async(req, res) => {
- const requestParams = {
- 'slack:incomingWebhookUrl': req.body.webhookUrl,
- 'slack:isIncomingWebhookPrioritized': req.body.isIncomingWebhookPrioritized,
- 'slack:token': req.body.slackToken,
- };
- try {
- await crowi.configManager.updateConfigsInTheSameNamespace('notification', requestParams);
- const responseParams = {
- webhookUrl: await crowi.configManager.getConfig('notification', 'slack:incomingWebhookUrl'),
- isIncomingWebhookPrioritized: await crowi.configManager.getConfig('notification', 'slack:isIncomingWebhookPrioritized'),
- slackToken: await crowi.configManager.getConfig('notification', 'slack:token'),
- };
- await crowi.setupSlack();
- return res.apiv3({ responseParams });
- }
- catch (err) {
- const msg = 'Error occurred in updating slack configuration';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'update-slackConfiguration-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/user-notification:
- * post:
- * tags: [NotificationSetting]
- * description: add user notification setting
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/UserNotificationParams'
- * responses:
- * 200:
- * description: Succeeded to add user notification setting
- * content:
- * application/json:
- * schema:
- * properties:
- * createdUser:
- * type: object
- * description: user who set notification
- * userNotifications:
- * type: object
- * description: user trigger notifications for updated
- */
- router.post('/user-notification', loginRequiredStrictly, adminRequired, csrf, validator.userNotification, apiV3FormValidator, async(req, res) => {
- const { pathPattern, channel } = req.body;
- const UpdatePost = crowi.model('UpdatePost');
- try {
- logger.info('notification.add', pathPattern, channel);
- const responseParams = {
- createdUser: await UpdatePost.create(pathPattern, channel, req.user),
- userNotifications: await UpdatePost.findAll(),
- };
- return res.apiv3({ responseParams });
- }
- catch (err) {
- const msg = 'Error occurred in updating user notification';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'update-userNotification-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/user-notification/{id}:
- * delete:
- * tags: [NotificationSetting]
- * description: delete user trigger notification pattern
- * parameters:
- * - name: id
- * in: path
- * required: true
- * description: id of user trigger notification
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Succeeded to delete user trigger notification pattern
- * content:
- * application/json:
- * schema:
- * properties:
- * deletedNotificaton:
- * type: object
- * description: deleted notification
- */
- router.delete('/user-notification/:id', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
- const { id } = req.params;
- try {
- const deletedNotificaton = await UpdatePost.remove(id);
- return res.apiv3(deletedNotificaton);
- }
- catch (err) {
- const msg = 'Error occurred in delete user trigger notification';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'delete-userTriggerNotification-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/global-notification:
- * post:
- * tags: [NotificationSetting]
- * description: add global notification
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/GlobalNotificationParams'
- * responses:
- * 200:
- * description: Succeeded to add global notification
- * content:
- * application/json:
- * schema:
- * properties:
- * createdNotification:
- * type: object
- * description: notification param created
- */
- router.post('/global-notification', loginRequiredStrictly, adminRequired, csrf, validator.globalNotification, apiV3FormValidator, async(req, res) => {
- const {
- notifyToType, toEmail, slackChannels, triggerPath, triggerEvents,
- } = req.body;
- let notification;
- if (notifyToType === GlobalNotificationSetting.TYPE.MAIL) {
- notification = new GlobalNotificationMailSetting(crowi);
- notification.toEmail = toEmail;
- }
- if (notifyToType === GlobalNotificationSetting.TYPE.SLACK) {
- notification = new GlobalNotificationSlackSetting(crowi);
- notification.slackChannels = slackChannels;
- }
- notification.triggerPath = triggerPath;
- notification.triggerEvents = triggerEvents || [];
- try {
- const createdNotification = await notification.save();
- return res.apiv3({ createdNotification });
- }
- catch (err) {
- const msg = 'Error occurred in updating global notification';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'post-globalNotification-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/global-notification/{id}:
- * put:
- * tags: [NotificationSetting]
- * description: update global notification
- * parameters:
- * - name: id
- * in: path
- * required: true
- * description: global notification id for updated
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/GlobalNotificationParams'
- * responses:
- * 200:
- * description: Succeeded to update global notification
- * content:
- * application/json:
- * schema:
- * properties:
- * createdNotification:
- * type: object
- * description: notification param updated
- */
- router.put('/global-notification/:id', loginRequiredStrictly, adminRequired, csrf, validator.globalNotification, apiV3FormValidator, async(req, res) => {
- const { id } = req.params;
- const {
- notifyToType, toEmail, slackChannels, triggerPath, triggerEvents,
- } = req.body;
- const models = {
- [GlobalNotificationSetting.TYPE.MAIL]: GlobalNotificationMailSetting,
- [GlobalNotificationSetting.TYPE.SLACK]: GlobalNotificationSlackSetting,
- };
- try {
- let setting = await GlobalNotificationSetting.findOne({ _id: id });
- setting = setting.toObject();
- // when switching from one type to another,
- // remove toEmail from slack setting and slackChannels from mail setting
- if (setting.__t !== notifyToType) {
- setting = models[setting.__t].hydrate(setting);
- setting.toEmail = undefined;
- setting.slackChannels = undefined;
- await setting.save();
- setting = setting.toObject();
- }
- if (notifyToType === GlobalNotificationSetting.TYPE.MAIL) {
- setting = GlobalNotificationMailSetting.hydrate(setting);
- setting.toEmail = toEmail;
- }
- if (notifyToType === GlobalNotificationSetting.TYPE.SLACK) {
- setting = GlobalNotificationSlackSetting.hydrate(setting);
- setting.slackChannels = slackChannels;
- }
- setting.__t = notifyToType;
- setting.triggerPath = triggerPath;
- setting.triggerEvents = triggerEvents || [];
- const createdNotification = await setting.save();
- return res.apiv3({ createdNotification });
- }
- catch (err) {
- const msg = 'Error occurred in updating global notification';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'post-globalNotification-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/notify-for-page-grant:
- * put:
- * tags: [NotificationSetting]
- * description: Update settings for notify for page grant
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/NotifyForPageGrant'
- * responses:
- * 200:
- * description: Succeeded to settings for notify for page grant
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/NotifyForPageGrant'
- */
- router.put('/notify-for-page-grant', loginRequiredStrictly, adminRequired, csrf, validator.notifyForPageGrant, apiV3FormValidator, async(req, res) => {
- let requestParams = {
- 'notification:owner-page:isEnabled': req.body.isNotificationForOwnerPageEnabled,
- 'notification:group-page:isEnabled': req.body.isNotificationForGroupPageEnabled,
- };
- requestParams = removeNullPropertyFromObject(requestParams);
- try {
- await crowi.configManager.updateConfigsInTheSameNamespace('notification', requestParams);
- const responseParams = {
- isNotificationForOwnerPageEnabled: await crowi.configManager.getConfig('notification', 'notification:owner-page:isEnabled'),
- isNotificationForGroupPageEnabled: await crowi.configManager.getConfig('notification', 'notification:group-page:isEnabled'),
- };
- return res.apiv3({ responseParams });
- }
- catch (err) {
- const msg = 'Error occurred in updating notify for page grant';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'update-notify-for-page-grant-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/global-notification/{id}/enabled:
- * put:
- * tags: [NotificationSetting]
- * description: toggle enabled global notification
- * parameters:
- * - name: id
- * in: path
- * required: true
- * description: notification id for updated
- * schema:
- * type: string
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * properties:
- * isEnabled:
- * type: boolean
- * description: is notification enabled
- * responses:
- * 200:
- * description: Succeeded to delete global notification pattern
- * content:
- * application/json:
- * schema:
- * properties:
- * deletedNotificaton:
- * type: object
- * description: notification id for updated
- */
- router.put('/global-notification/:id/enabled', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
- const { id } = req.params;
- const { isEnabled } = req.body;
- try {
- if (isEnabled) {
- await GlobalNotificationSetting.enable(id);
- }
- else {
- await GlobalNotificationSetting.disable(id);
- }
- return res.apiv3({ id });
- }
- catch (err) {
- const msg = 'Error occurred in toggle of global notification';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'toggle-globalNotification-failed'));
- }
- });
- /**
- * @swagger
- *
- * /notification-setting/global-notification/{id}:
- * delete:
- * tags: [NotificationSetting]
- * description: delete global notification pattern
- * parameters:
- * - name: id
- * in: path
- * required: true
- * description: id of global notification
- * schema:
- * type: string
- * responses:
- * 200:
- * description: Succeeded to delete global notification pattern
- * content:
- * application/json:
- * schema:
- * properties:
- * deletedNotificaton:
- * type: object
- * description: deleted notification
- */
- router.delete('/global-notification/:id', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
- const { id } = req.params;
- try {
- const deletedNotificaton = await GlobalNotificationSetting.findOneAndRemove({ _id: id });
- return res.apiv3(deletedNotificaton);
- }
- catch (err) {
- const msg = 'Error occurred in delete global notification';
- logger.error('Error', err);
- return res.apiv3Err(new ErrorV3(msg, 'delete-globalNotification-failed'));
- }
- });
- return router;
- };
|