From eed4111fe2aaebe88920effcd4d77d44144f0c8c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 25 Feb 2022 19:26:19 +0000 Subject: [PATCH] Rounding out user schema and query schema as required. --- packages/server/specs/openapi.json | 164 +++++++++++++++--- packages/server/specs/openapi.yaml | 119 +++++++++++-- packages/server/specs/resources/query.js | 16 +- packages/server/specs/resources/user.js | 66 ++++++- .../src/api/controllers/public/users.ts | 8 + .../server/src/api/routes/public/users.ts | 7 - 6 files changed, 338 insertions(+), 42 deletions(-) diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index b89bd0617b..45ec142fd9 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -940,19 +940,158 @@ ] }, "query": { + "description": "The query body must contain the required parameters for the query, this depends on query type, setup and bindings.", "type": "object", - "properties": {} + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object" + }, + { + "type": "integer" + }, + { + "type": "array" + }, + { + "type": "boolean" + } + ] + } }, "user": { "type": "object", - "properties": {} + "properties": { + "email": { + "description": "The email address of the user, this must be unique.", + "type": "string" + }, + "password": { + "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.", + "type": "string" + }, + "status": { + "description": "The status of the user, if they are active.", + "type": "string", + "enum": [ + "active" + ] + }, + "firstName": { + "description": "The first name of the user", + "type": "string" + }, + "lastName": { + "description": "The last name of the user", + "type": "string" + }, + "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": [ + "email", + "roles" + ] }, "userOutput": { "type": "object", "properties": { "user": { "type": "object", - "properties": {} + "properties": { + "email": { + "description": "The email address of the user, this must be unique.", + "type": "string" + }, + "password": { + "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.", + "type": "string" + }, + "status": { + "description": "The status of the user, if they are active.", + "type": "string", + "enum": [ + "active" + ] + }, + "firstName": { + "description": "The first name of the user", + "type": "string" + }, + "lastName": { + "description": "The last name of the user", + "type": "string" + }, + "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": [ + "email", + "roles" + ] } }, "required": [ @@ -1832,11 +1971,6 @@ "tags": [ "users" ], - "parameters": [ - { - "$ref": "#/components/parameters/appId" - } - ], "requestBody": { "required": true, "content": { @@ -1875,9 +2009,6 @@ "parameters": [ { "$ref": "#/components/parameters/userId" - }, - { - "$ref": "#/components/parameters/appId" } ], "requestBody": { @@ -1916,9 +2047,6 @@ "parameters": [ { "$ref": "#/components/parameters/userId" - }, - { - "$ref": "#/components/parameters/appId" } ], "responses": { @@ -1947,9 +2075,6 @@ "parameters": [ { "$ref": "#/components/parameters/userId" - }, - { - "$ref": "#/components/parameters/appId" } ], "responses": { @@ -1977,11 +2102,6 @@ "tags": [ "users" ], - "parameters": [ - { - "$ref": "#/components/parameters/appId" - } - ], "requestBody": { "required": true, "content": { diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index a8b2ed4a45..f7059fcc8e 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -688,17 +688,123 @@ components: required: - table query: + description: The query body must contain the required parameters for the query, + this depends on query type, setup and bindings. type: object - properties: {} + additionalProperties: + oneOf: + - type: string + - type: object + - type: integer + - type: array + - type: boolean user: type: object - properties: {} + properties: + email: + description: The email address of the user, this must be unique. + type: string + password: + 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. + type: string + status: + description: The status of the user, if they are active. + type: string + enum: + - active + firstName: + description: The first name of the user + type: string + lastName: + description: The last name of the user + type: string + 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: + - email + - roles userOutput: type: object properties: user: type: object - properties: {} + properties: + email: + description: The email address of the user, this must be unique. + type: string + password: + 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. + type: string + status: + description: The status of the user, if they are active. + type: string + enum: + - active + firstName: + description: The first name of the user + type: string + lastName: + description: The last name of the user + type: string + 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: + - email + - roles required: - user nameSearch: @@ -1236,8 +1342,6 @@ paths: summary: Create a new user in the Budibase portal. tags: - users - parameters: - - $ref: "#/components/parameters/appId" requestBody: required: true content: @@ -1261,7 +1365,6 @@ paths: - users parameters: - $ref: "#/components/parameters/userId" - - $ref: "#/components/parameters/appId" requestBody: required: true content: @@ -1284,7 +1387,6 @@ paths: - users parameters: - $ref: "#/components/parameters/userId" - - $ref: "#/components/parameters/appId" responses: "200": description: Returns the deleted user. @@ -1301,7 +1403,6 @@ paths: - users parameters: - $ref: "#/components/parameters/userId" - - $ref: "#/components/parameters/appId" responses: "200": description: Returns the retrieved user. @@ -1317,8 +1418,6 @@ paths: summary: Search for a user based on their email/username. tags: - users - parameters: - - $ref: "#/components/parameters/appId" requestBody: required: true content: diff --git a/packages/server/specs/resources/query.js b/packages/server/specs/resources/query.js index c1f9f1ff83..056c7e785f 100644 --- a/packages/server/specs/resources/query.js +++ b/packages/server/specs/resources/query.js @@ -1,4 +1,3 @@ -const { object } = require("./utils") const Resource = require("./utils/Resource") const query = { @@ -74,7 +73,20 @@ const sqlResponse = { }, } -const querySchema = object({}) +const querySchema = { + description: + "The query body must contain the required parameters for the query, this depends on query type, setup and bindings.", + type: "object", + additionalProperties: { + oneOf: [ + { type: "string" }, + { type: "object" }, + { type: "integer" }, + { type: "array" }, + { type: "boolean" }, + ], + }, +} module.exports = new Resource() .setExamples({ diff --git a/packages/server/specs/resources/user.js b/packages/server/specs/resources/user.js index f41bd6d7f3..15900bf99d 100644 --- a/packages/server/specs/resources/user.js +++ b/packages/server/specs/resources/user.js @@ -27,7 +27,71 @@ const user = { }, } -const userSchema = object({}) +const userSchema = object( + { + email: { + description: "The email address of the user, this must be unique.", + type: "string", + }, + password: { + 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.", + type: "string", + }, + status: { + description: "The status of the user, if they are active.", + type: "string", + enum: ["active"], + }, + firstName: { + description: "The first name of the user", + type: "string", + }, + lastName: { + description: "The last name of the user", + type: "string", + }, + 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: ["email", "roles"] } +) module.exports = new Resource() .setExamples({ diff --git a/packages/server/src/api/controllers/public/users.ts b/packages/server/src/api/controllers/public/users.ts index c8728c7de7..112369d84c 100644 --- a/packages/server/src/api/controllers/public/users.ts +++ b/packages/server/src/api/controllers/public/users.ts @@ -5,6 +5,7 @@ import { deleteGlobalUser, } from "../../../utilities/workerRequests" import { search as stringSearch } from "./utils" +const { getProdAppID } = require("@budibase/backend-core/db") function fixUser(ctx: any) { if (!ctx.request.body) { @@ -15,6 +16,13 @@ function fixUser(ctx: any) { } if (!ctx.request.body.roles) { ctx.request.body.roles = {} + } else { + const newRoles: { [key: string]: string } = {} + for (let [appId, role] of Object.entries(ctx.request.body.roles)) { + // @ts-ignore + newRoles[getProdAppID(appId)] = role + } + ctx.request.body.roles = newRoles } return ctx } diff --git a/packages/server/src/api/routes/public/users.ts b/packages/server/src/api/routes/public/users.ts index 3f500c074f..b603cb7a13 100644 --- a/packages/server/src/api/routes/public/users.ts +++ b/packages/server/src/api/routes/public/users.ts @@ -12,8 +12,6 @@ const read = [], * summary: Create a new user in the Budibase portal. * tags: * - users - * parameters: - * - $ref: '#/components/parameters/appId' * requestBody: * required: true * content: @@ -42,7 +40,6 @@ write.push(new Endpoint("post", "/users", controller.create)) * - users * parameters: * - $ref: '#/components/parameters/userId' - * - $ref: '#/components/parameters/appId' * requestBody: * required: true * content: @@ -71,7 +68,6 @@ write.push(new Endpoint("put", "/users/:userId", controller.update)) * - users * parameters: * - $ref: '#/components/parameters/userId' - * - $ref: '#/components/parameters/appId' * responses: * 200: * description: Returns the deleted user. @@ -94,7 +90,6 @@ write.push(new Endpoint("delete", "/users/:userId", controller.destroy)) * - users * parameters: * - $ref: '#/components/parameters/userId' - * - $ref: '#/components/parameters/appId' * responses: * 200: * description: Returns the retrieved user. @@ -115,8 +110,6 @@ read.push(new Endpoint("get", "/users/:userId", controller.read)) * summary: Search for a user based on their email/username. * tags: * - users - * parameters: - * - $ref: '#/components/parameters/appId' * requestBody: * required: true * content: