From ec761c238712d4ac04cebbc0763caad596a74ad9 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 4 Aug 2023 18:01:45 +0100 Subject: [PATCH] Building out public API for role assignment and un-assignment - need to flesh out pro component. --- packages/server/specs/openapi.json | 275 ++++++++++++------ packages/server/specs/openapi.yaml | 195 ++++++++----- packages/server/specs/resources/index.ts | 2 + packages/server/specs/resources/roles.ts | 65 +++++ packages/server/specs/resources/user.ts | 32 -- .../src/api/controllers/public/roles.ts | 15 + .../server/src/api/routes/public/roles.ts | 54 ++++ packages/server/src/definitions/openapi.ts | 133 ++++++--- 8 files changed, 545 insertions(+), 226 deletions(-) create mode 100644 packages/server/specs/resources/roles.ts create mode 100644 packages/server/src/api/controllers/public/roles.ts create mode 100644 packages/server/src/api/routes/public/roles.ts diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index d97b09568c..1071a39c29 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -1519,34 +1519,6 @@ "forceResetPassword": { "description": "If set to true forces the user to reset their password on first login.", "type": "boolean" - }, - "builder": { - "description": "Describes if the user is a builder user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to build any app in the system.", - "type": "boolean" - } - } - }, - "admin": { - "description": "Describes if the user is an admin user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to administrate the system.", - "type": "boolean" - } - } - }, - "roles": { - "description": "Contains the roles of the user per app (assuming they are not a builder user).", - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN." - } } }, "required": [ @@ -1587,34 +1559,6 @@ "description": "If set to true forces the user to reset their password on first login.", "type": "boolean" }, - "builder": { - "description": "Describes if the user is a builder user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to build any app in the system.", - "type": "boolean" - } - } - }, - "admin": { - "description": "Describes if the user is an admin user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to administrate the system.", - "type": "boolean" - } - } - }, - "roles": { - "description": "Contains the roles of the user per app (assuming they are not a builder user).", - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN." - } - }, "_id": { "description": "The ID of the user.", "type": "string" @@ -1666,34 +1610,6 @@ "description": "If set to true forces the user to reset their password on first login.", "type": "boolean" }, - "builder": { - "description": "Describes if the user is a builder user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to build any app in the system.", - "type": "boolean" - } - } - }, - "admin": { - "description": "Describes if the user is an admin user or not.", - "type": "object", - "properties": { - "global": { - "description": "If set to true the user will be able to administrate the system.", - "type": "boolean" - } - } - }, - "roles": { - "description": "Contains the roles of the user per app (assuming they are not a builder user).", - "type": "object", - "additionalProperties": { - "type": "string", - "description": "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN." - } - }, "_id": { "description": "The ID of the user.", "type": "string" @@ -1833,6 +1749,135 @@ "required": [ "name" ] + }, + "rolesAssign": { + "type": "object", + "properties": { + "builder": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global builder permissions from the list of users.", + "required": [ + "global" + ] + }, + "admin": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global admin permissions from the list of users.", + "required": [ + "global" + ] + }, + "role": { + "type": "object", + "properties": { + "roleId": { + "description": "The role ID, such as BASIC, ADMIN or a custom role ID.", + "type": "string" + }, + "appId": { + "description": "The app that the role relates to.", + "type": "string" + } + }, + "description": "Add/remove a per-app role, such as BASIC, ADMIN etc.", + "required": [ + "roleId", + "appId" + ] + }, + "userIds": { + "description": "The user IDs to be updated to add/remove the specified roles.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "userIds" + ] + }, + "rolesUnAssign": { + "type": "object", + "properties": { + "builder": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global builder permissions from the list of users.", + "required": [ + "global" + ] + }, + "admin": { + "type": "object", + "properties": { + "global": { + "type": "boolean" + } + }, + "description": "Add/remove global admin permissions from the list of users.", + "required": [ + "global" + ] + }, + "role": { + "type": "object", + "properties": { + "roleId": { + "description": "The role ID, such as BASIC, ADMIN or a custom role ID.", + "type": "string" + }, + "appId": { + "description": "The app that the role relates to.", + "type": "string" + } + }, + "description": "Add/remove a per-app role, such as BASIC, ADMIN etc.", + "required": [ + "roleId", + "appId" + ] + }, + "userIds": { + "description": "The user IDs to be updated to add/remove the specified roles.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "userIds" + ] + }, + "rolesOutput": { + "type": "object", + "properties": { + "userIds": { + "description": "The updated users' IDs", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "userIds" + ] } } }, @@ -2186,6 +2231,68 @@ } } }, + "/roles/assign": { + "post": { + "operationId": "roleAssign", + "summary": "Assign a role to a list of users", + "tags": [ + "roles" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesAssign" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a list of updated user IDs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesOutput" + } + } + } + } + } + } + }, + "/roles/unassign": { + "post": { + "operationId": "roleUnAssign", + "summary": "Un-assign a role from a list of users", + "tags": [ + "roles" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUnAssign" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a list of updated user IDs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesOutput" + } + } + } + } + } + } + }, "/tables/{tableId}/rows": { "post": { "operationId": "rowCreate", diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 86807c9981..aa7b3ddb51 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -1296,29 +1296,6 @@ components: description: If set to true forces the user to reset their password on first login. type: boolean - builder: - description: Describes if the user is a builder user or not. - type: object - properties: - global: - description: If set to true the user will be able to build any app in the - system. - type: boolean - admin: - description: Describes if the user is an admin user or not. - type: object - properties: - global: - description: If set to true the user will be able to administrate the system. - type: boolean - roles: - description: Contains the roles of the user per app (assuming they are not a - builder user). - type: object - additionalProperties: - type: string - description: A map of app ID (production app ID, minus the _dev component) to a - role ID, e.g. ADMIN. required: - email - roles @@ -1351,29 +1328,6 @@ components: description: If set to true forces the user to reset their password on first login. type: boolean - builder: - description: Describes if the user is a builder user or not. - type: object - properties: - global: - description: If set to true the user will be able to build any app in the - system. - type: boolean - admin: - description: Describes if the user is an admin user or not. - type: object - properties: - global: - description: If set to true the user will be able to administrate the system. - type: boolean - roles: - description: Contains the roles of the user per app (assuming they are not a - builder user). - type: object - additionalProperties: - type: string - description: A map of app ID (production app ID, minus the _dev component) to a - role ID, e.g. ADMIN. _id: description: The ID of the user. type: string @@ -1414,29 +1368,6 @@ components: description: If set to true forces the user to reset their password on first login. type: boolean - builder: - description: Describes if the user is a builder user or not. - type: object - properties: - global: - description: If set to true the user will be able to build any app in the - system. - type: boolean - admin: - description: Describes if the user is an admin user or not. - type: object - properties: - global: - description: If set to true the user will be able to administrate the system. - type: boolean - roles: - description: Contains the roles of the user per app (assuming they are not a - builder user). - type: object - additionalProperties: - type: string - description: A map of app ID (production app ID, minus the _dev component) to a - role ID, e.g. ADMIN. _id: description: The ID of the user. type: string @@ -1547,6 +1478,94 @@ components: insensitive starts with match. required: - name + rolesAssign: + type: object + properties: + builder: + type: object + properties: + global: + type: boolean + description: Add/remove global builder permissions from the list of users. + required: + - global + admin: + type: object + properties: + global: + type: boolean + description: Add/remove global admin permissions from the list of users. + required: + - global + role: + type: object + properties: + roleId: + description: The role ID, such as BASIC, ADMIN or a custom role ID. + type: string + appId: + description: The app that the role relates to. + type: string + description: Add/remove a per-app role, such as BASIC, ADMIN etc. + required: + - roleId + - appId + userIds: + description: The user IDs to be updated to add/remove the specified roles. + type: array + items: + type: string + required: + - userIds + rolesUnAssign: + type: object + properties: + builder: + type: object + properties: + global: + type: boolean + description: Add/remove global builder permissions from the list of users. + required: + - global + admin: + type: object + properties: + global: + type: boolean + description: Add/remove global admin permissions from the list of users. + required: + - global + role: + type: object + properties: + roleId: + description: The role ID, such as BASIC, ADMIN or a custom role ID. + type: string + appId: + description: The app that the role relates to. + type: string + description: Add/remove a per-app role, such as BASIC, ADMIN etc. + required: + - roleId + - appId + userIds: + description: The user IDs to be updated to add/remove the specified roles. + type: array + items: + type: string + required: + - userIds + rolesOutput: + type: object + properties: + userIds: + description: The updated users' IDs + type: array + items: + type: string + required: + - userIds security: - ApiKeyAuth: [] paths: @@ -1757,6 +1776,44 @@ paths: examples: queries: $ref: "#/components/examples/queries" + /roles/assign: + post: + operationId: roleAssign + summary: Assign a role to a list of users + tags: + - roles + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/rolesAssign" + responses: + "200": + description: Returns a list of updated user IDs + content: + application/json: + schema: + $ref: "#/components/schemas/rolesOutput" + /roles/unassign: + post: + operationId: roleUnAssign + summary: Un-assign a role from a list of users + tags: + - roles + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/rolesUnAssign" + responses: + "200": + description: Returns a list of updated user IDs + content: + application/json: + schema: + $ref: "#/components/schemas/rolesOutput" "/tables/{tableId}/rows": post: operationId: rowCreate diff --git a/packages/server/specs/resources/index.ts b/packages/server/specs/resources/index.ts index 6b8a1aa437..c06148b7de 100644 --- a/packages/server/specs/resources/index.ts +++ b/packages/server/specs/resources/index.ts @@ -5,6 +5,7 @@ import query from "./query" import user from "./user" import metrics from "./metrics" import misc from "./misc" +import roles from "./roles" export const examples = { ...application.getExamples(), @@ -23,4 +24,5 @@ export const schemas = { ...query.getSchemas(), ...user.getSchemas(), ...misc.getSchemas(), + ...roles.getSchemas(), } diff --git a/packages/server/specs/resources/roles.ts b/packages/server/specs/resources/roles.ts new file mode 100644 index 0000000000..02254261be --- /dev/null +++ b/packages/server/specs/resources/roles.ts @@ -0,0 +1,65 @@ +import { object } from "./utils" +import Resource from "./utils/Resource" + +const roleSchema = object( + { + builder: object( + { + global: { + type: "boolean", + }, + }, + { + description: + "Add/remove global builder permissions from the list of users.", + } + ), + admin: object( + { + global: { + type: "boolean", + }, + }, + { + description: + "Add/remove global admin permissions from the list of users.", + } + ), + role: object( + { + roleId: { + description: "The role ID, such as BASIC, ADMIN or a custom role ID.", + type: "string", + }, + appId: { + description: "The app that the role relates to.", + type: "string", + }, + }, + { description: "Add/remove a per-app role, such as BASIC, ADMIN etc." } + ), + userIds: { + description: + "The user IDs to be updated to add/remove the specified roles.", + type: "array", + items: { + type: "string", + }, + }, + }, + { required: ["userIds"] } +) + +export default new Resource().setSchemas({ + rolesAssign: roleSchema, + rolesUnAssign: roleSchema, + rolesOutput: object({ + userIds: { + description: "The updated users' IDs", + type: "array", + items: { + type: "string", + }, + }, + }), +}) diff --git a/packages/server/specs/resources/user.ts b/packages/server/specs/resources/user.ts index a7b9f1ddb9..9ec5388672 100644 --- a/packages/server/specs/resources/user.ts +++ b/packages/server/specs/resources/user.ts @@ -57,38 +57,6 @@ const userSchema = object( "If set to true forces the user to reset their password on first login.", type: "boolean", }, - builder: { - description: "Describes if the user is a builder user or not.", - type: "object", - properties: { - global: { - description: - "If set to true the user will be able to build any app in the system.", - type: "boolean", - }, - }, - }, - admin: { - description: "Describes if the user is an admin user or not.", - type: "object", - properties: { - global: { - description: - "If set to true the user will be able to administrate the system.", - type: "boolean", - }, - }, - }, - roles: { - description: - "Contains the roles of the user per app (assuming they are not a builder user).", - type: "object", - additionalProperties: { - type: "string", - description: - "A map of app ID (production app ID, minus the _dev component) to a role ID, e.g. ADMIN.", - }, - }, }, { required: ["email", "roles"] } ) diff --git a/packages/server/src/api/controllers/public/roles.ts b/packages/server/src/api/controllers/public/roles.ts new file mode 100644 index 0000000000..3b70094ae1 --- /dev/null +++ b/packages/server/src/api/controllers/public/roles.ts @@ -0,0 +1,15 @@ +import { UserCtx } from "@budibase/types" +import { Next } from "koa" + +async function assign(ctx: UserCtx, next: Next) { + ctx.body = { message: "roles assigned" } +} + +async function unAssign(ctx: UserCtx, next: Next) { + ctx.body = { message: "roles un-assigned" } +} + +export default { + assign, + unAssign, +} diff --git a/packages/server/src/api/routes/public/roles.ts b/packages/server/src/api/routes/public/roles.ts new file mode 100644 index 0000000000..2332a0ffd0 --- /dev/null +++ b/packages/server/src/api/routes/public/roles.ts @@ -0,0 +1,54 @@ +import controller from "../../controllers/public/roles" +import Endpoint from "./utils/Endpoint" + +const write = [] + +/** + * @openapi + * /roles/assign: + * post: + * operationId: roleAssign + * summary: Assign a role to a list of users + * tags: + * - roles + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesAssign' + * responses: + * 200: + * description: Returns a list of updated user IDs + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesOutput' + */ +write.push(new Endpoint("post", "/roles/assign", controller.assign)) + +/** + * @openapi + * /roles/unassign: + * post: + * operationId: roleUnAssign + * summary: Un-assign a role from a list of users + * tags: + * - roles + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesUnAssign' + * responses: + * 200: + * description: Returns a list of updated user IDs + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rolesOutput' + */ +write.push(new Endpoint("post", "/roles/unassign", controller.unAssign)) + +export default { write, read: [] } diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index 5ca4990647..ee078d0821 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -34,6 +34,12 @@ export interface paths { /** Based on query properties (currently only name) search for queries. */ post: operations["querySearch"]; }; + "/roles/assign": { + post: operations["roleAssign"]; + }; + "/roles/unassign": { + post: operations["roleUnAssign"]; + }; "/tables/{tableId}/rows": { /** Creates a row within the specified table. */ post: operations["rowCreate"]; @@ -256,7 +262,8 @@ export interface components { | "auto" | "json" | "internal" - | "barcodeqr"; + | "barcodeqr" + | "bigint"; /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ constraints?: { /** @enum {string} */ @@ -362,7 +369,8 @@ export interface components { | "auto" | "json" | "internal" - | "barcodeqr"; + | "barcodeqr" + | "bigint"; /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ constraints?: { /** @enum {string} */ @@ -470,7 +478,8 @@ export interface components { | "auto" | "json" | "internal" - | "barcodeqr"; + | "barcodeqr" + | "bigint"; /** @description A constraint can be applied to the column which will be validated against when a row is saved. */ constraints?: { /** @enum {string} */ @@ -577,18 +586,8 @@ export interface components { lastName?: string; /** @description If set to true forces the user to reset their password on first login. */ forceResetPassword?: boolean; - /** @description Describes if the user is a builder user or not. */ - builder?: { - /** @description If set to true the user will be able to build any app in the system. */ - global?: boolean; - }; - /** @description Describes if the user is an admin user or not. */ - admin?: { - /** @description If set to true the user will be able to administrate the system. */ - global?: boolean; - }; - /** @description Contains the roles of the user per app (assuming they are not a builder user). */ - roles: { [key: string]: string }; + } & { + roles: unknown; }; userOutput: { data: { @@ -607,24 +606,14 @@ export interface components { lastName?: string; /** @description If set to true forces the user to reset their password on first login. */ forceResetPassword?: boolean; - /** @description Describes if the user is a builder user or not. */ - builder?: { - /** @description If set to true the user will be able to build any app in the system. */ - global?: boolean; - }; - /** @description Describes if the user is an admin user or not. */ - admin?: { - /** @description If set to true the user will be able to administrate the system. */ - global?: boolean; - }; - /** @description Contains the roles of the user per app (assuming they are not a builder user). */ - roles: { [key: string]: string }; /** @description The ID of the user. */ _id: string; + } & { + roles: unknown; }; }; userSearch: { - data: { + data: ({ /** @description The email address of the user, this must be unique. */ email: string; /** @description The password of the user if using password based login - this will never be returned. This can be left out of subsequent requests (updates) and will be enriched back into the user structure. */ @@ -640,21 +629,11 @@ export interface components { lastName?: string; /** @description If set to true forces the user to reset their password on first login. */ forceResetPassword?: boolean; - /** @description Describes if the user is a builder user or not. */ - builder?: { - /** @description If set to true the user will be able to build any app in the system. */ - global?: boolean; - }; - /** @description Describes if the user is an admin user or not. */ - admin?: { - /** @description If set to true the user will be able to administrate the system. */ - global?: boolean; - }; - /** @description Contains the roles of the user per app (assuming they are not a builder user). */ - roles: { [key: string]: string }; /** @description The ID of the user. */ _id: string; - }[]; + } & { + roles: unknown; + })[]; }; rowSearch: { query: { @@ -712,6 +691,48 @@ export interface components { /** @description The name to be used when searching - this will be used in a case insensitive starts with match. */ name: string; }; + rolesAssign: { + /** @description Add/remove global builder permissions from the list of users. */ + builder?: { + global: boolean; + }; + /** @description Add/remove global admin permissions from the list of users. */ + admin?: { + global: boolean; + }; + /** @description Add/remove a per-app role, such as BASIC, ADMIN etc. */ + role?: { + /** @description The role ID, such as BASIC, ADMIN or a custom role ID. */ + roleId: string; + /** @description The app that the role relates to. */ + appId: string; + }; + /** @description The user IDs to be updated to add/remove the specified roles. */ + userIds: string[]; + }; + rolesUnAssign: { + /** @description Add/remove global builder permissions from the list of users. */ + builder?: { + global: boolean; + }; + /** @description Add/remove global admin permissions from the list of users. */ + admin?: { + global: boolean; + }; + /** @description Add/remove a per-app role, such as BASIC, ADMIN etc. */ + role?: { + /** @description The role ID, such as BASIC, ADMIN or a custom role ID. */ + roleId: string; + /** @description The app that the role relates to. */ + appId: string; + }; + /** @description The user IDs to be updated to add/remove the specified roles. */ + userIds: string[]; + }; + rolesOutput: { + /** @description The updated users' IDs */ + userIds: string[]; + }; }; parameters: { /** @description The ID of the table which this request is targeting. */ @@ -907,6 +928,36 @@ export interface operations { }; }; }; + roleAssign: { + responses: { + /** Returns a list of updated user IDs */ + 200: { + content: { + "application/json": components["schemas"]["rolesOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["rolesAssign"]; + }; + }; + }; + roleUnAssign: { + responses: { + /** Returns a list of updated user IDs */ + 200: { + content: { + "application/json": components["schemas"]["rolesOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["rolesUnAssign"]; + }; + }; + }; /** Creates a row within the specified table. */ rowCreate: { parameters: {