mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
Add new organization endpoints to API reference
This commit is contained in:
@ -2258,6 +2258,368 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v2/users/me/organizations": {
|
||||
"get": {
|
||||
"summary": "Return organizations that current user is part of",
|
||||
"description": "Return organizations that current user is part of",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"organizations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Organization"
|
||||
},
|
||||
"description": "Organizations that user is part of"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v2/organizations/{organizationId}/memberships": {
|
||||
"get": {
|
||||
"summary": "Return organization memberships",
|
||||
"description": "Return organization memberships",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "organizationId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of organization"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memberships": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MembershipOrg"
|
||||
},
|
||||
"description": "Memberships of organization"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v2/organizations/{organizationId}/memberships/{membershipId}": {
|
||||
"patch": {
|
||||
"summary": "Update organization membership",
|
||||
"description": "Update organization membership",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "organizationId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of organization"
|
||||
},
|
||||
{
|
||||
"name": "membershipId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of organization membership to update"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
"$ref": "#/components/schemas/MembershipOrg",
|
||||
"description": "Updated organization membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "Role of organization membership - either owner, admin, or member"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete organization membership",
|
||||
"description": "Delete organization membership",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "organizationId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of organization"
|
||||
},
|
||||
{
|
||||
"name": "membershipId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of organization membership to delete"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
"$ref": "#/components/schemas/MembershipOrg",
|
||||
"description": "Deleted organization membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v2/organizations/{organizationId}/workspaces": {
|
||||
"get": {
|
||||
"summary": "Return projects in organization that user is part of",
|
||||
"description": "Return projects in organization that user is part of",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "organizationId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of organization"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"workspaces": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Project"
|
||||
},
|
||||
"description": "Projects of organization"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v2/workspace/{workspaceId}/environments": {
|
||||
"post": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "workspaceId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"environmentName": {
|
||||
"example": "any"
|
||||
},
|
||||
"environmentSlug": {
|
||||
"example": "any"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "workspaceId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"environmentName": {
|
||||
"example": "any"
|
||||
},
|
||||
"environmentSlug": {
|
||||
"example": "any"
|
||||
},
|
||||
"oldEnvironmentSlug": {
|
||||
"example": "any"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "workspaceId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"environmentSlug": {
|
||||
"example": "any"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v2/workspace/{workspaceId}/secrets": {
|
||||
"post": {
|
||||
"description": "",
|
||||
@ -2450,56 +2812,6 @@
|
||||
}
|
||||
},
|
||||
"/api/v2/workspace/{workspaceId}/memberships/{membershipId}": {
|
||||
"delete": {
|
||||
"summary": "Delete project membership",
|
||||
"description": "Delete project membership",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "workspaceId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of project"
|
||||
},
|
||||
{
|
||||
"name": "membershipId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of membership"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
"$ref": "#/components/schemas/Membership",
|
||||
"description": "Deleted membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Update project membership",
|
||||
"description": "Update project membership",
|
||||
@ -2520,7 +2832,7 @@
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of membership"
|
||||
"description": "ID of project membership to update"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -2565,6 +2877,56 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete project membership",
|
||||
"description": "Delete project membership",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "workspaceId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of project"
|
||||
},
|
||||
{
|
||||
"name": "membershipId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "ID of project membership to delete"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
"$ref": "#/components/schemas/Membership",
|
||||
"description": "Deleted membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v2/secret/batch-create/workspace/{workspaceId}/environment/{environment}": {
|
||||
@ -3131,7 +3493,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v2/api-key-data/": {
|
||||
"/api/v2/api-key/": {
|
||||
"get": {
|
||||
"description": "",
|
||||
"parameters": [],
|
||||
@ -3174,7 +3536,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v2/api-key-data/{apiKeyDataId}": {
|
||||
"/api/v2/api-key/{apiKeyDataId}": {
|
||||
"delete": {
|
||||
"description": "",
|
||||
"parameters": [
|
||||
@ -3302,6 +3664,102 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"MembershipOrg": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_id": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"publicKey": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"organization": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"example": "owner"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"example": "accepted"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Organization": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_id": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"customerId": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"Project": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "My Project"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string",
|
||||
"example": ""
|
||||
},
|
||||
"environments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "development"
|
||||
},
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"example": "dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ProjectKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -42,9 +42,10 @@ import {
|
||||
} from './routes/v1';
|
||||
import {
|
||||
users as v2UsersRouter,
|
||||
organizations as v2OrganizationsRouter,
|
||||
workspace as v2WorkspaceRouter,
|
||||
secret as v2SecretRouter, // begin to phase out
|
||||
secrets as v2SecretsRouter,
|
||||
workspace as v2WorkspaceRouter,
|
||||
serviceTokenData as v2ServiceTokenDataRouter,
|
||||
apiKeyData as v2APIKeyDataRouter,
|
||||
environment as v2EnvironmentRouter,
|
||||
@ -98,7 +99,7 @@ app.use('/api/v1/membership', v1MembershipRouter);
|
||||
app.use('/api/v1/key', v1KeyRouter);
|
||||
app.use('/api/v1/invite-org', v1InviteOrgRouter);
|
||||
app.use('/api/v1/secret', v1SecretRouter);
|
||||
app.use('/api/v1/service-token', v1ServiceTokenRouter); // stop supporting
|
||||
app.use('/api/v1/service-token', v1ServiceTokenRouter); // deprecated
|
||||
app.use('/api/v1/password', v1PasswordRouter);
|
||||
app.use('/api/v1/stripe', v1StripeRouter);
|
||||
app.use('/api/v1/integration', v1IntegrationRouter);
|
||||
@ -106,9 +107,10 @@ app.use('/api/v1/integration-auth', v1IntegrationAuthRouter);
|
||||
|
||||
// v2 routes
|
||||
app.use('/api/v2/users', v2UsersRouter);
|
||||
app.use('/api/v2/organizations', v2OrganizationsRouter);
|
||||
app.use('/api/v2/workspace', v2EnvironmentRouter);
|
||||
app.use('/api/v2/workspace', v2WorkspaceRouter); // TODO: turn into plural route
|
||||
app.use('/api/v2/secret', v2SecretRouter); // stop supporting, TODO: revise
|
||||
app.use('/api/v2/workspace', v2WorkspaceRouter);
|
||||
app.use('/api/v2/secret', v2SecretRouter); // deprecated
|
||||
app.use('/api/v2/secrets', v2SecretsRouter);
|
||||
app.use('/api/v2/service-token', v2ServiceTokenDataRouter); // TODO: turn into plural route
|
||||
app.use('/api/v2/api-key', v2APIKeyDataRouter);
|
||||
@ -128,7 +130,6 @@ app.use((req, res, next) => {
|
||||
//* Error Handling Middleware (must be after all routing logic)
|
||||
app.use(requestErrorHandler)
|
||||
|
||||
|
||||
export const server = app.listen(PORT, () => {
|
||||
getLogger("backend-main").info(`Server started listening at port ${PORT}`)
|
||||
});
|
||||
|
@ -29,12 +29,6 @@ const productToPriceMap = {
|
||||
cardAuth: STRIPE_PRODUCT_CARD_AUTH
|
||||
};
|
||||
|
||||
/**
|
||||
* Return organizations that user is part of
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const getOrganizations = async (req: Request, res: Response) => {
|
||||
let organizations;
|
||||
try {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as usersController from './usersController';
|
||||
import * as organizationsController from './organizationsController';
|
||||
import * as workspaceController from './workspaceController';
|
||||
import * as serviceTokenDataController from './serviceTokenDataController';
|
||||
import * as apiKeyDataController from './apiKeyDataController';
|
||||
@ -8,6 +9,7 @@ import * as environmentController from './environmentController';
|
||||
|
||||
export {
|
||||
usersController,
|
||||
organizationsController,
|
||||
workspaceController,
|
||||
serviceTokenDataController,
|
||||
apiKeyDataController,
|
||||
|
296
backend/src/controllers/v2/organizationsController.ts
Normal file
296
backend/src/controllers/v2/organizationsController.ts
Normal file
@ -0,0 +1,296 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import {
|
||||
MembershipOrg,
|
||||
Membership,
|
||||
Workspace
|
||||
} from '../../models';
|
||||
import { deleteMembershipOrg } from '../../helpers/membershipOrg';
|
||||
import { updateSubscriptionOrgQuantity } from '../../helpers/organization';
|
||||
|
||||
/**
|
||||
* Return memberships for organization with id [organizationId]
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
export const getOrganizationMemberships = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Return organization memberships'
|
||||
#swagger.description = 'Return organization memberships'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.parameters['organizationId'] = {
|
||||
"description": "ID of organization",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memberships": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
$ref: "#/components/schemas/MembershipOrg"
|
||||
},
|
||||
"description": "Memberships of organization"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let memberships;
|
||||
try {
|
||||
const { organizationId } = req.params;
|
||||
|
||||
memberships = await MembershipOrg.find({
|
||||
organization: organizationId
|
||||
}).populate('user', '+publicKey');
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to get organization memberships'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
memberships
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update role of membership with id [membershipId] to role [role]
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
export const updateOrganizationMembership = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Update organization membership'
|
||||
#swagger.description = 'Update organization membership'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.parameters['organizationId'] = {
|
||||
"description": "ID of organization",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.parameters['membershipId'] = {
|
||||
"description": "ID of organization membership to update",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.requestBody = {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "Role of organization membership - either owner, admin, or member",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
$ref: "#/components/schemas/MembershipOrg",
|
||||
"description": "Updated organization membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let membership;
|
||||
try {
|
||||
const { membershipId } = req.params;
|
||||
const { role } = req.body;
|
||||
|
||||
membership = await MembershipOrg.findByIdAndUpdate(
|
||||
membershipId,
|
||||
{
|
||||
role
|
||||
}, {
|
||||
new: true
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to update organization membership'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
membership
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete organization membership with id [membershipId]
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const deleteOrganizationMembership = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Delete organization membership'
|
||||
#swagger.description = 'Delete organization membership'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.parameters['organizationId'] = {
|
||||
"description": "ID of organization",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.parameters['membershipId'] = {
|
||||
"description": "ID of organization membership to delete",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
$ref: "#/components/schemas/MembershipOrg",
|
||||
"description": "Deleted organization membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let membership;
|
||||
try {
|
||||
const { membershipId } = req.params;
|
||||
|
||||
// delete organization membership
|
||||
membership = await deleteMembershipOrg({
|
||||
membershipOrgId: membershipId
|
||||
});
|
||||
|
||||
await updateSubscriptionOrgQuantity({
|
||||
organizationId: membership.organization.toString()
|
||||
});
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to delete organization membership'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
membership
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return workspaces for organization with id [organizationId] that user has
|
||||
* access to
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
export const getOrganizationWorkspaces = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Return projects in organization that user is part of'
|
||||
#swagger.description = 'Return projects in organization that user is part of'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.parameters['organizationId'] = {
|
||||
"description": "ID of organization",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"workspaces": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
$ref: "#/components/schemas/Project"
|
||||
},
|
||||
"description": "Projects of organization"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let workspaces;
|
||||
try {
|
||||
const { organizationId } = req.params;
|
||||
|
||||
const workspacesSet = new Set(
|
||||
(
|
||||
await Workspace.find(
|
||||
{
|
||||
organization: organizationId
|
||||
},
|
||||
'_id'
|
||||
)
|
||||
).map((w) => w._id.toString())
|
||||
);
|
||||
|
||||
workspaces = (
|
||||
await Membership.find({
|
||||
user: req.user._id
|
||||
}).populate('workspace')
|
||||
)
|
||||
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
||||
.map((m) => m.workspace);
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to get organization workspaces'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
workspaces
|
||||
});
|
||||
}
|
@ -1,9 +1,16 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import {
|
||||
User
|
||||
User,
|
||||
MembershipOrg
|
||||
} from '../../models';
|
||||
|
||||
/**
|
||||
* Return the current user.
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const getMe = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = "Retrieve the current user on the request"
|
||||
@ -39,11 +46,64 @@ export const getMe = async (req: Request, res: Response) => {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to get user'
|
||||
message: 'Failed to get current user'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
user
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return organizations that the current user is part of.
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
export const getMyOrganizations = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Return organizations that current user is part of'
|
||||
#swagger.description = 'Return organizations that current user is part of'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"organizations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
$ref: "#/components/schemas/Organization"
|
||||
},
|
||||
"description": "Organizations that user is part of"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let organizations;
|
||||
try {
|
||||
organizations = (
|
||||
await MembershipOrg.find({
|
||||
user: req.user._id
|
||||
}).populate('organization')
|
||||
).map((m) => m.organization);
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: "Failed to get current user's organizations"
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
organizations
|
||||
});
|
||||
}
|
@ -311,76 +311,6 @@ export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete workspace membership with id [membershipId]
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const deleteWorkspaceMembership = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Delete project membership'
|
||||
#swagger.description = 'Delete project membership'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.parameters['workspaceId'] = {
|
||||
"description": "ID of project",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.parameters['membershipId'] = {
|
||||
"description": "ID of membership",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
$ref: "#/components/schemas/Membership",
|
||||
"description": "Deleted membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let membership;
|
||||
try {
|
||||
const {
|
||||
membershipId
|
||||
} = req.params;
|
||||
|
||||
membership = await Membership.findByIdAndDelete(membershipId);
|
||||
|
||||
if (!membership) throw new Error('Failed to delete workspace membership');
|
||||
|
||||
await Key.deleteMany({
|
||||
receiver: membership.user,
|
||||
workspace: membership.workspace
|
||||
});
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to delete workspace membership'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
membership
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update role of membership with id [membershipId] to role [role]
|
||||
* @param req
|
||||
@ -403,7 +333,7 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) =>
|
||||
}
|
||||
|
||||
#swagger.parameters['membershipId'] = {
|
||||
"description": "ID of membership",
|
||||
"description": "ID of project membership to update",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
@ -467,4 +397,74 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) =>
|
||||
return res.status(200).send({
|
||||
membership
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete workspace membership with id [membershipId]
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const deleteWorkspaceMembership = async (req: Request, res: Response) => {
|
||||
/*
|
||||
#swagger.summary = 'Delete project membership'
|
||||
#swagger.description = 'Delete project membership'
|
||||
|
||||
#swagger.security = [{
|
||||
"apiKeyAuth": []
|
||||
}]
|
||||
|
||||
#swagger.parameters['workspaceId'] = {
|
||||
"description": "ID of project",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.parameters['membershipId'] = {
|
||||
"description": "ID of project membership to delete",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
#swagger.responses[200] = {
|
||||
content: {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"membership": {
|
||||
$ref: "#/components/schemas/Membership",
|
||||
"description": "Deleted membership"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
let membership;
|
||||
try {
|
||||
const {
|
||||
membershipId
|
||||
} = req.params;
|
||||
|
||||
membership = await Membership.findByIdAndDelete(membershipId);
|
||||
|
||||
if (!membership) throw new Error('Failed to delete workspace membership');
|
||||
|
||||
await Key.deleteMany({
|
||||
receiver: membership.user,
|
||||
workspace: membership.workspace
|
||||
});
|
||||
} catch (err) {
|
||||
Sentry.setUser({ email: req.user.email });
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to delete workspace membership'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).send({
|
||||
membership
|
||||
});
|
||||
}
|
@ -7,6 +7,7 @@ import { Membership, Key } from '../models';
|
||||
* @param {Object} obj
|
||||
* @param {String} obj.userId - id of user to validate
|
||||
* @param {String} obj.workspaceId - id of workspace
|
||||
* @returns {Membership} membership - membership of user with id [userId] for workspace with id [workspaceId]
|
||||
*/
|
||||
const validateMembership = async ({
|
||||
userId,
|
||||
|
@ -1,6 +1,42 @@
|
||||
import * as Sentry from '@sentry/node';
|
||||
import { Types } from 'mongoose';
|
||||
import { MembershipOrg, Workspace, Membership, Key } from '../models';
|
||||
|
||||
/**
|
||||
* Validate that user with id [userId] is a member of organization with id [organizationId]
|
||||
* and has at least one of the roles in [acceptedRoles]
|
||||
*
|
||||
*/
|
||||
const validateMembership = async ({
|
||||
userId,
|
||||
organizationId,
|
||||
acceptedRoles
|
||||
}: {
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
acceptedRoles: string[];
|
||||
}) => {
|
||||
let membership;
|
||||
try {
|
||||
membership = await MembershipOrg.findOne({
|
||||
user: new Types.ObjectId(userId),
|
||||
organization: new Types.ObjectId(organizationId)
|
||||
});
|
||||
|
||||
if (!membership) throw new Error('Failed to find organization membership');
|
||||
|
||||
if (!acceptedRoles.includes(membership.role)) {
|
||||
throw new Error('Failed to validate organization membership role');
|
||||
}
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to validate organization membership');
|
||||
}
|
||||
|
||||
return membership;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return organization membership matching criteria specified in
|
||||
* query [queryObj]
|
||||
@ -84,6 +120,8 @@ const deleteMembershipOrg = async ({
|
||||
_id: membershipOrgId
|
||||
});
|
||||
|
||||
if (!deletedMembershipOrg) throw new Error('Failed to delete organization membership');
|
||||
|
||||
// delete keys associated with organization membership
|
||||
if (deletedMembershipOrg?.user) {
|
||||
// case: organization membership had a registered user
|
||||
@ -117,4 +155,9 @@ const deleteMembershipOrg = async ({
|
||||
return deletedMembershipOrg;
|
||||
};
|
||||
|
||||
export { findMembershipOrg, addMembershipsOrg, deleteMembershipOrg };
|
||||
export {
|
||||
validateMembership,
|
||||
findMembershipOrg,
|
||||
addMembershipsOrg,
|
||||
deleteMembershipOrg
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import requireBotAuth from './requireBotAuth';
|
||||
import requireSignupAuth from './requireSignupAuth';
|
||||
import requireWorkspaceAuth from './requireWorkspaceAuth';
|
||||
import requireMembershipAuth from './requireMembershipAuth';
|
||||
import requireMembershipOrgAuth from './requireMembershipOrgAuth';
|
||||
import requireOrganizationAuth from './requireOrganizationAuth';
|
||||
import requireIntegrationAuth from './requireIntegrationAuth';
|
||||
import requireIntegrationAuthorizationAuth from './requireIntegrationAuthorizationAuth';
|
||||
@ -18,6 +19,7 @@ export {
|
||||
requireSignupAuth,
|
||||
requireWorkspaceAuth,
|
||||
requireMembershipAuth,
|
||||
requireMembershipOrgAuth,
|
||||
requireOrganizationAuth,
|
||||
requireIntegrationAuth,
|
||||
requireIntegrationAuthorizationAuth,
|
||||
|
@ -6,11 +6,12 @@ import {
|
||||
import { validateMembership } from '../helpers/membership';
|
||||
|
||||
type req = 'params' | 'body' | 'query';
|
||||
|
||||
/**
|
||||
* Validate membership with id [membershipId] and that user with id
|
||||
* [req.user._id] can modify that membership.
|
||||
* @param {Object} obj
|
||||
* @param {String[]} obj.acceptedRoles - accepted workspace roles for JWT auth
|
||||
* @param {String[]} obj.acceptedRoles - accepted workspace roles
|
||||
* @param {String[]} obj.location - location of [workspaceId] on request (e.g. params, body) for parsing
|
||||
*/
|
||||
const requireMembershipAuth = ({
|
||||
|
49
backend/src/middleware/requireMembershipOrgAuth.ts
Normal file
49
backend/src/middleware/requireMembershipOrgAuth.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { UnauthorizedRequestError } from '../utils/errors';
|
||||
import {
|
||||
MembershipOrg
|
||||
} from '../models';
|
||||
import { validateMembership } from '../helpers/membershipOrg';
|
||||
|
||||
|
||||
type req = 'params' | 'body' | 'query';
|
||||
|
||||
/**
|
||||
* Validate (organization) membership id [membershipId] and that user with id
|
||||
* [req.user._id] can modify that membership.
|
||||
* @param {Object} obj
|
||||
* @param {String[]} obj.acceptedRoles - accepted organization roles
|
||||
* @param {String[]} obj.location - location of [membershipId] on request (e.g. params, body) for parsing
|
||||
*/
|
||||
const requireMembershipOrgAuth = ({
|
||||
acceptedRoles,
|
||||
location = 'params'
|
||||
}: {
|
||||
acceptedRoles: string[];
|
||||
location?: req;
|
||||
}) => {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const { membershipId } = req[location];
|
||||
const membershipOrg = await MembershipOrg.findById(membershipId);
|
||||
|
||||
if (!membershipOrg) throw new Error('Failed to find target organization membership');
|
||||
|
||||
const targetMembership = await validateMembership({
|
||||
userId: req.user._id.toString(),
|
||||
organizationId: membershipOrg.organization.toString(),
|
||||
acceptedRoles
|
||||
});
|
||||
|
||||
req.targetMembership = targetMembership;
|
||||
|
||||
return next();
|
||||
} catch (err) {
|
||||
return next(UnauthorizedRequestError({
|
||||
message: 'Unable to validate organization membership'
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default requireMembershipOrgAuth;
|
@ -4,6 +4,8 @@ import { body, param } from 'express-validator';
|
||||
import { requireAuth, validateRequest } from '../../middleware';
|
||||
import { membershipController } from '../../controllers/v1';
|
||||
|
||||
// note: ALL DEPRECIATED (moved to api/v2/workspace/:workspaceId/memberships/:membershipId)
|
||||
|
||||
router.get( // used for old CLI (deprecate)
|
||||
'/:workspaceId/connect',
|
||||
requireAuth({
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
import { OWNER, ADMIN, MEMBER, ACCEPTED } from '../../variables';
|
||||
import { organizationController } from '../../controllers/v1';
|
||||
|
||||
router.get(
|
||||
router.get( // deprecated (moved to api/v2/users/me/organizations)
|
||||
'/',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
@ -41,7 +41,7 @@ router.get(
|
||||
organizationController.getOrganization
|
||||
);
|
||||
|
||||
router.get(
|
||||
router.get( // deprecated (moved to api/v2/organizations/:organizationId/memberships)
|
||||
'/:organizationId/users',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
@ -56,7 +56,7 @@ router.get(
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/:organizationId/my-workspaces',
|
||||
'/:organizationId/my-workspaces', // deprecated (moved to api/v2/organizations/:organizationId/workspaces)
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
}),
|
||||
|
@ -1,16 +1,18 @@
|
||||
import users from './users';
|
||||
import secret from './secret'; // stop-supporting
|
||||
import secrets from './secrets';
|
||||
import organizations from './organizations';
|
||||
import workspace from './workspace';
|
||||
import secret from './secret'; // deprecated
|
||||
import secrets from './secrets';
|
||||
import serviceTokenData from './serviceTokenData';
|
||||
import apiKeyData from './apiKeyData';
|
||||
import environment from "./environment"
|
||||
|
||||
export {
|
||||
users,
|
||||
organizations,
|
||||
workspace,
|
||||
secret,
|
||||
secrets,
|
||||
workspace,
|
||||
serviceTokenData,
|
||||
apiKeyData,
|
||||
environment
|
||||
|
80
backend/src/routes/v2/organizations.ts
Normal file
80
backend/src/routes/v2/organizations.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import express from 'express';
|
||||
const router = express.Router();
|
||||
import {
|
||||
requireAuth,
|
||||
requireOrganizationAuth,
|
||||
requireMembershipOrgAuth,
|
||||
validateRequest
|
||||
} from '../../middleware';
|
||||
import { body, param, query } from 'express-validator';
|
||||
import { OWNER, ADMIN, MEMBER, ACCEPTED } from '../../variables';
|
||||
import { organizationsController } from '../../controllers/v2';
|
||||
|
||||
// TODO: /POST to create membership
|
||||
|
||||
router.get(
|
||||
'/:organizationId/memberships',
|
||||
param('organizationId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireOrganizationAuth({
|
||||
acceptedRoles: [OWNER, ADMIN, MEMBER],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
organizationsController.getOrganizationMemberships
|
||||
);
|
||||
|
||||
router.patch(
|
||||
'/:organizationId/memberships/:membershipId',
|
||||
param('organizationId').exists().trim(),
|
||||
param('membershipId').exists().trim(),
|
||||
body('role').exists().isString().trim().isIn([ADMIN, MEMBER]),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireOrganizationAuth({
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
requireMembershipOrgAuth({
|
||||
acceptedRoles: [OWNER, ADMIN]
|
||||
}),
|
||||
organizationsController.updateOrganizationMembership
|
||||
);
|
||||
|
||||
router.delete(
|
||||
'/:organizationId/memberships/:membershipId',
|
||||
param('organizationId').exists().trim(),
|
||||
param('membershipId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireOrganizationAuth({
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
requireMembershipOrgAuth({
|
||||
acceptedRoles: [OWNER, ADMIN]
|
||||
}),
|
||||
organizationsController.deleteOrganizationMembership
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/:organizationId/workspaces',
|
||||
param('organizationId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireOrganizationAuth({
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
organizationsController.getOrganizationWorkspaces
|
||||
);
|
||||
|
||||
export default router;
|
@ -10,7 +10,7 @@ import { ADMIN, MEMBER } from '../../variables';
|
||||
import { CreateSecretRequestBody, ModifySecretRequestBody } from '../../types/secret';
|
||||
import { secretController } from '../../controllers/v2';
|
||||
|
||||
// note to devs: stop supporting
|
||||
// note to devs: stop supporting these routes [deprecated]
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
@ -13,4 +13,12 @@ router.get(
|
||||
usersController.getMe
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/me/organizations',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
usersController.getMyOrganizations
|
||||
);
|
||||
|
||||
export default router;
|
@ -83,23 +83,6 @@ router.get( // new - TODO: rewire dashboard to this route
|
||||
workspaceController.getWorkspaceMemberships
|
||||
);
|
||||
|
||||
router.delete( // TODO - rewire dashboard to this route
|
||||
'/:workspaceId/memberships/:membershipId',
|
||||
param('workspaceId').exists().trim(),
|
||||
param('membershipId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN],
|
||||
}),
|
||||
requireMembershipAuth({
|
||||
acceptedRoles: [ADMIN]
|
||||
}),
|
||||
workspaceController.deleteWorkspaceMembership
|
||||
);
|
||||
|
||||
router.patch( // TODO - rewire dashboard to this route
|
||||
'/:workspaceId/memberships/:membershipId',
|
||||
param('workspaceId').exists().trim(),
|
||||
@ -118,4 +101,21 @@ router.patch( // TODO - rewire dashboard to this route
|
||||
workspaceController.updateWorkspaceMembership
|
||||
);
|
||||
|
||||
router.delete( // TODO - rewire dashboard to this route
|
||||
'/:workspaceId/memberships/:membershipId',
|
||||
param('workspaceId').exists().trim(),
|
||||
param('membershipId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN],
|
||||
}),
|
||||
requireMembershipAuth({
|
||||
acceptedRoles: [ADMIN]
|
||||
}),
|
||||
workspaceController.deleteWorkspaceMembership
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
@ -66,6 +66,33 @@ const generateOpenAPISpec = async () => {
|
||||
workspace: '',
|
||||
role: 'admin'
|
||||
},
|
||||
MembershipOrg: {
|
||||
user: {
|
||||
_id: '',
|
||||
email: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
publicKey: '',
|
||||
updatedAt: '',
|
||||
createdAt: ''
|
||||
},
|
||||
organization: '',
|
||||
role: 'owner',
|
||||
status: 'accepted'
|
||||
},
|
||||
Organization: {
|
||||
_id: '',
|
||||
name: '',
|
||||
customerId: ''
|
||||
},
|
||||
Project: {
|
||||
name: 'My Project',
|
||||
organization: '',
|
||||
environments: [{
|
||||
name: 'development',
|
||||
slug: 'dev'
|
||||
}]
|
||||
},
|
||||
ProjectKey: {
|
||||
encryptedkey: '',
|
||||
nonce: '',
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete Membership"
|
||||
openapi: "DELETE /api/v2/organizations/{organizationId}/memberships/{membershipId}"
|
||||
---
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get Memberships"
|
||||
openapi: "GET /api/v2/organizations/{organizationId}/memberships"
|
||||
---
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Update Membership"
|
||||
openapi: "PATCH /api/v2/organizations/{organizationId}/memberships/{membershipId}"
|
||||
---
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get Projects"
|
||||
openapi: "GET /api/v2/organizations/{organizationId}/workspaces"
|
||||
---
|
@ -1,4 +1,4 @@
|
||||
---
|
||||
title: "Get Current User"
|
||||
title: "Get My User"
|
||||
openapi: "GET /api/v2/users/me"
|
||||
---
|
||||
|
4
docs/api-reference/endpoints/users/my-organizations.mdx
Normal file
4
docs/api-reference/endpoints/users/my-organizations.mdx
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get My Organizations"
|
||||
openapi: "GET /api/v2/users/me/organizations"
|
||||
---
|
@ -162,7 +162,17 @@
|
||||
{
|
||||
"group": "Users",
|
||||
"pages": [
|
||||
"api-reference/endpoints/users/me"
|
||||
"api-reference/endpoints/users/me",
|
||||
"api-reference/endpoints/users/my-organizations"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Organizations",
|
||||
"pages": [
|
||||
"api-reference/endpoints/organizations/memberships",
|
||||
"api-reference/endpoints/organizations/update-membership",
|
||||
"api-reference/endpoints/organizations/delete-membership",
|
||||
"api-reference/endpoints/organizations/workspaces"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
359
docs/spec.yaml
359
docs/spec.yaml
@ -1392,6 +1392,229 @@ paths:
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/users/me/organizations:
|
||||
get:
|
||||
summary: Return organizations that current user is part of
|
||||
description: Return organizations that current user is part of
|
||||
parameters: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
organizations:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Organization'
|
||||
description: Organizations that user is part of
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/organizations/{organizationId}/memberships:
|
||||
get:
|
||||
summary: Return organization memberships
|
||||
description: Return organization memberships
|
||||
parameters:
|
||||
- name: organizationId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of organization
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
memberships:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/MembershipOrg'
|
||||
description: Memberships of organization
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/organizations/{organizationId}/memberships/{membershipId}:
|
||||
patch:
|
||||
summary: Update organization membership
|
||||
description: Update organization membership
|
||||
parameters:
|
||||
- name: organizationId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of organization
|
||||
- name: membershipId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of organization membership to update
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
membership:
|
||||
$ref: '#/components/schemas/MembershipOrg'
|
||||
description: Updated organization membership
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
role:
|
||||
type: string
|
||||
description: >-
|
||||
Role of organization membership - either owner, admin, or
|
||||
member
|
||||
delete:
|
||||
summary: Delete organization membership
|
||||
description: Delete organization membership
|
||||
parameters:
|
||||
- name: organizationId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of organization
|
||||
- name: membershipId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of organization membership to delete
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
membership:
|
||||
$ref: '#/components/schemas/MembershipOrg'
|
||||
description: Deleted organization membership
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/organizations/{organizationId}/workspaces:
|
||||
get:
|
||||
summary: Return projects in organization that user is part of
|
||||
description: Return projects in organization that user is part of
|
||||
parameters:
|
||||
- name: organizationId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of organization
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
workspaces:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Project'
|
||||
description: Projects of organization
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/workspace/{workspaceId}/environments:
|
||||
post:
|
||||
description: ''
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad Request
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
environmentName:
|
||||
example: any
|
||||
environmentSlug:
|
||||
example: any
|
||||
put:
|
||||
description: ''
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad Request
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
environmentName:
|
||||
example: any
|
||||
environmentSlug:
|
||||
example: any
|
||||
oldEnvironmentSlug:
|
||||
example: any
|
||||
delete:
|
||||
description: ''
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad Request
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
environmentSlug:
|
||||
example: any
|
||||
/api/v2/workspace/{workspaceId}/secrets:
|
||||
post:
|
||||
description: ''
|
||||
@ -1509,37 +1732,6 @@ paths:
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/workspace/{workspaceId}/memberships/{membershipId}:
|
||||
delete:
|
||||
summary: Delete project membership
|
||||
description: Delete project membership
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of project
|
||||
- name: membershipId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of membership
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
membership:
|
||||
$ref: '#/components/schemas/Membership'
|
||||
description: Deleted membership
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
patch:
|
||||
summary: Update project membership
|
||||
description: Update project membership
|
||||
@ -1555,7 +1747,7 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of membership
|
||||
description: ID of project membership to update
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
@ -1581,6 +1773,37 @@ paths:
|
||||
role:
|
||||
type: string
|
||||
description: Role of membership - either admin or member
|
||||
delete:
|
||||
summary: Delete project membership
|
||||
description: Delete project membership
|
||||
parameters:
|
||||
- name: workspaceId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of project
|
||||
- name: membershipId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: ID of project membership to delete
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
membership:
|
||||
$ref: '#/components/schemas/Membership'
|
||||
description: Deleted membership
|
||||
'400':
|
||||
description: Bad Request
|
||||
security:
|
||||
- apiKeyAuth: []
|
||||
/api/v2/secret/batch-create/workspace/{workspaceId}/environment/{environment}:
|
||||
post:
|
||||
description: ''
|
||||
@ -1927,7 +2150,7 @@ paths:
|
||||
description: OK
|
||||
'400':
|
||||
description: Bad Request
|
||||
/api/v2/api-key-data/:
|
||||
/api/v2/api-key/:
|
||||
get:
|
||||
description: ''
|
||||
parameters: []
|
||||
@ -1954,7 +2177,7 @@ paths:
|
||||
example: any
|
||||
expiresIn:
|
||||
example: any
|
||||
/api/v2/api-key-data/{apiKeyDataId}:
|
||||
/api/v2/api-key/{apiKeyDataId}:
|
||||
delete:
|
||||
description: ''
|
||||
parameters:
|
||||
@ -2043,6 +2266,74 @@ components:
|
||||
role:
|
||||
type: string
|
||||
example: admin
|
||||
MembershipOrg:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
type: object
|
||||
properties:
|
||||
_id:
|
||||
type: string
|
||||
example: ''
|
||||
email:
|
||||
type: string
|
||||
example: ''
|
||||
firstName:
|
||||
type: string
|
||||
example: ''
|
||||
lastName:
|
||||
type: string
|
||||
example: ''
|
||||
publicKey:
|
||||
type: string
|
||||
example: ''
|
||||
updatedAt:
|
||||
type: string
|
||||
example: ''
|
||||
createdAt:
|
||||
type: string
|
||||
example: ''
|
||||
organization:
|
||||
type: string
|
||||
example: ''
|
||||
role:
|
||||
type: string
|
||||
example: owner
|
||||
status:
|
||||
type: string
|
||||
example: accepted
|
||||
Organization:
|
||||
type: object
|
||||
properties:
|
||||
_id:
|
||||
type: string
|
||||
example: ''
|
||||
name:
|
||||
type: string
|
||||
example: ''
|
||||
customerId:
|
||||
type: string
|
||||
example: ''
|
||||
Project:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: My Project
|
||||
organization:
|
||||
type: string
|
||||
example: ''
|
||||
environments:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: development
|
||||
slug:
|
||||
type: string
|
||||
example: dev
|
||||
ProjectKey:
|
||||
type: object
|
||||
properties:
|
||||
|
Reference in New Issue
Block a user