diff --git a/backend/src/app.ts b/backend/src/app.ts index 1d5432f1a..34ed89997 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -40,6 +40,7 @@ import { secret as v2SecretRouter, workspace as v2WorkspaceRouter, serviceTokenData as v2ServiceTokenDataRouter, + apiKeyData as v2APIKeyDataRouter, } from './routes/v2'; import { getLogger } from './utils/logger'; @@ -98,6 +99,7 @@ app.use('/api/v1/integration-auth', v1IntegrationAuthRouter); app.use('/api/v2/workspace', v2WorkspaceRouter); app.use('/api/v2/secret', v2SecretRouter); app.use('/api/v2/service-token-data', v2ServiceTokenDataRouter); +app.use('/api/v2/api-key-data', v2APIKeyDataRouter); //* Handle unrouted requests and respond with proper error message as well as status code app.use((req, res, next)=>{ diff --git a/backend/src/controllers/v1/keyController.ts b/backend/src/controllers/v1/keyController.ts index 332215894..ffcb16d9c 100644 --- a/backend/src/controllers/v1/keyController.ts +++ b/backend/src/controllers/v1/keyController.ts @@ -2,7 +2,6 @@ import { Request, Response } from 'express'; import * as Sentry from '@sentry/node'; import { Key } from '../../models'; import { findMembership } from '../../helpers/membership'; -import { GRANTED } from '../../variables'; /** * Add (encrypted) copy of workspace key for workspace with id [workspaceId] for user with @@ -26,9 +25,6 @@ export const uploadKey = async (req: Request, res: Response) => { throw new Error('Failed receiver membership validation for workspace'); } - receiverMembership.status = GRANTED; - await receiverMembership.save(); - await new Key({ encryptedKey: key.encryptedKey, nonce: key.nonce, diff --git a/backend/src/controllers/v1/membershipController.ts b/backend/src/controllers/v1/membershipController.ts index 187e8127c..42cc29d9c 100644 --- a/backend/src/controllers/v1/membershipController.ts +++ b/backend/src/controllers/v1/membershipController.ts @@ -7,7 +7,7 @@ import { } from '../../helpers/membership'; import { sendMail } from '../../helpers/nodemailer'; import { SITE_URL } from '../../config'; -import { ADMIN, MEMBER, GRANTED, ACCEPTED } from '../../variables'; +import { ADMIN, MEMBER, ACCEPTED } from '../../variables'; /** * Check that user is a member of workspace with id [workspaceId] @@ -175,8 +175,7 @@ export const inviteUserToWorkspace = async (req: Request, res: Response) => { // already a member of the workspace const inviteeMembership = await Membership.findOne({ user: invitee._id, - workspace: workspaceId, - status: GRANTED + workspace: workspaceId }); if (inviteeMembership) @@ -205,8 +204,7 @@ export const inviteUserToWorkspace = async (req: Request, res: Response) => { const m = await new Membership({ user: invitee._id, workspace: workspaceId, - role: MEMBER, - status: GRANTED + role: MEMBER }).save(); await sendMail({ diff --git a/backend/src/controllers/v1/workspaceController.ts b/backend/src/controllers/v1/workspaceController.ts index d34fecbd7..4c0e869c5 100644 --- a/backend/src/controllers/v1/workspaceController.ts +++ b/backend/src/controllers/v1/workspaceController.ts @@ -15,7 +15,7 @@ import { deleteWorkspace as deleteWork } from '../../helpers/workspace'; import { addMemberships } from '../../helpers/membership'; -import { ADMIN, COMPLETED, GRANTED } from '../../variables'; +import { ADMIN } from '../../variables'; /** * Return public keys of members of workspace with id [workspaceId] @@ -33,13 +33,12 @@ export const getWorkspacePublicKeys = async (req: Request, res: Response) => { workspace: workspaceId }).populate<{ user: IUser }>('user', 'publicKey') ) - .filter((m) => m.status === COMPLETED || m.status === GRANTED) - .map((member) => { - return { - publicKey: member.user.publicKey, - userId: member.user._id - }; - }); + .map((member) => { + return { + publicKey: member.user.publicKey, + userId: member.user._id + }; + }); } catch (err) { Sentry.setUser({ email: req.user.email }); Sentry.captureException(err); @@ -169,8 +168,7 @@ export const createWorkspace = async (req: Request, res: Response) => { await addMemberships({ userIds: [req.user._id], workspaceId: workspace._id.toString(), - roles: [ADMIN], - statuses: [GRANTED] + roles: [ADMIN] }); } catch (err) { Sentry.setUser({ email: req.user.email }); @@ -335,31 +333,4 @@ export const getWorkspaceServiceTokens = async ( return res.status(200).send({ serviceTokens }); -} - -export const getWorkspaceServiceTokenData = async ( - req: Request, - res: Response -) => { - let serviceTokenData; - try { - const { workspaceId } = req.query; - - serviceTokenData = await ServiceTokenData - .find({ - workspace: workspaceId - }) - .select('+encryptedKey +iv +tag'); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get workspace service token data' - }); - } - - return res.status(200).send({ - serviceTokenData - }); } \ No newline at end of file diff --git a/backend/src/controllers/v2/apiKeyDataController.ts b/backend/src/controllers/v2/apiKeyDataController.ts new file mode 100644 index 000000000..3aacde8af --- /dev/null +++ b/backend/src/controllers/v2/apiKeyDataController.ts @@ -0,0 +1,106 @@ +import { Request, Response } from 'express'; +import * as Sentry from '@sentry/node'; +import crypto from 'crypto'; +import bcrypt from 'bcrypt'; +import { + APIKeyData +} from '../../models'; +import { + SALT_ROUNDS +} from '../../config'; + +/** + * Return API key data for user with id [req.user_id] + * @param req + * @param res + * @returns + */ +export const getAPIKeyData = async (req: Request, res: Response) => { + let apiKeyData; + try { + apiKeyData = await APIKeyData.find({ + user: req.user._id + }); + } catch (err) { + Sentry.setUser({ email: req.user.email }); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to get API key data' + }); + } + + return res.status(200).send({ + apiKeyData + }); +} + +/** + * Create new API key data for user with id [req.user._id] + * @param req + * @param res + */ +export const createAPIKeyData = async (req: Request, res: Response) => { + let apiKey, apiKeyData; + try { + const { name, expiresIn } = req.body; + + const secret = crypto.randomBytes(16).toString('hex'); + const secretHash = await bcrypt.hash(secret, SALT_ROUNDS); + + const expiresAt = new Date(); + expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); + + apiKeyData = await new APIKeyData({ + name, + expiresAt, + user: req.user._id, + secretHash + }).save(); + + // return api key data without sensitive data + apiKeyData = await APIKeyData.findById(apiKeyData._id); + + if (!apiKeyData) throw new Error('Failed to find API key data'); + + apiKey = `ak.${apiKeyData._id.toString()}.${secret}`; + + } catch (err) { + console.error(err); + Sentry.setUser({ email: req.user.email }); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to API key data' + }); + } + + return res.status(200).send({ + apiKey, + apiKeyData + }); +} + +/** + * Delete API key data with id [apiKeyDataId]. + * @param req + * @param res + * @returns + */ +export const deleteAPIKeyData = async (req: Request, res: Response) => { + let apiKeyData; + try { + const { apiKeyDataId } = req.params; + + apiKeyData = await APIKeyData.findByIdAndDelete(apiKeyDataId); + + } catch (err) { + Sentry.setUser({ email: req.user.email }); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to delete API key data' + }); + } + + return res.status(200).send({ + apiKeyData + }); +} \ No newline at end of file diff --git a/backend/src/controllers/v2/index.ts b/backend/src/controllers/v2/index.ts index d4729c15c..e867f7692 100644 --- a/backend/src/controllers/v2/index.ts +++ b/backend/src/controllers/v2/index.ts @@ -1,7 +1,9 @@ import * as workspaceController from './workspaceController'; import * as serviceTokenDataController from './serviceTokenDataController'; +import * as apiKeyDataController from './apiKeyDataController'; export { workspaceController, - serviceTokenDataController + serviceTokenDataController, + apiKeyDataController } diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index 637801fa2..62dcebda6 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -2,6 +2,7 @@ import { Request, Response } from 'express'; import * as Sentry from '@sentry/node'; import { Key, + ServiceTokenData } from '../../models'; import { v2PushSecrets as push, @@ -182,4 +183,30 @@ export const getWorkspaceKey = async (req: Request, res: Response) => { return res.status(200).send({ key }); +} +export const getWorkspaceServiceTokenData = async ( + req: Request, + res: Response +) => { + let serviceTokenData; + try { + const { workspaceId } = req.query; + + serviceTokenData = await ServiceTokenData + .find({ + workspace: workspaceId + }) + .select('+encryptedKey +iv +tag'); + + } catch (err) { + Sentry.setUser({ email: req.user.email }); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to get workspace service token data' + }); + } + + return res.status(200).send({ + serviceTokenData + }); } \ No newline at end of file diff --git a/backend/src/ee/middleware/requireSecretSnapshotAuth.ts b/backend/src/ee/middleware/requireSecretSnapshotAuth.ts index 71d7c5215..5eae3721c 100644 --- a/backend/src/ee/middleware/requireSecretSnapshotAuth.ts +++ b/backend/src/ee/middleware/requireSecretSnapshotAuth.ts @@ -14,10 +14,8 @@ import { */ const requireSecretSnapshotAuth = ({ acceptedRoles, - acceptedStatuses }: { acceptedRoles: string[]; - acceptedStatuses: string[]; }) => { return async (req: Request, res: Response, next: NextFunction) => { try { @@ -34,8 +32,7 @@ const requireSecretSnapshotAuth = ({ await validateMembership({ userId: req.user._id.toString(), workspaceId: secretSnapshot.workspace.toString(), - acceptedRoles, - acceptedStatuses + acceptedRoles }); req.secretSnapshot = secretSnapshot as any; diff --git a/backend/src/ee/routes/v1/secret.ts b/backend/src/ee/routes/v1/secret.ts index c9605a2d0..43cc8bafc 100644 --- a/backend/src/ee/routes/v1/secret.ts +++ b/backend/src/ee/routes/v1/secret.ts @@ -7,7 +7,7 @@ import { } from '../../../middleware'; import { query, param } from 'express-validator'; import { secretController } from '../../controllers/v1'; -import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../../variables'; +import { ADMIN, MEMBER } from '../../../variables'; router.get( '/:secretId/secret-versions', @@ -15,8 +15,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('secretId').exists().trim(), query('offset').exists().isInt(), diff --git a/backend/src/ee/routes/v1/secretSnapshot.ts b/backend/src/ee/routes/v1/secretSnapshot.ts index 4b23f03e5..80aa7d1ee 100644 --- a/backend/src/ee/routes/v1/secretSnapshot.ts +++ b/backend/src/ee/routes/v1/secretSnapshot.ts @@ -8,7 +8,7 @@ import { validateRequest } from '../../../middleware'; import { param } from 'express-validator'; -import { ADMIN, MEMBER, GRANTED } from '../../../variables'; +import { ADMIN, MEMBER } from '../../../variables'; import { secretSnapshotController } from '../../controllers/v1'; router.get( @@ -17,8 +17,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireSecretSnapshotAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('secretSnapshotId').exists().trim(), validateRequest, diff --git a/backend/src/ee/routes/v1/workspace.ts b/backend/src/ee/routes/v1/workspace.ts index f95ea7c93..48c054970 100644 --- a/backend/src/ee/routes/v1/workspace.ts +++ b/backend/src/ee/routes/v1/workspace.ts @@ -6,7 +6,7 @@ import { validateRequest } from '../../../middleware'; import { param, query } from 'express-validator'; -import { ADMIN, MEMBER, GRANTED } from '../../../variables'; +import { ADMIN, MEMBER } from '../../../variables'; import { workspaceController } from '../../controllers/v1'; router.get( @@ -15,8 +15,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), query('offset').exists().isInt(), @@ -31,8 +30,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, @@ -43,8 +41,7 @@ router.get( '/:workspaceId/logs', requireAuth, requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), query('offset').exists().isInt(), diff --git a/backend/src/helpers/auth.ts b/backend/src/helpers/auth.ts index ad63d41b4..2b972c09d 100644 --- a/backend/src/helpers/auth.ts +++ b/backend/src/helpers/auth.ts @@ -3,22 +3,25 @@ import * as Sentry from '@sentry/node'; import bcrypt from 'bcrypt'; import { User, - ServiceTokenData + ServiceTokenData, + APIKeyData } from '../models'; import { JWT_AUTH_LIFETIME, JWT_AUTH_SECRET, JWT_REFRESH_LIFETIME, - JWT_REFRESH_SECRET, - SALT_ROUNDS + JWT_REFRESH_SECRET } from '../config'; import { AccountNotFoundError, ServiceTokenDataNotFoundError, - UnauthorizedRequestError, - BadRequestError + APIKeyDataNotFoundError, + UnauthorizedRequestError } from '../utils/errors'; +// TODO 1: check if API key works +// TODO 2: optimize middleware + /** * Validate that auth token value [authTokenValue] falls under one of * accepted auth modes [acceptedAuthModes]. @@ -40,6 +43,9 @@ const validateAuthMode = ({ case 'st': authMode = 'serviceToken'; break; + case 'ak': + authMode = 'apiKey'; + break; default: authMode = 'jwt'; break; @@ -106,9 +112,11 @@ const getAuthSTDPayload = async ({ // TODO: optimize double query serviceTokenData = await ServiceTokenData - .findById(TOKEN_IDENTIFIER, 'secretHash expiresAt'); + .findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt'); - if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) { + if (!serviceTokenData) { + throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); + } else if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) { // case: service token expired await ServiceTokenData.findByIdAndDelete(serviceTokenData._id); throw UnauthorizedRequestError({ @@ -116,8 +124,6 @@ const getAuthSTDPayload = async ({ }); } - if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); - const isMatch = await bcrypt.compare(TOKEN_SECRET, serviceTokenData.secretHash); if (!isMatch) throw UnauthorizedRequestError({ message: 'Failed to authenticate service token' @@ -136,6 +142,50 @@ const getAuthSTDPayload = async ({ return serviceTokenData; } +/** + * Return API key data payload corresponding to API key [authTokenValue] + * @param {Object} obj + * @param {String} obj.authTokenValue - API key value + * @returns {APIKeyData} apiKeyData - API key data + */ +const getAuthAPIKeyPayload = async ({ + authTokenValue +}: { + authTokenValue: string; +}) => { + let user; + try { + const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); + + const apiKeyData = await APIKeyData + .findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt') + .populate('user', '+publicKey'); + + if (!apiKeyData) { + throw APIKeyDataNotFoundError({ message: 'Failed to find API key data' }); + } else if (apiKeyData?.expiresAt && new Date(apiKeyData.expiresAt) < new Date()) { + // case: API key expired + await APIKeyData.findByIdAndDelete(apiKeyData._id); + throw UnauthorizedRequestError({ + message: 'Failed to authenticate expired API key' + }); + } + + const isMatch = await bcrypt.compare(TOKEN_SECRET, apiKeyData.secretHash); + if (!isMatch) throw UnauthorizedRequestError({ + message: 'Failed to authenticate API key' + }); + + user = apiKeyData.user; + } catch (err) { + throw UnauthorizedRequestError({ + message: 'Failed to authenticate API key' + }); + } + + return user; +} + /** * Return newly issued (JWT) auth and refresh tokens to user with id [userId] * @param {Object} obj @@ -229,6 +279,7 @@ export { validateAuthMode, getAuthUserPayload, getAuthSTDPayload, + getAuthAPIKeyPayload, createToken, issueTokens, clearTokens diff --git a/backend/src/helpers/membership.ts b/backend/src/helpers/membership.ts index b237803f1..466cefdef 100644 --- a/backend/src/helpers/membership.ts +++ b/backend/src/helpers/membership.ts @@ -3,7 +3,7 @@ import { Membership, Key } from '../models'; /** * Validate that user with id [userId] is a member of workspace with id [workspaceId] - * and has at least one of the roles in [acceptedRoles] and statuses in [acceptedStatuses] + * and has at least one of the roles in [acceptedRoles] * @param {Object} obj * @param {String} obj.userId - id of user to validate * @param {String} obj.workspaceId - id of workspace @@ -12,12 +12,10 @@ const validateMembership = async ({ userId, workspaceId, acceptedRoles, - acceptedStatuses }: { userId: string; workspaceId: string; acceptedRoles: string[]; - acceptedStatuses: string[]; }) => { let membership; @@ -33,11 +31,6 @@ const validateMembership = async ({ if (!acceptedRoles.includes(membership.role)) { throw new Error('Failed to validate membership role'); } - - if (!acceptedStatuses.includes(membership.status)) { - throw new Error('Failed to validate membership status'); - } - } catch (err) { Sentry.setUser(null); Sentry.captureException(err); @@ -72,18 +65,15 @@ const findMembership = async (queryObj: any) => { * @param {String[]} obj.userIds - id of users. * @param {String} obj.workspaceId - id of workspace. * @param {String[]} obj.roles - roles of users. - * @param {String[]} obj.statuses - statuses of users. */ const addMemberships = async ({ userIds, workspaceId, - roles, - statuses + roles }: { userIds: string[]; workspaceId: string; roles: string[]; - statuses: string[]; }): Promise => { try { const operations = userIds.map((userId, idx) => { @@ -92,14 +82,12 @@ const addMemberships = async ({ filter: { user: userId, workspace: workspaceId, - role: roles[idx], - status: statuses[idx] + role: roles[idx] }, update: { user: userId, workspace: workspaceId, - role: roles[idx], - status: statuses[idx] + role: roles[idx] }, upsert: true } diff --git a/backend/src/helpers/rateLimiter.ts b/backend/src/helpers/rateLimiter.ts index 6153369e3..6171559af 100644 --- a/backend/src/helpers/rateLimiter.ts +++ b/backend/src/helpers/rateLimiter.ts @@ -3,7 +3,7 @@ import rateLimit from 'express-rate-limit'; // 300 requests per 15 minutes const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, - max: 400, + max: 450, standardHeaders: true, legacyHeaders: false, skip: (request) => request.path === '/healthcheck' @@ -20,7 +20,7 @@ const signupLimiter = rateLimit({ // 10 requests per hour const loginLimiter = rateLimit({ windowMs: 60 * 60 * 1000, - max: 20, + max: 25, standardHeaders: true, legacyHeaders: false }); diff --git a/backend/src/helpers/signup.ts b/backend/src/helpers/signup.ts index 8a201cb11..4621d1f50 100644 --- a/backend/src/helpers/signup.ts +++ b/backend/src/helpers/signup.ts @@ -5,7 +5,7 @@ import { createOrganization } from './organization'; import { addMembershipsOrg } from './membershipOrg'; import { createWorkspace } from './workspace'; import { addMemberships } from './membership'; -import { OWNER, ADMIN, ACCEPTED, GRANTED } from '../variables'; +import { OWNER, ADMIN, ACCEPTED } from '../variables'; import { sendMail } from '../helpers/nodemailer'; /** @@ -113,8 +113,7 @@ const initializeDefaultOrg = async ({ await addMemberships({ userIds: [user._id.toString()], workspaceId: workspace._id.toString(), - roles: [ADMIN], - statuses: [GRANTED] + roles: [ADMIN] }); } catch (err) { throw new Error('Failed to initialize default organization and workspace'); diff --git a/backend/src/middleware/requireAuth.ts b/backend/src/middleware/requireAuth.ts index 8253cb64e..5d95883a5 100644 --- a/backend/src/middleware/requireAuth.ts +++ b/backend/src/middleware/requireAuth.ts @@ -4,7 +4,8 @@ import { User, ServiceTokenData } from '../models'; import { validateAuthMode, getAuthUserPayload, - getAuthSTDPayload + getAuthSTDPayload, + getAuthAPIKeyPayload } from '../helpers/auth'; import { BadRequestError } from '../utils/errors'; @@ -53,6 +54,11 @@ const requireAuth = ({ authTokenValue: AUTH_TOKEN_VALUE }); break; + case 'apiKey': + req.user = await getAuthAPIKeyPayload({ + authTokenValue: AUTH_TOKEN_VALUE + }); + break; default: req.user = await getAuthUserPayload({ authTokenValue: AUTH_TOKEN_VALUE diff --git a/backend/src/middleware/requireBotAuth.ts b/backend/src/middleware/requireBotAuth.ts index 14c099393..435b06a59 100644 --- a/backend/src/middleware/requireBotAuth.ts +++ b/backend/src/middleware/requireBotAuth.ts @@ -7,11 +7,9 @@ type req = 'params' | 'body' | 'query'; const requireBotAuth = ({ acceptedRoles, - acceptedStatuses, location = 'params' }: { acceptedRoles: string[]; - acceptedStatuses: string[]; location?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { @@ -24,8 +22,7 @@ const requireBotAuth = ({ await validateMembership({ userId: req.user._id.toString(), workspaceId: bot.workspace.toString(), - acceptedRoles, - acceptedStatuses + acceptedRoles }); req.bot = bot; diff --git a/backend/src/middleware/requireIntegrationAuth.ts b/backend/src/middleware/requireIntegrationAuth.ts index 4389028ab..b185b922b 100644 --- a/backend/src/middleware/requireIntegrationAuth.ts +++ b/backend/src/middleware/requireIntegrationAuth.ts @@ -9,14 +9,11 @@ import { IntegrationNotFoundError, UnauthorizedRequestError } from '../utils/err * with the integration on request params. * @param {Object} obj * @param {String[]} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.acceptedStatuses - accepted workspace statuses */ const requireIntegrationAuth = ({ - acceptedRoles, - acceptedStatuses + acceptedRoles }: { acceptedRoles: string[]; - acceptedStatuses: string[]; }) => { return async (req: Request, res: Response, next: NextFunction) => { // integration authorization middleware @@ -35,8 +32,7 @@ const requireIntegrationAuth = ({ await validateMembership({ userId: req.user._id.toString(), workspaceId: integration.workspace.toString(), - acceptedRoles, - acceptedStatuses + acceptedRoles }); const integrationAuth = await IntegrationAuth.findOne({ diff --git a/backend/src/middleware/requireIntegrationAuthorizationAuth.ts b/backend/src/middleware/requireIntegrationAuthorizationAuth.ts index 278716e60..6c1f9066e 100644 --- a/backend/src/middleware/requireIntegrationAuthorizationAuth.ts +++ b/backend/src/middleware/requireIntegrationAuthorizationAuth.ts @@ -10,16 +10,13 @@ import { UnauthorizedRequestError } from '../utils/errors'; * with the integration authorization on request params. * @param {Object} obj * @param {String[]} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.acceptedStatuses - accepted workspace statuses * @param {Boolean} obj.attachAccessToken - whether or not to decrypt and attach integration authorization access token onto request */ const requireIntegrationAuthorizationAuth = ({ acceptedRoles, - acceptedStatuses, attachAccessToken = true }: { acceptedRoles: string[]; - acceptedStatuses: string[]; attachAccessToken?: boolean; }) => { return async (req: Request, res: Response, next: NextFunction) => { @@ -38,8 +35,7 @@ const requireIntegrationAuthorizationAuth = ({ await validateMembership({ userId: req.user._id.toString(), workspaceId: integrationAuth.workspace.toString(), - acceptedRoles, - acceptedStatuses + acceptedRoles }); req.integrationAuth = integrationAuth; diff --git a/backend/src/middleware/requireSecretAuth.ts b/backend/src/middleware/requireSecretAuth.ts index 8f6fc5305..c6a291200 100644 --- a/backend/src/middleware/requireSecretAuth.ts +++ b/backend/src/middleware/requireSecretAuth.ts @@ -9,15 +9,12 @@ import { * Validate if user on request has proper membership to modify secret. * @param {Object} obj * @param {String[]} obj.acceptedRoles - accepted workspace roles - * @param {String[]} obj.acceptedStatuses - accepted workspace statuses * @param {String[]} obj.location - location of [workspaceId] on request (e.g. params, body) for parsing */ const requireSecretAuth = ({ - acceptedRoles, - acceptedStatuses + acceptedRoles }: { acceptedRoles: string[]; - acceptedStatuses: string[]; }) => { return async (req: Request, res: Response, next: NextFunction) => { try { @@ -34,8 +31,7 @@ const requireSecretAuth = ({ await validateMembership({ userId: req.user._id.toString(), workspaceId: secret.workspace.toString(), - acceptedRoles, - acceptedStatuses + acceptedRoles }); req.secret = secret as any; diff --git a/backend/src/middleware/requireServiceTokenDataAuth.ts b/backend/src/middleware/requireServiceTokenDataAuth.ts index 48eaac3dc..2b4eb739a 100644 --- a/backend/src/middleware/requireServiceTokenDataAuth.ts +++ b/backend/src/middleware/requireServiceTokenDataAuth.ts @@ -7,11 +7,9 @@ type req = 'params' | 'body' | 'query'; const requireServiceTokenDataAuth = ({ acceptedRoles, - acceptedStatuses, location = 'params' }: { acceptedRoles: string[]; - acceptedStatuses: string[]; location?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { @@ -30,8 +28,7 @@ const requireServiceTokenDataAuth = ({ await validateMembership({ userId: req.user._id.toString(), workspaceId: serviceTokenData.workspace.toString(), - acceptedRoles, - acceptedStatuses + acceptedRoles }); } diff --git a/backend/src/middleware/requireWorkspaceAuth.ts b/backend/src/middleware/requireWorkspaceAuth.ts index 68edec6a4..9b710cc83 100644 --- a/backend/src/middleware/requireWorkspaceAuth.ts +++ b/backend/src/middleware/requireWorkspaceAuth.ts @@ -9,16 +9,13 @@ type req = 'params' | 'body' | 'query'; * on request params. * @param {Object} obj * @param {String[]} obj.acceptedRoles - accepted workspace roles for JWT auth - * @param {String[]} obj.acceptedStatuses - accepted workspace statuses for JWT auth * @param {String[]} obj.location - location of [workspaceId] on request (e.g. params, body) for parsing */ const requireWorkspaceAuth = ({ acceptedRoles, - acceptedStatuses, location = 'params' }: { acceptedRoles: string[]; - acceptedStatuses: string[]; location?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { @@ -30,8 +27,7 @@ const requireWorkspaceAuth = ({ const membership = await validateMembership({ userId: req.user._id.toString(), workspaceId, - acceptedRoles, - acceptedStatuses + acceptedRoles }); req.membership = membership; diff --git a/backend/src/models/apiKeyData.ts b/backend/src/models/apiKeyData.ts new file mode 100644 index 000000000..af73b5f69 --- /dev/null +++ b/backend/src/models/apiKeyData.ts @@ -0,0 +1,37 @@ +import { Schema, model, Types } from 'mongoose'; + +export interface IAPIKeyData { + name: string; + user: Types.ObjectId; + expiresAt: Date; + secretHash: string; +} + +const apiKeyDataSchema = new Schema( + { + name: { + type: String, + required: true + }, + user: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true + }, + expiresAt: { + type: Date + }, + secretHash: { + type: String, + required: true, + select: false + } + }, + { + timestamps: true + } +); + +const APIKeyData = model('APIKeyData', apiKeyDataSchema); + +export default APIKeyData; diff --git a/backend/src/models/index.ts b/backend/src/models/index.ts index 8e934d511..72ffca607 100644 --- a/backend/src/models/index.ts +++ b/backend/src/models/index.ts @@ -14,7 +14,8 @@ import Token, { IToken } from './token'; import User, { IUser } from './user'; import UserAction, { IUserAction } from './userAction'; import Workspace, { IWorkspace } from './workspace'; -import ServiceTokenData, { IServiceTokenData } from './serviceTokenData '; +import ServiceTokenData, { IServiceTokenData } from './serviceTokenData'; +import APIKeyData, { IAPIKeyData } from './apiKeyData'; export { BackupPrivateKey, @@ -50,5 +51,7 @@ export { Workspace, IWorkspace, ServiceTokenData, - IServiceTokenData + IServiceTokenData, + APIKeyData, + IAPIKeyData }; diff --git a/backend/src/models/membership.ts b/backend/src/models/membership.ts index a38c64651..abbce82c1 100644 --- a/backend/src/models/membership.ts +++ b/backend/src/models/membership.ts @@ -1,5 +1,5 @@ import { Schema, model, Types } from 'mongoose'; -import { ADMIN, MEMBER, INVITED, COMPLETED, GRANTED } from '../variables'; +import { ADMIN, MEMBER } from '../variables'; export interface IMembership { _id: Types.ObjectId; @@ -7,7 +7,6 @@ export interface IMembership { inviteEmail?: string; workspace: Types.ObjectId; role: 'admin' | 'member'; - status: 'invited' | 'completed' | 'granted'; } const membershipSchema = new Schema( @@ -28,12 +27,6 @@ const membershipSchema = new Schema( type: String, enum: [ADMIN, MEMBER], required: true - }, - status: { - // INVITED, COMPLETED, GRANTED - type: String, - enum: [INVITED, COMPLETED, GRANTED], - required: true } }, { diff --git a/backend/src/models/serviceTokenData .ts b/backend/src/models/serviceTokenData.ts similarity index 93% rename from backend/src/models/serviceTokenData .ts rename to backend/src/models/serviceTokenData.ts index 8e8ae5eab..612d07bf6 100644 --- a/backend/src/models/serviceTokenData .ts +++ b/backend/src/models/serviceTokenData.ts @@ -1,5 +1,4 @@ import { Schema, model, Types } from 'mongoose'; -import { ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD } from '../variables'; export interface IServiceTokenData { name: string; @@ -38,7 +37,6 @@ const serviceTokenDataSchema = new Schema( }, secretHash: { type: String, - unique: true, required: true, select: false }, diff --git a/backend/src/routes/v1/bot.ts b/backend/src/routes/v1/bot.ts index 0d631b8eb..1b98f48c5 100644 --- a/backend/src/routes/v1/bot.ts +++ b/backend/src/routes/v1/bot.ts @@ -8,7 +8,7 @@ import { validateRequest } from '../../middleware'; import { botController } from '../../controllers/v1'; -import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; router.get( '/:workspaceId', @@ -16,8 +16,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim().notEmpty(), validateRequest, @@ -30,8 +29,7 @@ router.patch( acceptedAuthModes: ['jwt'] }), requireBotAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), body('isActive').isBoolean(), body('botKey'), diff --git a/backend/src/routes/v1/integration.ts b/backend/src/routes/v1/integration.ts index 3715bef46..ea589162a 100644 --- a/backend/src/routes/v1/integration.ts +++ b/backend/src/routes/v1/integration.ts @@ -5,7 +5,7 @@ import { requireIntegrationAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; import { body, param } from 'express-validator'; import { integrationController } from '../../controllers/v1'; @@ -15,8 +15,7 @@ router.patch( acceptedAuthModes: ['jwt'] }), requireIntegrationAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('integrationId').exists().trim(), body('app').exists().trim(), @@ -35,8 +34,7 @@ router.delete( acceptedAuthModes: ['jwt'] }), requireIntegrationAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('integrationId').exists().trim(), validateRequest, diff --git a/backend/src/routes/v1/integrationAuth.ts b/backend/src/routes/v1/integrationAuth.ts index c613ce62f..605c5023e 100644 --- a/backend/src/routes/v1/integrationAuth.ts +++ b/backend/src/routes/v1/integrationAuth.ts @@ -7,7 +7,7 @@ import { requireIntegrationAuthorizationAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; import { integrationAuthController } from '../../controllers/v1'; router.get( @@ -25,7 +25,6 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED], location: 'body' }), body('workspaceId').exists().trim().notEmpty(), @@ -41,8 +40,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireIntegrationAuthorizationAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('integrationAuthId'), validateRequest, @@ -56,7 +54,6 @@ router.delete( }), requireIntegrationAuthorizationAuth({ acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED], attachAccessToken: false }), param('integrationAuthId'), diff --git a/backend/src/routes/v1/key.ts b/backend/src/routes/v1/key.ts index d8bc7c29e..b66bd1276 100644 --- a/backend/src/routes/v1/key.ts +++ b/backend/src/routes/v1/key.ts @@ -6,7 +6,7 @@ import { validateRequest } from '../../middleware'; import { body, param } from 'express-validator'; -import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; import { keyController } from '../../controllers/v1'; router.post( @@ -15,8 +15,7 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), body('key').exists(), @@ -30,8 +29,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId'), validateRequest, diff --git a/backend/src/routes/v1/secret.ts b/backend/src/routes/v1/secret.ts index c3f0626ce..cce105500 100644 --- a/backend/src/routes/v1/secret.ts +++ b/backend/src/routes/v1/secret.ts @@ -8,7 +8,7 @@ import { } from '../../middleware'; import { body, query, param } from 'express-validator'; import { secretController } from '../../controllers/v1'; -import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; router.post( '/:workspaceId', @@ -16,8 +16,7 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), body('secrets').exists(), body('keys').exists(), @@ -34,8 +33,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), query('environment').exists().trim(), query('channel'), diff --git a/backend/src/routes/v1/serviceToken.ts b/backend/src/routes/v1/serviceToken.ts index edc00a939..18487ac3e 100644 --- a/backend/src/routes/v1/serviceToken.ts +++ b/backend/src/routes/v1/serviceToken.ts @@ -7,7 +7,7 @@ import { validateRequest } from '../../middleware'; import { body } from 'express-validator'; -import { ADMIN, MEMBER, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; import { serviceTokenController } from '../../controllers/v1'; // note: deprecate service-token routes in favor of service-token data routes/structure @@ -25,7 +25,6 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED], location: 'body' }), body('name').exists().trim().notEmpty(), diff --git a/backend/src/routes/v1/workspace.ts b/backend/src/routes/v1/workspace.ts index 7a1f8c5b8..801462662 100644 --- a/backend/src/routes/v1/workspace.ts +++ b/backend/src/routes/v1/workspace.ts @@ -6,7 +6,7 @@ import { requireWorkspaceAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; import { workspaceController, membershipController } from '../../controllers/v1'; router.get( @@ -15,8 +15,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, @@ -30,7 +29,6 @@ router.get( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] }), param('workspaceId').exists().trim(), validateRequest, @@ -51,8 +49,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, @@ -76,8 +73,7 @@ router.delete( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN] }), param('workspaceId').exists().trim(), validateRequest, @@ -90,8 +86,7 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), body('name').exists().trim().notEmpty(), @@ -105,8 +100,7 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), body('email').exists().trim().notEmpty(), @@ -120,8 +114,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, @@ -134,8 +127,7 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, @@ -148,26 +140,11 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, workspaceController.getWorkspaceServiceTokens ); -router.get( - '/:workspaceId/service-token-data', - requireAuth({ - acceptedAuthModes: ['jwt'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [GRANTED] - }), - param('workspaceId').exists().trim(), - validateRequest, - workspaceController.getWorkspaceServiceTokenData -); - export default router; diff --git a/backend/src/routes/v2/apiKeyData.ts b/backend/src/routes/v2/apiKeyData.ts new file mode 100644 index 000000000..07bbcbc44 --- /dev/null +++ b/backend/src/routes/v2/apiKeyData.ts @@ -0,0 +1,39 @@ +import express from 'express'; +const router = express.Router(); +import { + requireAuth, + validateRequest +} from '../../middleware'; +import { param, body } from 'express-validator'; +import { apiKeyDataController } from '../../controllers/v2'; + +router.get( + '/', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + apiKeyDataController.getAPIKeyData +); + +router.post( + '/', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + body('name').exists().trim(), + body('expiresIn'), // measured in ms + validateRequest, + apiKeyDataController.createAPIKeyData +); + +router.delete( + '/:apiKeyDataId', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + param('apiKeyDataId').exists().trim(), + validateRequest, + apiKeyDataController.deleteAPIKeyData +); + +export default router; \ No newline at end of file diff --git a/backend/src/routes/v2/index.ts b/backend/src/routes/v2/index.ts index acf115a92..d0f3833ba 100644 --- a/backend/src/routes/v2/index.ts +++ b/backend/src/routes/v2/index.ts @@ -1,9 +1,11 @@ import secret from './secret'; import workspace from './workspace'; import serviceTokenData from './serviceTokenData'; +import apiKeyData from './apiKeyData'; export { secret, workspace, - serviceTokenData + serviceTokenData, + apiKeyData } diff --git a/backend/src/routes/v2/serviceTokenData.ts b/backend/src/routes/v2/serviceTokenData.ts index 578d4e38e..254bf60f3 100644 --- a/backend/src/routes/v2/serviceTokenData.ts +++ b/backend/src/routes/v2/serviceTokenData.ts @@ -10,8 +10,6 @@ import { param, body } from 'express-validator'; import { ADMIN, MEMBER, - COMPLETED, - GRANTED } from '../../variables'; import { serviceTokenDataController } from '../../controllers/v2'; @@ -30,7 +28,6 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED], location: 'body' }), body('name').exists().trim(), @@ -50,8 +47,7 @@ router.delete( acceptedAuthModes: ['jwt'] }), requireServiceTokenDataAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED], + acceptedRoles: [ADMIN, MEMBER] }), param('serviceTokenDataId').exists().trim(), validateRequest, diff --git a/backend/src/routes/v2/workspace.ts b/backend/src/routes/v2/workspace.ts index b2c91bd1b..eaa8e58a3 100644 --- a/backend/src/routes/v2/workspace.ts +++ b/backend/src/routes/v2/workspace.ts @@ -6,7 +6,7 @@ import { requireWorkspaceAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../variables'; +import { ADMIN, MEMBER } from '../../variables'; import { workspaceController } from '../../controllers/v2'; router.post( @@ -15,8 +15,7 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), body('secrets').exists(), body('keys').exists(), @@ -33,8 +32,7 @@ router.get( acceptedAuthModes: ['jwt', 'serviceToken'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), query('environment').exists().trim(), query('channel'), @@ -49,12 +47,24 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - acceptedStatuses: [COMPLETED, GRANTED] + acceptedRoles: [ADMIN, MEMBER] }), param('workspaceId').exists().trim(), validateRequest, workspaceController.getWorkspaceKey ); +router.get( + '/:workspaceId/service-token-data', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER] + }), + param('workspaceId').exists().trim(), + validateRequest, + workspaceController.getWorkspaceServiceTokenData +); + export default router; diff --git a/backend/src/types/express/index.d.ts b/backend/src/types/express/index.d.ts index 22f745976..f43b5fa79 100644 --- a/backend/src/types/express/index.d.ts +++ b/backend/src/types/express/index.d.ts @@ -17,6 +17,7 @@ declare global { serviceToken: any; accessToken: any; serviceTokenData: any; + apiKeyData: any; query?: any; } } diff --git a/backend/src/utils/errors.ts b/backend/src/utils/errors.ts index 865e27767..e9972edf5 100644 --- a/backend/src/utils/errors.ts +++ b/backend/src/utils/errors.ts @@ -153,4 +153,14 @@ export const ServiceTokenDataNotFoundError = (error?: Partial[API KEY DATA ERRORS]<----- +export const APIKeyDataNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'service_token_data_not_found_error', + message: error?.message ?? 'The requested service token data was not found', + context: error?.context, + stack: error?.stack +}) + //* ----->[MISC ERRORS]<----- diff --git a/backend/src/variables/index.ts b/backend/src/variables/index.ts index e8a373e74..16c068925 100644 --- a/backend/src/variables/index.ts +++ b/backend/src/variables/index.ts @@ -28,8 +28,6 @@ import { MEMBER, INVITED, ACCEPTED, - COMPLETED, - GRANTED } from './organization'; import { SECRET_SHARED, SECRET_PERSONAL } from './secret'; import { EVENT_PUSH_SECRETS, EVENT_PULL_SECRETS } from './event'; @@ -48,8 +46,6 @@ export { MEMBER, INVITED, ACCEPTED, - COMPLETED, - GRANTED, SECRET_SHARED, SECRET_PERSONAL, ENV_DEV, diff --git a/backend/src/variables/organization.ts b/backend/src/variables/organization.ts index f91e1f5d3..1b74bd3ee 100644 --- a/backend/src/variables/organization.ts +++ b/backend/src/variables/organization.ts @@ -9,16 +9,10 @@ const INVITED = 'invited'; // -- organization const ACCEPTED = 'accepted'; -// -- workspace -const COMPLETED = 'completed'; -const GRANTED = 'granted'; - export { OWNER, ADMIN, MEMBER, INVITED, - ACCEPTED, - COMPLETED, - GRANTED + ACCEPTED } \ No newline at end of file