Skip to content

Commit

Permalink
fix: allow non-platform users to exit isPlatformApiUser middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
wanlingt committed Aug 15, 2023
1 parent d725176 commit 96a1bb8
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
45 changes: 35 additions & 10 deletions src/app/modules/auth/auth.middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createLoggerWithLabel } from '../../config/logger'
import { createReqMeta } from '../../utils/request'
import { ControllerHandler } from '../core/core.types'
import { UNAUTHORIZED_USER_MESSAGE } from '../user/user.constant'
import { getPopulatedApiUserById } from '../user/user.service'
import * as UserService from '../user/user.service'

import { getUserByApiKey } from './auth.service'
import {
Expand Down Expand Up @@ -187,26 +187,51 @@ export const authenticateApiKey: ControllerHandler = (req, res, next) => {
}

/**
* Middleware that only allows users with a valid bearer token and isPlatform flag to pass through to the next handler
* Middleware that checks if user is a platform user
*/
const isPlatformApiUser: ControllerHandler = (req, res, next) => {
const isPlatformApiUser: ControllerHandler<
unknown,
unknown,
{ userEmail: string }
> = (req, res, next) => {
const { userEmail } = req.body
const sessionUserId = getUserIdFromSession(req.session)
if (!sessionUserId) {
return res.status(StatusCodes.UNAUTHORIZED).json(UNAUTHORIZED_USER_MESSAGE)
}
return getPopulatedApiUserById(sessionUserId)
return UserService.getPopulatedApiUserById(sessionUserId)
.map((retrievedUser) => {
if (!retrievedUser) {
return res
.status(StatusCodes.UNAUTHORIZED)
.json(UNAUTHORIZED_USER_MESSAGE)
}
if (!retrievedUser.apiToken?.isPlatform) {
return res
.status(StatusCodes.UNAUTHORIZED)
.json({ message: 'User is not a platform' })
if (!retrievedUser.apiToken?.isPlatform || !userEmail) {
// Exit this middleware if
// 1. User is not a platform
// 2. User is a platform but has no userEmail provided
return next()
} else {
return UserService.findUserByEmail(userEmail).map((emailUser) => {
if (!emailUser) {
return res
.status(StatusCodes.UNPROCESSABLE_ENTITY)
.json('User not found')
}
logger.info({
message: 'API user is a platform',
meta: {
action: 'isPlatformApiUser',
...createReqMeta(req),
reqBody: req.body,
apiUser: sessionUserId,
userEmail,
},
})
req.session.user = { _id: emailUser._id }
return next()
})
}
return next()
})
.mapErr((error) => {
logger.error({
Expand All @@ -223,7 +248,7 @@ const isPlatformApiUser: ControllerHandler = (req, res, next) => {
})
}

export const authenticateApiKeyPlatformUser = [
export const authenticateApiKeyAndPlatform = [
authenticateApiKey,
isPlatformApiUser,
] as ControllerHandler[]
6 changes: 4 additions & 2 deletions src/app/modules/form/admin-form/admin-form.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,7 @@ export const _handleUpdateWebhookSettings: ControllerHandler<
> = (req, res) => {
const { formId } = req.params
const { userEmail, webhook: webhookSettings } = req.body
const authedUserId = (req.session as AuthedSessionData).user._id

logger.info({
message: 'User attempting to update webhook settings',
Expand All @@ -1323,7 +1324,7 @@ export const _handleUpdateWebhookSettings: ControllerHandler<
})

// Step 1: Retrieve currently logged in user.
return UserService.findUserByEmail(userEmail)
return UserService.findUserById(authedUserId)
.andThen((user) =>
// Step 2: Retrieve form with write permission check.
AuthService.getFormAfterPermissionChecks({
Expand Down Expand Up @@ -1516,6 +1517,7 @@ export const _handleGetWebhookSettings: ControllerHandler<
> = (req, res) => {
const { formId } = req.params
const { userEmail } = req.body
const authedUserId = (req.session as AuthedSessionData).user._id

logger.info({
message: 'User attempting to get webhook settings',
Expand All @@ -1528,7 +1530,7 @@ export const _handleGetWebhookSettings: ControllerHandler<
},
})

return UserService.findUserByEmail(userEmail)
return UserService.findUserById(authedUserId)
.andThen((user) =>
// Retrieve form for settings as well as for permissions checking
FormService.retrieveFullFormById(formId).map((form) => ({
Expand Down
4 changes: 2 additions & 2 deletions src/app/modules/form/admin-form/admin-form.middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const updateSettingsValidator = celebrate({
*/
export const updateWebhookSettingsValidator = celebrate({
[Segments.BODY]: Joi.object<WebhookSettingsUpdateDto>({
userEmail: Joi.string().email().required(),
userEmail: Joi.string().email().optional(),
webhook: webhookSettingsValidator,
}),
})
Expand All @@ -57,6 +57,6 @@ export const updateWebhookSettingsValidator = celebrate({
*/
export const getWebhookSettingsValidator = celebrate({
[Segments.BODY]: Joi.object<{ userEmail: string }>({
userEmail: Joi.string().email().required(),
userEmail: Joi.string().email().optional(),
}),
})

0 comments on commit 96a1bb8

Please sign in to comment.