176 lines
4.3 KiB
JavaScript
176 lines
4.3 KiB
JavaScript
class ApiRoutes
|
|
{
|
|
static create = container => new this(container.Logger, container.NotificationFacade, container.Config);
|
|
|
|
|
|
constructor(logger, notificationFacade, config)
|
|
{
|
|
this.logger = logger;
|
|
this.notificationFacade = notificationFacade;
|
|
this.authToken = config.authToken;
|
|
this.allowedIps = config.allowedIps;
|
|
}
|
|
|
|
|
|
createRouter(express)
|
|
{
|
|
const router = express.Router();
|
|
|
|
router.post('/notification', this._wrapAsyncHandler(this._handlePostNotification));
|
|
router.get('/notification/latched', this._wrapAsyncHandler(this._handleLatchedNotifications));
|
|
router.post('/notification/:token/reset', this._wrapAsyncHandler(this._handleResetNotification));
|
|
router.post('/notification/:token/reminders/enable', this._wrapAsyncHandler(this._handleEnableReminders));
|
|
router.post('/notification/:token/reminders/disable', this._wrapAsyncHandler(this._handleDisableReminders));
|
|
router.get('/ip', this._handleIp.bind(this));
|
|
|
|
return router;
|
|
}
|
|
|
|
|
|
async _handlePostNotification(req, res)
|
|
{
|
|
if (!this._isIpAllowed(req, this.allowedIps.post))
|
|
{
|
|
this._logRequestWarning(req, 'IP address not in allowedIps.post');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
if (req.headers.authorization !== 'Bearer ' + this.authToken)
|
|
{
|
|
this._logRequestWarning(req, 'Missing or invalid authorization header');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
if (!req.body || !req.body.subject || !req.body.message)
|
|
{
|
|
this._logRequestWarning(req, 'Missing body, subject and/or message parameters');
|
|
res.sendStatus(400);
|
|
return;
|
|
}
|
|
|
|
await this.notificationFacade.postNotification(req.body.subject, req.body.message, req.body.priority || 0);
|
|
res.sendStatus(200);
|
|
}
|
|
|
|
|
|
async _handleResetNotification(req, res)
|
|
{
|
|
if (!this._isIpAllowed(req, this.allowedIps.manage))
|
|
{
|
|
this._logRequestWarning(req, 'IP address not in allowedIps.manage');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
await this.notificationFacade.resetNotification(req.params.token);
|
|
res.sendStatus(200);
|
|
}
|
|
|
|
|
|
async _handleEnableReminders(req, res)
|
|
{
|
|
if (!this._isIpAllowed(req, this.allowedIps.manage))
|
|
{
|
|
this._logRequestWarning(req, 'IP address not in allowedIps.manage');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
await this.notificationFacade.setReminders(req.params.token, true);
|
|
res.sendStatus(200);
|
|
}
|
|
|
|
|
|
async _handleDisableReminders(req, res)
|
|
{
|
|
if (!this._isIpAllowed(req, this.allowedIps.manage))
|
|
{
|
|
this._logRequestWarning(req, 'IP address not in allowedIps.manage');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
await this.notificationFacade.setReminders(req.params.token, false);
|
|
res.sendStatus(200);
|
|
}
|
|
|
|
|
|
async _handleLatchedNotifications(req, res)
|
|
{
|
|
if (!this._isIpAllowed(req, this.allowedIps.manage))
|
|
{
|
|
this._logRequestWarning(req, 'IP address not in allowedIps.manage');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer '))
|
|
{
|
|
this._logRequestWarning(req, 'Missing or invalid authorization header');
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
const token = req.headers.authorization.substr(7);
|
|
const notifications = this.notificationFacade.getLatchedNotifications(token);
|
|
|
|
if (notifications == null)
|
|
{
|
|
this._logRequestWarning(req, `Invalid token: ${token}`);
|
|
res.sendStatus(401);
|
|
return;
|
|
}
|
|
|
|
res.send(JSON.stringify(notifications));
|
|
}
|
|
|
|
|
|
_handleIp(req, res)
|
|
{
|
|
res.send(this._getIp(req));
|
|
}
|
|
|
|
|
|
_wrapAsyncHandler(handler)
|
|
{
|
|
const boundHandler = handler.bind(this);
|
|
|
|
return async (req, res) =>
|
|
{
|
|
try
|
|
{
|
|
await boundHandler(req, res);
|
|
}
|
|
catch (err)
|
|
{
|
|
this.logger.error(`Unhandled exception in request handler: ${err}`);
|
|
this.logger.verbose(err.stack);
|
|
res.sendStatus(500);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
_logRequestWarning(req, message)
|
|
{
|
|
const ip = this._getIp(req);
|
|
this.logger.warn(`[${ip}] ${message}`);
|
|
}
|
|
|
|
|
|
_isIpAllowed(req, whitelist)
|
|
{
|
|
return whitelist === null || whitelist.includes(this._getIp(req));
|
|
}
|
|
|
|
|
|
_getIp(req)
|
|
{
|
|
return req.headers['x-forwarded-for'] || req.ip;
|
|
}
|
|
}
|
|
|
|
|
|
module.exports = ApiRoutes; |