mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 17:26:36 +00:00
Begin service token data refactor
This commit is contained in:
+2
-2
@@ -34,7 +34,7 @@ import {
|
|||||||
stripe as stripeRouter,
|
stripe as stripeRouter,
|
||||||
integration as integrationRouter,
|
integration as integrationRouter,
|
||||||
integrationAuth as integrationAuthRouter,
|
integrationAuth as integrationAuthRouter,
|
||||||
apiKey as apiKeyRouter
|
serviceTokenData as serviceTokenDataRouter
|
||||||
} from './routes';
|
} from './routes';
|
||||||
|
|
||||||
import { getLogger } from './utils/logger';
|
import { getLogger } from './utils/logger';
|
||||||
@@ -86,7 +86,7 @@ app.use('/api/v1/password', passwordRouter);
|
|||||||
app.use('/api/v1/stripe', stripeRouter);
|
app.use('/api/v1/stripe', stripeRouter);
|
||||||
app.use('/api/v1/integration', integrationRouter);
|
app.use('/api/v1/integration', integrationRouter);
|
||||||
app.use('/api/v1/integration-auth', integrationAuthRouter);
|
app.use('/api/v1/integration-auth', integrationAuthRouter);
|
||||||
app.use('/api/v1/api-key', apiKeyRouter);
|
app.use('/api/v1/service-token-data', serviceTokenDataRouter);
|
||||||
|
|
||||||
//* Handle unrouted requests and respond with proper error message as well as status code
|
//* Handle unrouted requests and respond with proper error message as well as status code
|
||||||
app.use((req, res, next)=>{
|
app.use((req, res, next)=>{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const PORT = process.env.PORT || 4000;
|
const PORT = process.env.PORT || 4000;
|
||||||
const EMAIL_TOKEN_LIFETIME = process.env.EMAIL_TOKEN_LIFETIME! || '86400';
|
const EMAIL_TOKEN_LIFETIME = process.env.EMAIL_TOKEN_LIFETIME! || '86400';
|
||||||
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY!;
|
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY!;
|
||||||
|
const SALT_ROUNDS = parseInt(process.env.SALT_ROUNDS!) || 10;
|
||||||
const JWT_AUTH_LIFETIME = process.env.JWT_AUTH_LIFETIME! || '10d';
|
const JWT_AUTH_LIFETIME = process.env.JWT_AUTH_LIFETIME! || '10d';
|
||||||
const JWT_AUTH_SECRET = process.env.JWT_AUTH_SECRET!;
|
const JWT_AUTH_SECRET = process.env.JWT_AUTH_SECRET!;
|
||||||
const JWT_REFRESH_LIFETIME = process.env.JWT_REFRESH_LIFETIME! || '90d';
|
const JWT_REFRESH_LIFETIME = process.env.JWT_REFRESH_LIFETIME! || '90d';
|
||||||
@@ -47,6 +48,7 @@ export {
|
|||||||
PORT,
|
PORT,
|
||||||
EMAIL_TOKEN_LIFETIME,
|
EMAIL_TOKEN_LIFETIME,
|
||||||
ENCRYPTION_KEY,
|
ENCRYPTION_KEY,
|
||||||
|
SALT_ROUNDS,
|
||||||
JWT_AUTH_LIFETIME,
|
JWT_AUTH_LIFETIME,
|
||||||
JWT_AUTH_SECRET,
|
JWT_AUTH_SECRET,
|
||||||
JWT_REFRESH_LIFETIME,
|
JWT_REFRESH_LIFETIME,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
IntegrationAuth,
|
IntegrationAuth,
|
||||||
IUser,
|
IUser,
|
||||||
ServiceToken,
|
ServiceToken,
|
||||||
|
ServiceTokenData,
|
||||||
} from '../models';
|
} from '../models';
|
||||||
import {
|
import {
|
||||||
createWorkspace as create,
|
createWorkspace as create,
|
||||||
@@ -334,4 +335,31 @@ export const getWorkspaceServiceTokens = async (
|
|||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
serviceTokens
|
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
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import requireOrganizationAuth from './requireOrganizationAuth';
|
|||||||
import requireIntegrationAuth from './requireIntegrationAuth';
|
import requireIntegrationAuth from './requireIntegrationAuth';
|
||||||
import requireIntegrationAuthorizationAuth from './requireIntegrationAuthorizationAuth';
|
import requireIntegrationAuthorizationAuth from './requireIntegrationAuthorizationAuth';
|
||||||
import requireServiceTokenAuth from './requireServiceTokenAuth';
|
import requireServiceTokenAuth from './requireServiceTokenAuth';
|
||||||
|
import requireServiceTokenDataAuth from './requireServiceTokenDataAuth';
|
||||||
import validateRequest from './validateRequest';
|
import validateRequest from './validateRequest';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -17,5 +18,6 @@ export {
|
|||||||
requireIntegrationAuth,
|
requireIntegrationAuth,
|
||||||
requireIntegrationAuthorizationAuth,
|
requireIntegrationAuthorizationAuth,
|
||||||
requireServiceTokenAuth,
|
requireServiceTokenAuth,
|
||||||
|
requireServiceTokenDataAuth,
|
||||||
validateRequest
|
validateRequest
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ServiceToken } from '../models';
|
|||||||
import { JWT_SERVICE_SECRET } from '../config';
|
import { JWT_SERVICE_SECRET } from '../config';
|
||||||
import { BadRequestError, UnauthorizedRequestError } from '../utils/errors';
|
import { BadRequestError, UnauthorizedRequestError } from '../utils/errors';
|
||||||
|
|
||||||
|
// TODO: deprecate
|
||||||
declare module 'jsonwebtoken' {
|
declare module 'jsonwebtoken' {
|
||||||
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|||||||
+10
-10
@@ -1,11 +1,11 @@
|
|||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { APIKeyData } from '../models';
|
import { ServiceToken, ServiceTokenData } from '../models';
|
||||||
import { validateMembership } from '../helpers/membership';
|
import { validateMembership } from '../helpers/membership';
|
||||||
import { AccountNotFoundError } from '../utils/errors';
|
import { AccountNotFoundError } from '../utils/errors';
|
||||||
|
|
||||||
type req = 'params' | 'body' | 'query';
|
type req = 'params' | 'body' | 'query';
|
||||||
|
|
||||||
const requireAPIKeyDataAuth = ({
|
const requireServiceTokenDataAuth = ({
|
||||||
acceptedRoles,
|
acceptedRoles,
|
||||||
acceptedStatuses,
|
acceptedStatuses,
|
||||||
location = 'params'
|
location = 'params'
|
||||||
@@ -16,25 +16,25 @@ const requireAPIKeyDataAuth = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return async (req: Request, res: Response, next: NextFunction) => {
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|
||||||
// req.user
|
const serviceTokenData = await ServiceTokenData
|
||||||
|
.findById(req[location].serviceTokenDataId)
|
||||||
|
.select('+encryptedKey +iv +tag');
|
||||||
|
|
||||||
const apiKeyData = await APIKeyData.findById(req[location].apiKeyDataId);
|
if (!serviceTokenData) {
|
||||||
|
return next(AccountNotFoundError({message: 'Failed to locate service token data'}));
|
||||||
if (!apiKeyData) {
|
|
||||||
return next(AccountNotFoundError({message: 'Failed to locate API Key data'}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await validateMembership({
|
await validateMembership({
|
||||||
userId: req.user._id.toString(),
|
userId: req.user._id.toString(),
|
||||||
workspaceId: apiKeyData?.workspace.toString(),
|
workspaceId: serviceTokenData.workspace.toString(),
|
||||||
acceptedRoles,
|
acceptedRoles,
|
||||||
acceptedStatuses
|
acceptedStatuses
|
||||||
});
|
});
|
||||||
|
|
||||||
req.apiKeyData = '' // ??
|
req.serviceTokenData = serviceTokenData;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default requireAPIKeyDataAuth;
|
export default requireServiceTokenDataAuth;
|
||||||
@@ -14,7 +14,7 @@ import Token, { IToken } from './token';
|
|||||||
import User, { IUser } from './user';
|
import User, { IUser } from './user';
|
||||||
import UserAction, { IUserAction } from './userAction';
|
import UserAction, { IUserAction } from './userAction';
|
||||||
import Workspace, { IWorkspace } from './workspace';
|
import Workspace, { IWorkspace } from './workspace';
|
||||||
import APIKeyData, { IAPIKeyData } from './apiKeyData';
|
import ServiceTokenData, { IServiceTokenData } from './serviceTokenData ';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
BackupPrivateKey,
|
BackupPrivateKey,
|
||||||
@@ -49,6 +49,6 @@ export {
|
|||||||
IUserAction,
|
IUserAction,
|
||||||
Workspace,
|
Workspace,
|
||||||
IWorkspace,
|
IWorkspace,
|
||||||
APIKeyData,
|
ServiceTokenData,
|
||||||
IAPIKeyData,
|
IServiceTokenData
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Schema, model, Types } from 'mongoose';
|
import { Schema, model, Types } from 'mongoose';
|
||||||
import { ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD } from '../variables';
|
import { ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD } from '../variables';
|
||||||
|
|
||||||
|
// TODO: deprecate
|
||||||
export interface IServiceToken {
|
export interface IServiceToken {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -1,36 +1,33 @@
|
|||||||
import { Schema, model, Types } from 'mongoose';
|
import { Schema, model, Types } from 'mongoose';
|
||||||
import { ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD } from '../variables';
|
import { ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD } from '../variables';
|
||||||
|
|
||||||
export interface IAPIKeyData {
|
export interface IServiceTokenData {
|
||||||
name: string;
|
name: string;
|
||||||
workspaces: {
|
workspace: Types.ObjectId;
|
||||||
workspace: Types.ObjectId,
|
environment: string; // TODO: adapt to upcoming environment id
|
||||||
environments: string[]
|
|
||||||
}[];
|
|
||||||
expiresAt: Date;
|
expiresAt: Date;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
apiKeyHash: string;
|
serviceTokenHash: string;
|
||||||
encryptedKey: string;
|
encryptedKey: string;
|
||||||
iv: string;
|
iv: string;
|
||||||
tag: string;
|
tag: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiKeyDataSchema = new Schema<IAPIKeyData>(
|
const serviceTokenDataSchema = new Schema<IServiceTokenData>(
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
workspaces: [{
|
workspace: {
|
||||||
workspace: {
|
type: Schema.Types.ObjectId,
|
||||||
type: Schema.Types.ObjectId,
|
ref: 'Workspace',
|
||||||
ref: 'Workspace'
|
required: true
|
||||||
},
|
},
|
||||||
environments: [{
|
environment: { // TODO: adapt to upcoming environment id
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD]
|
required: true
|
||||||
}]
|
},
|
||||||
}],
|
|
||||||
expiresAt: {
|
expiresAt: {
|
||||||
type: Date
|
type: Date
|
||||||
},
|
},
|
||||||
@@ -38,7 +35,7 @@ const apiKeyDataSchema = new Schema<IAPIKeyData>(
|
|||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
apiKeyHash: {
|
serviceTokenHash: {
|
||||||
type: String,
|
type: String,
|
||||||
unique: true,
|
unique: true,
|
||||||
required: true
|
required: true
|
||||||
@@ -61,6 +58,6 @@ const apiKeyDataSchema = new Schema<IAPIKeyData>(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const APIKeyData = model<IAPIKeyData>('APIKeyData', apiKeyDataSchema);
|
const ServiceTokenData = model<IServiceTokenData>('ServiceTokenData', serviceTokenDataSchema);
|
||||||
|
|
||||||
export default APIKeyData;
|
export default ServiceTokenData;
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
import express from 'express';
|
|
||||||
const router = express.Router();
|
|
||||||
import {
|
|
||||||
requireAuth
|
|
||||||
} from '../middleware';
|
|
||||||
import {
|
|
||||||
APIKeyData
|
|
||||||
} from '../models';
|
|
||||||
import { param, body, query } from 'express-validator';
|
|
||||||
import crypto from 'crypto';
|
|
||||||
import bcrypt from 'bcrypt';
|
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
|
|
||||||
// TODO: middleware
|
|
||||||
router.post(
|
|
||||||
'/',
|
|
||||||
requireAuth,
|
|
||||||
body('name').exists().trim(),
|
|
||||||
body('workspace'),
|
|
||||||
body('environment'),
|
|
||||||
body('encryptedKey'),
|
|
||||||
body('iv'),
|
|
||||||
body('tag'),
|
|
||||||
body('expiresAt'),
|
|
||||||
async (req, res) => {
|
|
||||||
let apiKey, apiKeyData;
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
workspace,
|
|
||||||
environment,
|
|
||||||
encryptedKey,
|
|
||||||
iv,
|
|
||||||
tag,
|
|
||||||
expiresAt
|
|
||||||
} = req.body;
|
|
||||||
|
|
||||||
// create 38-char API key with first 6-char being the prefix
|
|
||||||
apiKey = crypto.randomBytes(19).toString('hex');
|
|
||||||
|
|
||||||
const saltRounds = 10; // TODO: add as config envar
|
|
||||||
const apiKeyHash = await bcrypt.hash(apiKey, saltRounds);
|
|
||||||
|
|
||||||
apiKeyData = await new APIKeyData({
|
|
||||||
name,
|
|
||||||
workspace,
|
|
||||||
environment,
|
|
||||||
expiresAt,
|
|
||||||
prefix: apiKey.substring(0, 6),
|
|
||||||
apiKeyHash,
|
|
||||||
encryptedKey,
|
|
||||||
iv,
|
|
||||||
tag
|
|
||||||
}).save();
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to create workspace API Key'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
apiKey,
|
|
||||||
apiKeyData
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: middleware
|
|
||||||
router.get(
|
|
||||||
'/',
|
|
||||||
requireAuth,
|
|
||||||
query('workspaceId').exists().trim(),
|
|
||||||
async (req, res) => {
|
|
||||||
let apiKeyData;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.query;
|
|
||||||
|
|
||||||
apiKeyData = await APIKeyData.find({
|
|
||||||
workspace: workspaceId
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get workspace API Key data'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
apiKeyData
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: middleware
|
|
||||||
router.delete(
|
|
||||||
':apiKeyDataId',
|
|
||||||
requireAuth,
|
|
||||||
// TODO: requireAPIKeyDataAuth,
|
|
||||||
param('apiKeyDataId').exists().trim(),
|
|
||||||
async (req, res) => {
|
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// INFISICAL TOKEN = <API_KEY>.<KEY>
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
@@ -15,7 +15,7 @@ import password from './password';
|
|||||||
import stripe from './stripe';
|
import stripe from './stripe';
|
||||||
import integration from './integration';
|
import integration from './integration';
|
||||||
import integrationAuth from './integrationAuth';
|
import integrationAuth from './integrationAuth';
|
||||||
import apiKey from './apiKey';
|
import serviceTokenData from './serviceTokenData';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
signup,
|
signup,
|
||||||
@@ -35,5 +35,5 @@ export {
|
|||||||
stripe,
|
stripe,
|
||||||
integration,
|
integration,
|
||||||
integrationAuth,
|
integrationAuth,
|
||||||
apiKey
|
serviceTokenData
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
import express from 'express';
|
||||||
|
const router = express.Router();
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import bcrypt from 'bcrypt';
|
||||||
|
import * as Sentry from '@sentry/node';
|
||||||
|
import {
|
||||||
|
requireAuth,
|
||||||
|
requireWorkspaceAuth,
|
||||||
|
requireServiceTokenDataAuth,
|
||||||
|
validateRequest
|
||||||
|
} from '../middleware';
|
||||||
|
import {
|
||||||
|
ServiceTokenData
|
||||||
|
} from '../models';
|
||||||
|
import { param, body, query } from 'express-validator';
|
||||||
|
import {
|
||||||
|
SALT_ROUNDS
|
||||||
|
} from '../config';
|
||||||
|
import {
|
||||||
|
ADMIN,
|
||||||
|
MEMBER,
|
||||||
|
COMPLETED,
|
||||||
|
GRANTED
|
||||||
|
} from '../variables';
|
||||||
|
|
||||||
|
// TODO: move logic into separate controller (probably after pull with latest routing)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 different concepts that we should distinguish between:
|
||||||
|
* - API key (user) - allows user to perform queries and mutations on whatever
|
||||||
|
* their account could access (better than JWT because it has ACL and scoping).
|
||||||
|
* - Service token (bound to a workspace and environment).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service token flow?
|
||||||
|
* 1. Post service token data details including project key encrypted under <symmetric_key> on cient-side.
|
||||||
|
* 2. Construct <infisical_token> on client-side as <infisical_token>=<service_token>.<symmetric_key>
|
||||||
|
* 3. Need for CLI to be able to get back service token details
|
||||||
|
*/
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/',
|
||||||
|
requireWorkspaceAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER],
|
||||||
|
acceptedStatuses: [COMPLETED, GRANTED],
|
||||||
|
location: 'body'
|
||||||
|
}),
|
||||||
|
requireAuth,
|
||||||
|
body('name').exists().trim(),
|
||||||
|
body('workspace'),
|
||||||
|
body('environment'),
|
||||||
|
body('encryptedKey'),
|
||||||
|
body('iv'),
|
||||||
|
body('tag'),
|
||||||
|
body('expiresAt'),
|
||||||
|
validateRequest,
|
||||||
|
async (req, res) => {
|
||||||
|
let serviceToken, serviceTokenData;
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
workspace,
|
||||||
|
environment,
|
||||||
|
encryptedKey,
|
||||||
|
iv,
|
||||||
|
tag,
|
||||||
|
expiresAt
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
// create 38-char service token with first 6-char being the prefix
|
||||||
|
serviceToken = crypto.randomBytes(19).toString('hex');
|
||||||
|
|
||||||
|
const serviceTokenHash = await bcrypt.hash(serviceToken, SALT_ROUNDS);
|
||||||
|
|
||||||
|
serviceTokenData = await new ServiceTokenData({
|
||||||
|
name,
|
||||||
|
workspace,
|
||||||
|
environment,
|
||||||
|
expiresAt,
|
||||||
|
prefix: serviceToken.substring(0, 6),
|
||||||
|
serviceTokenHash,
|
||||||
|
encryptedKey,
|
||||||
|
iv,
|
||||||
|
tag
|
||||||
|
}).save();
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
Sentry.setUser({ email: req.user.email });
|
||||||
|
Sentry.captureException(err);
|
||||||
|
return res.status(400).send({
|
||||||
|
message: 'Failed to create service token data'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
serviceToken,
|
||||||
|
serviceTokenData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: CLI has to get service token details without needing a JWT
|
||||||
|
router.get(
|
||||||
|
'/:serviceTokenDataId',
|
||||||
|
requireAuth,
|
||||||
|
requireServiceTokenDataAuth,
|
||||||
|
param('serviceTokenDataId').exists().trim(),
|
||||||
|
validateRequest,
|
||||||
|
async (req, res) => {
|
||||||
|
return ({
|
||||||
|
serviceTokenData: req.serviceTokenData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
router.delete(
|
||||||
|
'/:serviceTokenDataId',
|
||||||
|
requireAuth,
|
||||||
|
requireServiceTokenDataAuth,
|
||||||
|
param('serviceTokenDataId').exists().trim(),
|
||||||
|
validateRequest,
|
||||||
|
async (req, res) => {
|
||||||
|
let serviceTokenData;
|
||||||
|
try {
|
||||||
|
const { serviceTokenDataId } = req.params;
|
||||||
|
|
||||||
|
serviceTokenData = await ServiceTokenData.findByIdAndDelete(serviceTokenDataId);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
Sentry.setUser({ email: req.user.email });
|
||||||
|
Sentry.captureException(err);
|
||||||
|
return res.status(400).send({
|
||||||
|
message: 'Failed to delete service token data'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
serviceTokenData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -119,7 +119,7 @@ router.get(
|
|||||||
);
|
);
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
'/:workspaceId/service-tokens',
|
'/:workspaceId/service-tokens', // deprecate
|
||||||
requireAuth,
|
requireAuth,
|
||||||
requireWorkspaceAuth({
|
requireWorkspaceAuth({
|
||||||
acceptedRoles: [ADMIN, MEMBER],
|
acceptedRoles: [ADMIN, MEMBER],
|
||||||
@@ -130,4 +130,16 @@ router.get(
|
|||||||
workspaceController.getWorkspaceServiceTokens
|
workspaceController.getWorkspaceServiceTokens
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/:workspaceId/service-token-data',
|
||||||
|
requireAuth,
|
||||||
|
requireWorkspaceAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER],
|
||||||
|
acceptedStatuses: [GRANTED]
|
||||||
|
}),
|
||||||
|
param('workspaceId').exists().trim(),
|
||||||
|
validateRequest,
|
||||||
|
workspaceController.getWorkspaceServiceTokenData
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
Vendored
+1
@@ -15,6 +15,7 @@ declare global {
|
|||||||
bot: any;
|
bot: any;
|
||||||
serviceToken: any;
|
serviceToken: any;
|
||||||
accessToken: any;
|
accessToken: any;
|
||||||
|
serviceTokenData: any;
|
||||||
query?: any;
|
query?: any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user