Checkpoint service account functionality, added UI and general backend structure

This commit is contained in:
Tuan Dang
2023-03-27 22:00:10 +07:00
parent 3a0ce7c084
commit d36d7bfce6
39 changed files with 1710 additions and 356 deletions
@@ -295,6 +295,7 @@ return res.status(200).send({
*/
export const getOrganizationServiceAccounts = async (req: Request, res: Response) => {
const { organizationId } = req.params;
const serviceAccounts = await ServiceAccount.find({
organization: new Types.ObjectId(organizationId)
});
@@ -1,34 +1,49 @@
import { Request, Response } from 'express';
import { Types } from 'mongoose';
import crypto from 'crypto';
import bcrypt from 'bcrypt';
import {
ServiceAccount,
ServiceAccountKey,
ServiceAccountPermission
ServiceAccountOrganizationPermissions,
ServiceAccountWorkspacePermissions
} from '../../models';
import {
validateCreateServiceAccountPermission
} from '../../helpers/serviceAccount';
import {
CreateServiceAccountDto,
AddServiceAccountPermissionDto
CreateServiceAccountDto
} from '../../interfaces/serviceAccounts/dto';
import {
PERMISSION_SA_WORKSPACE_SET,
PERMISSION_SA_SET
} from '../../variables';
import { ServiceAccountKeyNotFoundError, ValidationError } from '../../utils/errors';
import { BadRequestError, ServiceAccountNotFoundError } from '../../utils/errors';
import { getSaltRounds } from '../../config';
/**
* Return service account with id [serviceAccountId]
* @param req
* @param res
*/
export const getServiceAccount = async (req: Request, res: Response) => {
const { serviceAccountId } = req.params;
const serviceAccount = await ServiceAccount.findById(serviceAccountId);
if (!serviceAccount) {
throw ServiceAccountNotFoundError({ message: 'Failed to find service account' });
}
return res.status(200).send({
serviceAccount
});
}
/**
* Create a new service account under organization with id [organizationId]
* that has access to workspaces [workspaces]
* @param req
* @param res
* @returns
* @returns
*/
export const createServiceAccount = async (req: Request, res: Response) => {
const {
organizationId,
name,
organizationId,
publicKey,
expiresIn,
}: CreateServiceAccountDto = req.body;
@@ -38,15 +53,59 @@ export const createServiceAccount = async (req: Request, res: Response) => {
expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
}
const secret = crypto.randomBytes(16).toString('base64');
const secretHash = await bcrypt.hash(secret, getSaltRounds());
// create service account
const serviceAccount = await new ServiceAccount({
name,
organization: new Types.ObjectId(organizationId),
user: req.user,
publicKey,
expiresAt
expiresAt,
secretHash
}).save();
const serviceAccountObj = serviceAccount.toObject();
delete serviceAccountObj.secretHash;
// provision default org-level permissions for service account
const permissions = await new ServiceAccountOrganizationPermissions({
serviceAccount: serviceAccount._id
}).save();
const secretId = Buffer.from(serviceAccount._id.toString(), 'hex').toString('base64');
return res.status(200).send({
serviceAccountAccessKey: `SA.${secretId}.${secret}`,
serviceAccount: serviceAccountObj
});
}
/**
* Change name of service account with id [serviceAccountId] to [name]
* @param req
* @param res
* @returns
*/
export const changeServiceAccountName = async (req: Request, res: Response) => {
const { serviceAccountId } = req.params;
const { name } = req.body;
const serviceAccount = await ServiceAccount.findOneAndUpdate(
{
_id: new Types.ObjectId(serviceAccountId)
},
{
name
},
{
new: true
}
);
return res.status(200).send({
serviceAccount
});
@@ -78,66 +137,111 @@ export const addServiceAccountKey = async (req: Request, res: Response) => {
}
/**
* Add a permission to service account with id [serviceAccountId]
* @param req
* @param res
* Return organization-level permissions for service account with id [serviceAccountId]
* @param req
* @param res
*/
export const addServiceAccountPermission = async (req: Request, res: Response) => {
const {
name,
workspaceId,
environment
}: AddServiceAccountPermissionDto = req.body;
export const getServiceAccountOrganizationPermissions = async (req: Request, res: Response) => {
const { serviceAccountId } = req.params;
if (PERMISSION_SA_WORKSPACE_SET.has(name)) {
// case: permission named [name] is workspace-related
// some such permissions require workspaceId and environment to be present.
if (!workspaceId || !environment) {
throw ValidationError({
message: 'Failed validation that is workspace-related permission must specify a workspace and environment'
});
} else {
const serviceAccountKey = await ServiceAccountKey.findOne({
serviceAccount: req.serviceAccount._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!serviceAccountKey) throw ServiceAccountKeyNotFoundError({ message: 'Failed to find service account key' });
}
}
const serviceAccountPermission = await new ServiceAccountPermission({
serviceAccount: req.serviceAccount._id,
name,
workspace: workspaceId ? new Types.ObjectId(workspaceId) : undefined,
environment
const permissions = await ServiceAccountOrganizationPermissions.findOne({
serviceAccount: new Types.ObjectId(serviceAccountId),
});
return res.status(200).send({
serviceAccountPermission
permissions
});
}
/**
* Delete a permission from service account with id [serviceAccountId]
* Return workspace-level permissions for service account with id [serviceAccountId]
* @param req
* @param res
*/
export const deleteServiceAccountPermission = async (req: Request, res: Response) => {
const { serviceAccountPermissionId } = req.params;
// user must either be an admin/owner of the organization or they must
// have created the service account in the first place to be able to delete it
// TODO: how to delete just 1 permission?
const serviceAccountPermission = await ServiceAccountPermission.findByIdAndDelete(serviceAccountPermissionId);
export const getServiceAccountWorkspacePermissions = async (req: Request, res: Response) => {
const permissions = await ServiceAccountWorkspacePermissions.find({
serviceAccount: req.serviceAccount._id
}).populate('workspace');
return res.status(200).send({
serviceAccountPermission
permissions
});
}
/**
* Add organization permissions to service account with id [serviceAccountId]
* @param req
* @param res
*/
export const addServiceAccountOrganizationPermission = async (req: Request, res: Response) => {
const permissions = ServiceAccountOrganizationPermissions.findOne({
serviceAccount: req.serviceAccount._id
});
// TODO
return res.status(200).send({
permissions
});
}
/**
* Add a workspace permissions to service account with id [serviceAccountId]
* @param req
* @param res
*/
export const addServiceAccountWorkspacePermission = async (req: Request, res: Response) => {
const { serviceAccountId } = req.params;
const {
environment,
workspaceId,
canRead = false,
canWrite = false,
canUpdate = false,
canDelete = false
} = req.body;
if (!req.membership.workspace.environments.some((e: { name: string; slug: string }) => e.slug === environment)) {
return res.status(400).send({
message: 'Failed to validate workspace environment'
});
}
const existingPermission = await ServiceAccountWorkspacePermissions.findOne({
serviceAccount: new Types.ObjectId(serviceAccountId),
workspaceId: new Types.ObjectId(workspaceId),
environment
});
if (existingPermission) throw BadRequestError({ message: 'Failed to add workspace permission to service account due to already-existing ' });
const permissions = await new ServiceAccountWorkspacePermissions({
serviceAccount: new Types.ObjectId(serviceAccountId),
workspace: new Types.ObjectId(workspaceId),
environment,
canRead,
canWrite,
canUpdate,
canDelete
}).save();
return res.status(200).send({
permissions
});
}
/**
* Delete workspace permissions from service account with id [serviceAccountId]
* @param req
* @param res
*/
export const deleteServiceAccountWorkspacePermission = async (req: Request, res: Response) => {
const { serviceAccountWorkspacePermissionsId } = req.params;
const permissions = await ServiceAccountWorkspacePermissions.findByIdAndDelete(serviceAccountWorkspacePermissionsId);
return res.status(200).send({
permissions
});
}
@@ -156,10 +260,14 @@ export const deleteServiceAccount = async (req: Request, res: Response) => {
// case: service account with id [serviceAccountId] was deleted
await ServiceAccountKey.deleteMany({
serviceAccount: serviceAccount?._id
serviceAccount: serviceAccount._id
});
await ServiceAccountPermission.deleteMany({
await ServiceAccountOrganizationPermissions.deleteMany({
serviceAccount: new Types.ObjectId(serviceAccountId)
});
await ServiceAccountWorkspacePermissions.deleteMany({
serviceAccount: new Types.ObjectId(serviceAccountId)
});
}
-110
View File
@@ -1,110 +0,0 @@
import { Types } from 'mongoose';
import {
Workspace,
ServiceAccount,
ServiceAccountKey
} from '../models';
import {
WorkspaceNotFoundError,
ServiceAccountNotFoundError,
ServiceAccountKeyNotFoundError
} from '../utils/errors';
import {
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE,
PERMISSION_SA_SET
} from '../variables';
/**
* Validate that user with id [userId] can provision the permission
* named [name] for a service account with id [serviceAccountId] and
* optionally workspace with id [workspaceId] and environment [environment]
* @param {Object} obj
* @param {String} obj.name - name of permission to create
* @param {Types.ObjectId} userId - id of user creating the permission
* @param {Types.ObjectId} serviceAccountId - id of service account that permission will be bound to
* @param {Types.ObjectId} workspaceId - id of workspace that permission concerns
* @param {Types.ObjectId} workspaceId - id of service account that permission will be bound to
*/
const validateCreateServiceAccountPermission = async ({
name,
userId,
serviceAccountId,
workspaceId,
environment
}: {
name: string;
userId: Types.ObjectId;
serviceAccountId: Types.ObjectId,
workspaceId?: Types.ObjectId;
environment?: string;
}) => {
// TODO: as we upgrade user permissions to be more global, then we should take into account
// the user's permissions as it concerns to being able to interact with service accounts
if (!PERMISSION_SA_SET.has(name)) throw new Error(`${name} is not a valid permission name`);
if ([
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE
].includes(name)) {
if (workspaceId && environment) {
// case: either workspace id [workspaceId] or environment name [environment] is being passed in
// (i.e. validating a service account permission concerning a workspace and/or environment)
const workspace = await Workspace.findById(workspaceId);
if (!workspace) {
// case: workspace does not exist
throw WorkspaceNotFoundError({ message: 'Failed to locate workspace' });
}
if (!workspace.environments.some((env) => env.slug === environment)) {
// case: environment name [environment] is not a valid environment slug in workspace
throw Error('Failed to locate environment in workspace');
}
const serviceAccount = await ServiceAccount.findById(serviceAccountId);
if (!serviceAccount) {
// case: service account does not exist
throw ServiceAccountNotFoundError({ message: 'Failed to locate service account' });
}
const serviceAccountKey = await ServiceAccountKey.findOne({
serviceAccount: serviceAccount._id,
workspace: workspaceId
});
if (!serviceAccountKey) {
// case: service account key does not exist
throw ServiceAccountKeyNotFoundError({ message: 'Failed to locate service account key' });
}
} else {
throw new Error('Failed to validate workspace and environment for workspace-related permission');
}
}
}
const validateDeleteServiceAccountPermission = async ({
userId,
serviceAccountId,
name,
workspaceId,
environment
}: {
userId: Types.ObjectId;
serviceAccountId: Types.ObjectId;
name: string;
workspaceId: Types.ObjectId;
environment: string;
}) => {
// does the user have the authority to delete the permission?
// does the service account permission exist?
}
export {
validateCreateServiceAccountPermission
}
+2
View File
@@ -11,6 +11,7 @@ import requireIntegrationAuthorizationAuth from './requireIntegrationAuthorizati
import requireServiceTokenAuth from './requireServiceTokenAuth';
import requireServiceTokenDataAuth from './requireServiceTokenDataAuth';
import requireServiceAccountAuth from './requireServiceAccountAuth';
import requireServiceAccountWorkspacePermissionsAuth from './requireServiceAccountWorkspacePermissionsAuth';
import requireSecretAuth from './requireSecretAuth';
import requireSecretsAuth from './requireSecretsAuth';
import validateRequest from './validateRequest';
@@ -29,6 +30,7 @@ export {
requireServiceTokenAuth,
requireServiceTokenDataAuth,
requireServiceAccountAuth,
requireServiceAccountWorkspacePermissionsAuth,
requireSecretAuth,
requireSecretsAuth,
validateRequest
@@ -0,0 +1,52 @@
import { Request, Response, NextFunction } from 'express';
import { ServiceAccount, ServiceAccountWorkspacePermissions } from '../models';
import {
ServiceAccountNotFoundError
} from '../utils/errors';
import {
validateMembershipOrg
} from '../helpers/membershipOrg';
type req = 'params' | 'body' | 'query';
const requireServiceAccountWorkspacePermissionsAuth = ({
acceptedRoles,
acceptedStatuses,
location = 'params'
}: {
acceptedRoles: string[];
acceptedStatuses: string[];
location?: req;
}) => {
return async (req: Request, res: Response, next: NextFunction) => {
const serviceAccountWorkspacePermissionsId = req[location].serviceAccountWorkspacePermissionsId;
const serviceAccountWorkspacePermissions = await ServiceAccountWorkspacePermissions.findById(serviceAccountWorkspacePermissionsId);
if (!serviceAccountWorkspacePermissions) {
return next(ServiceAccountNotFoundError({ message: 'Failed to locate Service Account workspace permission' }));
}
const serviceAccount = await ServiceAccount.findById(serviceAccountWorkspacePermissions.serviceAccount);
if (!serviceAccount) {
return next(ServiceAccountNotFoundError({ message: 'Failed to locate Service Account' }));
}
if (serviceAccount.user.toString() !== req.user.id.toString()) {
// case: creator of the service account is different from
// the user on the request -> apply middleware role/status validation
await validateMembershipOrg({
userId: req.user._id,
organizationId: serviceAccount.organization,
acceptedRoles,
acceptedStatuses
});
}
req.serviceAccount = serviceAccount;
next();
}
}
export default requireServiceAccountWorkspacePermissionsAuth;
+6 -3
View File
@@ -12,7 +12,8 @@ import Secret, { ISecret } from './secret';
import ServiceToken, { IServiceToken } from './serviceToken';
import ServiceAccount, { IServiceAccount } from './serviceAccount'; // new
import ServiceAccountKey, { IServiceAccountKey } from './serviceAccountKey'; // new
import ServiceAccountPermission, { IServiceAccountPermission } from './serviceAccountPermission';
import ServiceAccountOrganizationPermissions, { IServiceAccountOrganizationPermissions } from './serviceAccountOrganizationPermission'; // new
import ServiceAccountWorkspacePermissions, { IServiceAccountWorkspacePermissions } from './serviceAccountWorkspacePermissions'; // new
import TokenData, { ITokenData } from './tokenData';
import User, { IUser } from './user';
import UserAction, { IUserAction } from './userAction';
@@ -50,8 +51,10 @@ export {
IServiceAccount,
ServiceAccountKey,
IServiceAccountKey,
ServiceAccountPermission,
IServiceAccountPermission,
ServiceAccountOrganizationPermissions,
IServiceAccountOrganizationPermissions,
ServiceAccountWorkspacePermissions,
IServiceAccountWorkspacePermissions,
TokenData,
ITokenData,
User,
+6
View File
@@ -7,6 +7,7 @@ export interface IServiceAccount extends Document {
user: Types.ObjectId;
publicKey: string;
expiresAt: Date;
secretHash: string;
}
const serviceAccountSchema = new Schema<IServiceAccount>(
@@ -31,6 +32,11 @@ const serviceAccountSchema = new Schema<IServiceAccount>(
},
expiresAt: {
type: Date
},
secretHash: {
type: String,
required: true,
select: false
}
},
{
@@ -0,0 +1,28 @@
import { Schema, model, Types, Document } from 'mongoose';
export interface IServiceAccountOrganizationPermissions extends Document {
_id: Types.ObjectId;
serviceAccount: Types.ObjectId;
canFoo: boolean;
}
const serviceAccountOrganizationPermissionsSchema = new Schema<IServiceAccountOrganizationPermissions>(
{
serviceAccount: {
type: Schema.Types.ObjectId,
ref: 'ServiceAccount',
required: true
},
canFoo: {
type: Boolean,
default: false
}
},
{
timestamps: true
}
);
const ServiceAccountOrganizationPermissions = model<IServiceAccountOrganizationPermissions>('ServiceAccountOrganizationPermissions', serviceAccountOrganizationPermissionsSchema);
export default ServiceAccountOrganizationPermissions;
@@ -1,39 +0,0 @@
import { Schema, model, Types, Document } from 'mongoose';
export interface IServiceAccountPermission extends Document {
_id: Types.ObjectId;
serviceAccount: Types.ObjectId;
name: string;
workspace?: Types.ObjectId;
environment?: string;
}
const serviceAccountPermissionSchema = new Schema<IServiceAccountPermission>(
{
serviceAccount: {
type: Schema.Types.ObjectId,
ref: 'ServiceAccount',
required: true
},
name: {
type: String,
required: true
},
workspace: {
type: Schema.Types.ObjectId,
ref: 'Workspace',
default: null
},
environment: {
type: 'String',
default: null
}
},
{
timestamps: true
}
);
const ServiceAccountPermission = model<IServiceAccountPermission>('ServiceAccountPermission', serviceAccountPermissionSchema);
export default ServiceAccountPermission;
@@ -0,0 +1,54 @@
import { Schema, model, Types, Document } from 'mongoose';
export interface IServiceAccountWorkspacePermissions extends Document {
_id: Types.ObjectId;
serviceAccount: Types.ObjectId;
workspace: Types.ObjectId;
environment: string;
canRead: boolean;
canWrite: boolean;
canUpdate: boolean;
canDelete: boolean;
}
const serviceAccountWorkspacePermissions = new Schema<IServiceAccountWorkspacePermissions>(
{
serviceAccount: {
type: Schema.Types.ObjectId,
ref: 'ServiceAccount',
required: true
},
workspace:{
type: Schema.Types.ObjectId,
ref: 'Workspace',
required: true
},
environment: {
type: String,
required: true
},
canRead: {
type: Boolean,
default: false
},
canWrite: {
type: Boolean,
default: false
},
canUpdate: {
type: Boolean,
default: false
},
canDelete: {
type: Boolean,
default: false
}
},
{
timestamps: true
}
);
const ServiceAccountWorkspacePermissions = model<IServiceAccountWorkspacePermissions>('ServiceAccountWorkspacePermissions', serviceAccountWorkspacePermissions);
export default ServiceAccountWorkspacePermissions;
+130 -34
View File
@@ -1,27 +1,45 @@
import express from 'express';
const router = express.Router();
import {
requireAuth,
requireOrganizationAuth,
requireWorkspaceAuth,
requireServiceAccountAuth,
requireServiceAccountWorkspacePermissionsAuth,
validateRequest
} from '../../middleware';
import { body } from 'express-validator';
import { param, query, body } from 'express-validator';
import {
OWNER,
ADMIN,
MEMBER,
ACCEPTED,
PERMISSION_SA_SET
ACCEPTED
} from '../../variables';
import { serviceAccountsController } from '../../controllers/v2';
router.get(
'/:serviceAccountId',
param('serviceAccountId').exists().isString().trim(),
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.getServiceAccount
);
router.post(
'/',
body('organizationId').exists().isString().trim(),
body('name').exists().isString().trim(),
body('publicKey').exists().isString().trim(),
body('expiresIn'), // measured in ms
body('expiresIn').isNumeric(), // measured in ms
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireOrganizationAuth({
acceptedRoles: [OWNER, ADMIN, MEMBER],
acceptedStatuses: [ACCEPTED],
@@ -30,17 +48,119 @@ router.post(
serviceAccountsController.createServiceAccount
);
router.post(
'/serviceAccountId/:serviceAccountId/permissions',
body('name').exists().isString().trim().custom((value) => PERMISSION_SA_SET.has(value)),
body('workspaceId').optional().isMongoId(),
body('environment').optional(),
router.patch(
'/:serviceAccountId/name',
param('serviceAccountId').exists().isString().trim(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.addServiceAccountPermission
serviceAccountsController.changeServiceAccountName
);
router.delete(
'/:serviceAccountId',
param('serviceAccountId').exists().isString().trim(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.deleteServiceAccount
);
router.get(
'/:serviceAccountId/permissions/organization',
param('serviceAccountId').exists().isString().trim(),
query('offset').exists(),
query('limit').exists(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.getServiceAccountOrganizationPermissions
);
router.get(
'/:serviceAccountId/permissions/workspace',
param('serviceAccountId').exists().isString().trim(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.getServiceAccountWorkspacePermissions
);
router.post(
'/:serviceAccountId/permissions/organization',
param('serviceAccountId').exists().isString().trim(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.addServiceAccountOrganizationPermission
);
router.post(
'/:serviceAccountId/permissions/workspace',
param('serviceAccountId').exists().isString().trim(),
body('workspaceId').exists().isString().notEmpty(),
body('environment').exists().isString().notEmpty(),
body('canRead').isBoolean().optional(),
body('canWrite').isBoolean().optional(),
body('canUpdate').isBoolean().optional(),
body('canDelete').isBoolean().optional(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
requireWorkspaceAuth({
acceptedRoles: [ADMIN, MEMBER],
location: 'body'
}),
serviceAccountsController.addServiceAccountWorkspacePermission
);
router.delete(
'/:serviceAccountId/permissions/workspace/:serviceAccountWorkspacePermissionsId',
param('serviceAccountId').exists().isString().trim(),
param('serviceAccountWorkspacePermissionsId').exists().isString().trim(),
validateRequest,
requireAuth({
acceptedAuthModes: ['jwt']
}),
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
requireServiceAccountWorkspacePermissionsAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
serviceAccountsController.deleteServiceAccountWorkspacePermission
);
// router.post(
@@ -55,28 +175,4 @@ router.post(
// serviceAccountsController.addServiceAccountKey
// );
router.delete(
'/:serviceAccountId/key/:serviceAccountKeyId',
requireServiceAccountAuth({
acceptedRoles: [OWNER, ADMIN],
acceptedStatuses: [ACCEPTED]
}),
async (req, res) => {
// TODO: delete service account key id
}
);
// TODO: create service account permission
// router.post(
// );
// TODO: delete service account permission
router.delete(
'/:serviceAccountId/service-account-permission/:serviceAccountPermissionId',
)
export default router;
+1 -1
View File
@@ -66,7 +66,7 @@ export const initSmtp = () => {
const transporter = nodemailer.createTransport(mailOpts);
transporter
.verify()
.then(() => {
.then((err) => {
Sentry.setUser(null);
Sentry.captureMessage('SMTP - Successfully connected');
})
+1 -11
View File
@@ -63,12 +63,6 @@ import {
TOKEN_EMAIL_ORG_INVITATION,
TOKEN_EMAIL_PASSWORD_RESET
} from './token';
import {
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE,
PERMISSION_SA_WORKSPACE_SET,
PERMISSION_SA_SET
} from './permissions';
export {
OWNER,
@@ -130,9 +124,5 @@ export {
TOKEN_EMAIL_CONFIRMATION,
TOKEN_EMAIL_MFA,
TOKEN_EMAIL_ORG_INVITATION,
TOKEN_EMAIL_PASSWORD_RESET,
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE,
PERMISSION_SA_WORKSPACE_SET,
PERMISSION_SA_SET
TOKEN_EMAIL_PASSWORD_RESET
};
-19
View File
@@ -1,19 +0,0 @@
const PERMISSION_SA_WORKSPACE_READ = 'read';
const PERMISSION_SA_WORKSPACE_WRITE = 'write';
const PERMISSION_SA_WORKSPACE_SET = new Set([
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE
]);
const PERMISSION_SA_SET = new Set([
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE
]);
export {
PERMISSION_SA_WORKSPACE_READ,
PERMISSION_SA_WORKSPACE_WRITE,
PERMISSION_SA_WORKSPACE_SET,
PERMISSION_SA_SET
}