From 79b34121a4a1c043840851498237fd96ebbbea82 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Thu, 6 Jul 2023 08:24:46 +0200 Subject: [PATCH] feat: openapi schema for user admin (#4146) --- src/lib/error/bad-data-error.ts | 2 +- src/lib/openapi/index.ts | 2 + src/lib/openapi/meta-schema-rules.test.ts | 10 - .../spec/create-user-response-schema.ts | 34 + src/lib/openapi/spec/create-user-schema.ts | 30 +- src/lib/openapi/spec/id-schema.ts | 3 + src/lib/openapi/spec/index.ts | 1 + src/lib/openapi/spec/password-schema.ts | 9 + src/lib/openapi/spec/update-user-schema.ts | 21 +- src/lib/openapi/spec/user-schema.ts | 7 + src/lib/openapi/spec/users-schema.ts | 4 + src/lib/routes/admin-api/user-admin.ts | 149 ++- src/lib/services/user-service.ts | 2 +- src/test/e2e/api/admin/user-admin.e2e.test.ts | 10 +- .../__snapshots__/openapi.e2e.test.ts.snap | 1014 ++++++++++++++++- .../api/legacy/unleash/admin/user-admin.md | 2 +- 16 files changed, 1253 insertions(+), 47 deletions(-) create mode 100644 src/lib/openapi/spec/create-user-response-schema.ts diff --git a/src/lib/error/bad-data-error.ts b/src/lib/error/bad-data-error.ts index 2c1f61aec9..d5dd4792b2 100644 --- a/src/lib/error/bad-data-error.ts +++ b/src/lib/error/bad-data-error.ts @@ -16,7 +16,7 @@ class BadDataError extends UnleashError { errors?: [ValidationErrorDescription, ...ValidationErrorDescription[]], ) { const topLevelMessage = - 'Request validation failed: your request body contains invalid data' + + 'Request validation failed: your request body or params contain invalid data' + (errors ? '. Refer to the `details` list for more information.' : `: ${message}`); diff --git a/src/lib/openapi/index.ts b/src/lib/openapi/index.ts index a6cf0cc7b5..a3e526bccc 100644 --- a/src/lib/openapi/index.ts +++ b/src/lib/openapi/index.ts @@ -133,6 +133,7 @@ import { userSchema, usersGroupsBaseSchema, usersSchema, + createUserResponseSchema, usersSearchSchema, validatedEdgeTokensSchema, validatePasswordSchema, @@ -327,6 +328,7 @@ export const schemas: UnleashSchemas = { createStrategySchema, updateStrategySchema, userSchema, + createUserResponseSchema, usersGroupsBaseSchema, usersSchema, usersSearchSchema, diff --git a/src/lib/openapi/meta-schema-rules.test.ts b/src/lib/openapi/meta-schema-rules.test.ts index ce8bf49d78..1aa0c73622 100644 --- a/src/lib/openapi/meta-schema-rules.test.ts +++ b/src/lib/openapi/meta-schema-rules.test.ts @@ -96,7 +96,6 @@ const metaRules: Rule[] = [ 'createApiTokenSchema', 'createFeatureSchema', 'createInvitedUserSchema', - 'createUserSchema', 'environmentsSchema', 'environmentsProjectSchema', 'eventSchema', @@ -113,11 +112,9 @@ const metaRules: Rule[] = [ 'groupSchema', 'groupsSchema', 'groupUserModelSchema', - 'idSchema', 'maintenanceSchema', 'toggleMaintenanceSchema', 'meSchema', - 'passwordSchema', 'patchSchema', 'permissionSchema', 'profileSchema', @@ -143,11 +140,9 @@ const metaRules: Rule[] = [ 'updateFeatureSchema', 'updateFeatureStrategySchema', 'updateTagTypeSchema', - 'updateUserSchema', 'upsertContextFieldSchema', 'upsertStrategySchema', 'usersGroupsBaseSchema', - 'usersSchema', 'validateEdgeTokensSchema', 'validateTagTypeSchema', 'variantFlagSchema', @@ -175,7 +170,6 @@ const metaRules: Rule[] = [ 'createFeatureSchema', 'createFeatureStrategySchema', 'createInvitedUserSchema', - 'createUserSchema', 'dateSchema', 'environmentsSchema', 'eventSchema', @@ -191,12 +185,10 @@ const metaRules: Rule[] = [ 'groupSchema', 'groupsSchema', 'groupUserModelSchema', - 'idSchema', 'maintenanceSchema', 'toggleMaintenanceSchema', 'meSchema', 'parametersSchema', - 'passwordSchema', 'patchesSchema', 'patchSchema', 'permissionSchema', @@ -223,11 +215,9 @@ const metaRules: Rule[] = [ 'updateFeatureSchema', 'updateFeatureStrategySchema', 'updateTagTypeSchema', - 'updateUserSchema', 'upsertContextFieldSchema', 'upsertStrategySchema', 'usersGroupsBaseSchema', - 'usersSchema', 'usersSearchSchema', 'validateEdgeTokensSchema', 'validateTagTypeSchema', diff --git a/src/lib/openapi/spec/create-user-response-schema.ts b/src/lib/openapi/spec/create-user-response-schema.ts new file mode 100644 index 0000000000..cc868e939b --- /dev/null +++ b/src/lib/openapi/spec/create-user-response-schema.ts @@ -0,0 +1,34 @@ +import { FromSchema } from 'json-schema-to-ts'; +import { userSchema } from './user-schema'; + +export const createUserResponseSchema = { + $id: '#/components/schemas/createUserResponseSchema', + type: 'object', + additionalProperties: false, + description: 'An Unleash user after creation', + required: ['id'], + properties: { + ...userSchema.properties, + rootRole: { + description: + 'Which [root role](https://docs.getunleash.io/reference/rbac#standard-roles) this user is assigned. Usually a numeric role ID, but can be a string when returning newly created user with an explicit string role.', + oneOf: [ + { + type: 'integer', + example: 1, + minimum: 0, + }, + { + type: 'string', + example: 'Admin', + enum: ['Admin', 'Editor', 'Viewer', 'Owner', 'Member'], + }, + ], + }, + }, + components: {}, +} as const; + +export type CreateUserResponseSchema = FromSchema< + typeof createUserResponseSchema +>; diff --git a/src/lib/openapi/spec/create-user-schema.ts b/src/lib/openapi/spec/create-user-schema.ts index 0f339440db..90f0397560 100644 --- a/src/lib/openapi/spec/create-user-schema.ts +++ b/src/lib/openapi/spec/create-user-schema.ts @@ -5,24 +5,52 @@ export const createUserSchema = { type: 'object', additionalProperties: false, required: ['rootRole'], + description: + 'The payload must contain at least one of the name and email properties, though which one is up to you. For the user to be able to log in to the system, the user must have an email.', properties: { username: { + description: + "The user's username. Must be provided if email is not provided.", type: 'string', + example: 'hunter', }, email: { + description: + "The user's email address. Must be provided if username is not provided.", type: 'string', + example: 'user@example.com', }, name: { + description: "The user's name (not the user's username).", type: 'string', + example: 'Sam Seawright', }, password: { type: 'string', + example: 'k!5As3HquUrQ', + description: 'Password for the user', }, rootRole: { - type: 'number', + description: + "The role to assign to the user. Can be either the role's ID or its unique name.", + oneOf: [ + { + type: 'integer', + example: 1, + minimum: 0, + }, + { + type: 'string', + example: 'Admin', + enum: ['Admin', 'Editor', 'Viewer', 'Owner', 'Member'], + }, + ], }, sendEmail: { type: 'boolean', + example: false, + description: + 'Whether to send a welcome email with a login link to the user or not. Defaults to `true`.', }, }, components: {}, diff --git a/src/lib/openapi/spec/id-schema.ts b/src/lib/openapi/spec/id-schema.ts index d9daebe1e3..29d9960e49 100644 --- a/src/lib/openapi/spec/id-schema.ts +++ b/src/lib/openapi/spec/id-schema.ts @@ -4,10 +4,13 @@ export const idSchema = { $id: '#/components/schemas/idSchema', type: 'object', additionalProperties: false, + description: 'Email id used for password reset', required: ['id'], properties: { id: { type: 'string', + description: 'User email', + example: 'user@example.com', }, }, components: {}, diff --git a/src/lib/openapi/spec/index.ts b/src/lib/openapi/spec/index.ts index 276f2ec608..66d1aace0a 100644 --- a/src/lib/openapi/spec/index.ts +++ b/src/lib/openapi/spec/index.ts @@ -8,6 +8,7 @@ export * from './pats-schema'; export * from './role-schema'; export * from './tags-schema'; export * from './user-schema'; +export * from './create-user-response-schema'; export * from './addon-schema'; export * from './addon-create-update-schema'; export * from './email-schema'; diff --git a/src/lib/openapi/spec/password-schema.ts b/src/lib/openapi/spec/password-schema.ts index 05f481c05c..f93dab5973 100644 --- a/src/lib/openapi/spec/password-schema.ts +++ b/src/lib/openapi/spec/password-schema.ts @@ -5,15 +5,24 @@ export const passwordSchema = { type: 'object', additionalProperties: false, required: ['password'], + description: 'Fields used to create new password or update old password', properties: { password: { type: 'string', + example: 'k!5As3HquUrQ', + description: 'The new password to change or validate.', }, oldPassword: { type: 'string', + example: 'Oldk!5As3HquUrQ', + description: + 'The old password the user is changing. This field is for the non-admin users changing their own password.', }, confirmPassword: { type: 'string', + example: 'k!5As3HquUrQ', + description: + 'The confirmation of the new password. This field is for the non-admin users changing their own password.', }, }, components: {}, diff --git a/src/lib/openapi/spec/update-user-schema.ts b/src/lib/openapi/spec/update-user-schema.ts index 2c77a8024c..070326dd19 100644 --- a/src/lib/openapi/spec/update-user-schema.ts +++ b/src/lib/openapi/spec/update-user-schema.ts @@ -4,15 +4,34 @@ export const updateUserSchema = { $id: '#/components/schemas/updateUserSchema', type: 'object', additionalProperties: true, + description: 'All fields that can be directly changed for the user', properties: { email: { + description: + "The user's email address. Must be provided if username is not provided.", type: 'string', + example: 'user@example.com', }, name: { + description: "The user's name (not the user's username).", type: 'string', + example: 'Sam Seawright', }, rootRole: { - type: 'number', + description: + "The role to assign to the user. Can be either the role's ID or its unique name.", + oneOf: [ + { + type: 'integer', + example: 1, + minimum: 0, + }, + { + type: 'string', + example: 'Admin', + enum: ['Admin', 'Editor', 'Viewer', 'Owner', 'Member'], + }, + ], }, }, components: {}, diff --git a/src/lib/openapi/spec/user-schema.ts b/src/lib/openapi/spec/user-schema.ts index 574091bf1a..005d13bbcc 100644 --- a/src/lib/openapi/spec/user-schema.ts +++ b/src/lib/openapi/spec/user-schema.ts @@ -84,6 +84,13 @@ export const userSchema = { enum: AccountTypes, example: 'User', }, + permissions: { + description: 'Deprecated', + type: 'array', + items: { + type: 'string', + }, + }, }, components: {}, } as const; diff --git a/src/lib/openapi/spec/users-schema.ts b/src/lib/openapi/spec/users-schema.ts index e28bb9a607..ff16185a19 100644 --- a/src/lib/openapi/spec/users-schema.ts +++ b/src/lib/openapi/spec/users-schema.ts @@ -6,16 +6,20 @@ export const usersSchema = { $id: '#/components/schemas/usersSchema', type: 'object', additionalProperties: false, + description: 'Users and root roles', required: ['users'], properties: { users: { type: 'array', + description: 'A list of users in the Unleash instance.', items: { $ref: '#/components/schemas/userSchema', }, }, rootRoles: { type: 'array', + description: + 'A list of [root roles](https://docs.getunleash.io/reference/rbac#standard-roles) in the Unleash instance.', items: { $ref: '#/components/schemas/roleSchema', }, diff --git a/src/lib/routes/admin-api/user-admin.ts b/src/lib/routes/admin-api/user-admin.ts index 4ef45894b9..71bc420d25 100644 --- a/src/lib/routes/admin-api/user-admin.ts +++ b/src/lib/routes/admin-api/user-admin.ts @@ -5,7 +5,7 @@ import UserService from '../../services/user-service'; import { AccountService } from '../../services/account-service'; import { AccessService } from '../../services/access-service'; import { Logger } from '../../logger'; -import { IUnleashConfig, IUnleashServices } from '../../types'; +import { IUnleashConfig, IUnleashServices, RoleName } from '../../types'; import { EmailService } from '../../services/email-service'; import ResetTokenService from '../../services/reset-token-service'; import { IAuthRequest } from '../unleash-types'; @@ -15,7 +15,10 @@ import { simpleAuthSettingsKey } from '../../types/settings/simple-auth-settings import { anonymise } from '../../util/anonymise'; import { OpenApiService } from '../../services/openapi-service'; import { createRequestSchema } from '../../openapi/util/create-request-schema'; -import { createResponseSchema } from '../../openapi/util/create-response-schema'; +import { + createResponseSchema, + resourceCreatedResponseSchema, +} from '../../openapi/util/create-response-schema'; import { userSchema, UserSchema } from '../../openapi/spec/user-schema'; import { serializeDates } from '../../types/serialize-dates'; import { usersSchema, UsersSchema } from '../../openapi/spec/users-schema'; @@ -31,7 +34,10 @@ import { resetPasswordSchema, ResetPasswordSchema, } from '../../openapi/spec/reset-password-schema'; -import { emptyResponse } from '../../openapi/util/standard-responses'; +import { + emptyResponse, + getStandardResponses, +} from '../../openapi/util/standard-responses'; import { GroupService } from '../../services/group-service'; import { UsersGroupsBaseSchema, @@ -45,6 +51,11 @@ import { AdminCountSchema, adminCountSchema, } from '../../openapi/spec/admin-count-schema'; +import { BadDataError } from '../../error'; +import { + createUserResponseSchema, + CreateUserResponseSchema, +} from '../../openapi/spec/create-user-response-schema'; export default class UserAdminController extends Controller { private flagResolver: IFlagResolver; @@ -114,8 +125,14 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'validateUserPassword', + summary: 'Validate password for a user', + description: + 'Validate the password strength. Minimum 10 characters, uppercase letter, number, special character.', requestBody: createRequestSchema('passwordSchema'), - responses: { 200: emptyResponse }, + responses: { + 200: emptyResponse, + ...getStandardResponses(400, 401, 415), + }, }), ], }); @@ -129,8 +146,13 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'changeUserPassword', + summary: 'Change password for a user', + description: 'Change password for a user as an admin', requestBody: createRequestSchema('passwordSchema'), - responses: { 200: emptyResponse }, + responses: { + 200: emptyResponse, + ...getStandardResponses(400, 401, 403), + }, }), ], }); @@ -144,9 +166,12 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'resetUserPassword', + summary: 'Reset user password', + description: 'Reset user password as an admin', requestBody: createRequestSchema('idSchema'), responses: { 200: createResponseSchema('resetPasswordSchema'), + ...getStandardResponses(400, 401, 403, 404), }, }), ], @@ -161,7 +186,14 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'getUsers', - responses: { 200: createResponseSchema('usersSchema') }, + summary: + 'Get all users and [root roles](https://docs.getunleash.io/reference/rbac#standard-roles)', + description: + 'Will return all users and all available root roles for the Unleash instance.', + responses: { + 200: createResponseSchema('usersSchema'), + ...getStandardResponses(401, 403), + }, }), ], }); @@ -175,7 +207,22 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'searchUsers', - responses: { 200: createResponseSchema('usersSchema') }, + summary: 'Search users', + description: + ' It will preform a simple search based on name and email matching the given query. Requires minimum 2 characters', + parameters: [ + { + name: 'q', + description: + 'The pattern to search in the username or email', + schema: { type: 'string' }, + in: 'query', + }, + ], + responses: { + 200: createResponseSchema('usersSchema'), + ...getStandardResponses(401), + }, }), ], }); @@ -189,8 +236,12 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'getBaseUsersAndGroups', + summary: 'Get basic user and group information', + description: + 'Get a subset of user and group information eligible even for non-admin users', responses: { 200: createResponseSchema('usersGroupsBaseSchema'), + ...getStandardResponses(401), }, }), ], @@ -205,8 +256,12 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'getAdminCount', + summary: 'Get total count of admin accounts', + description: + 'Get a total count of admins with password, without password and admin service accounts', responses: { 200: createResponseSchema('adminCountSchema'), + ...getStandardResponses(401, 403), }, }), ], @@ -221,8 +276,15 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'createUser', + summary: 'Create a new user', + description: 'Creates a new user with the given root role.', requestBody: createRequestSchema('createUserSchema'), - responses: { 200: createResponseSchema('userSchema') }, + responses: { + 201: resourceCreatedResponseSchema( + 'createUserResponseSchema', + ), + ...getStandardResponses(400, 401, 403), + }, }), rateLimit({ windowMs: minutesToMilliseconds(1), @@ -242,7 +304,12 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'getUser', - responses: { 200: createResponseSchema('userSchema') }, + summary: 'Get user', + description: 'Will return a single user by id', + responses: { + 200: createResponseSchema('userSchema'), + ...getStandardResponses(400, 401, 404), + }, }), ], }); @@ -256,8 +323,14 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'updateUser', + summary: 'Update a user', + description: + 'Only the explicitly specified fields get updated.', requestBody: createRequestSchema('updateUserSchema'), - responses: { 200: createResponseSchema('userSchema') }, + responses: { + 200: createResponseSchema('createUserResponseSchema'), + ...getStandardResponses(400, 401, 403, 404), + }, }), ], }); @@ -272,7 +345,12 @@ export default class UserAdminController extends Controller { openApiService.validPath({ tags: ['Users'], operationId: 'deleteUser', - responses: { 200: emptyResponse }, + summary: 'Delete a user', + description: 'Deletes the user with the given userId', + responses: { + 200: emptyResponse, + ...getStandardResponses(401, 403, 404), + }, }), ], }); @@ -382,6 +460,9 @@ export default class UserAdminController extends Controller { async getUser(req: Request, res: Response): Promise { const { id } = req.params; + if (!Number.isInteger(Number(id))) { + throw new BadDataError('User id should be an integer'); + } const user = await this.userService.getUser(Number(id)); this.openApiService.respondWithValidation( @@ -394,11 +475,14 @@ export default class UserAdminController extends Controller { async createUser( req: IAuthRequest, - res: Response, + res: Response, ): Promise { const { username, email, name, rootRole, sendEmail, password } = req.body; const { user } = req; + const normalizedRootRole = Number.isInteger(Number(rootRole)) + ? Number(rootRole) + : (rootRole as RoleName); const createdUser = await this.userService.createUser( { @@ -406,7 +490,7 @@ export default class UserAdminController extends Controller { email, name, password, - rootRole, + rootRole: normalizedRootRole, }, user, ); @@ -451,48 +535,67 @@ export default class UserAdminController extends Controller { ); } - const responseData: UserSchema = { + const responseData: CreateUserResponseSchema = { ...serializeDates(createdUser), inviteLink: inviteLink || this.unleashUrl, emailSent, - rootRole, + rootRole: normalizedRootRole, }; this.openApiService.respondWithValidation( 201, res, - userSchema.$id, + createUserResponseSchema.$id, responseData, + { location: `${responseData.id}` }, ); } async updateUser( - req: IAuthRequest<{ id: string }, UserSchema, UpdateUserSchema>, - res: Response, + req: IAuthRequest< + { id: string }, + CreateUserResponseSchema, + UpdateUserSchema + >, + res: Response, ): Promise { const { user, params, body } = req; const { id } = params; const { name, email, rootRole } = body; + if (!Number.isInteger(Number(id))) { + throw new BadDataError('User id should be an integer'); + } + const normalizedRootRole = Number.isInteger(Number(rootRole)) + ? Number(rootRole) + : (rootRole as RoleName); const updateUser = await this.userService.updateUser( { id: Number(id), name, email, - rootRole, + rootRole: normalizedRootRole, }, user, ); - this.openApiService.respondWithValidation(200, res, userSchema.$id, { - ...serializeDates(updateUser), - rootRole, - }); + this.openApiService.respondWithValidation( + 200, + res, + createUserResponseSchema.$id, + { + ...serializeDates(updateUser), + rootRole: normalizedRootRole, + }, + ); } async deleteUser(req: IAuthRequest, res: Response): Promise { const { user, params } = req; const { id } = params; + if (!Number.isInteger(Number(id))) { + throw new BadDataError('User id should be an integer'); + } await this.userService.deleteUser(+id, user); res.status(200).send(); diff --git a/src/lib/services/user-service.ts b/src/lib/services/user-service.ts index 45833d2c09..3048f58c9c 100644 --- a/src/lib/services/user-service.ts +++ b/src/lib/services/user-service.ts @@ -192,7 +192,7 @@ class UserService { const exists = await this.store.hasUser({ username, email }); if (exists) { - throw new Error('User already exists'); + throw new BadDataError('User already exists'); } const user = await this.store.insert({ diff --git a/src/test/e2e/api/admin/user-admin.e2e.test.ts b/src/test/e2e/api/admin/user-admin.e2e.test.ts index 3544b3101d..04219dbcce 100644 --- a/src/test/e2e/api/admin/user-admin.e2e.test.ts +++ b/src/test/e2e/api/admin/user-admin.e2e.test.ts @@ -1,4 +1,4 @@ -import { setupApp, setupAppWithCustomConfig } from '../../helpers/test-helper'; +import { setupAppWithCustomConfig } from '../../helpers/test-helper'; import dbInit from '../../helpers/database-init'; import getLogger from '../../../fixtures/no-logger'; import { @@ -29,7 +29,13 @@ let adminRole: IRole; beforeAll(async () => { db = await dbInit('user_admin_api_serial', getLogger); stores = db.stores; - app = await setupApp(stores); + app = await setupAppWithCustomConfig(stores, { + experimental: { + flags: { + strictSchemaValidation: true, + }, + }, + }); userStore = stores.userStore; eventStore = stores.eventStore; diff --git a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap index 0870c3b254..14f7590ba4 100644 --- a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap +++ b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap @@ -2069,25 +2069,158 @@ The provider you choose for your addon dictates what properties the \`parameters ], "type": "object", }, + "createUserResponseSchema": { + "additionalProperties": false, + "description": "An Unleash user after creation", + "properties": { + "accountType": { + "description": "A user is either an actual User or a Service Account", + "example": "User", + "type": "string", + }, + "createdAt": { + "description": "The user was created at this time", + "example": "2023-06-30T11:41:00.123Z", + "format": "date-time", + "type": "string", + }, + "email": { + "description": "Email of the user", + "example": "user@example.com", + "type": "string", + }, + "emailSent": { + "description": "Is the welcome email sent to the user or not", + "example": false, + "type": "boolean", + }, + "id": { + "description": "The user id", + "example": 123, + "minimum": 0, + "type": "integer", + }, + "imageUrl": { + "description": "URL used for the userprofile image", + "example": "https://example.com/242x200.png", + "type": "string", + }, + "inviteLink": { + "description": "If the user is actively inviting other users, this is the link that can be shared with other users", + "example": "http://localhost:4242/invite-link/some-secret", + "type": "string", + }, + "isAPI": { + "deprecated": true, + "description": "(Deprecated): Used internally to know which operations the user should be allowed to perform", + "example": true, + "type": "boolean", + }, + "loginAttempts": { + "description": "How many unsuccessful attempts at logging in has the user made", + "example": 3, + "minimum": 0, + "type": "integer", + }, + "name": { + "description": "Name of the user", + "example": "User", + "type": "string", + }, + "permissions": { + "description": "Deprecated", + "items": { + "type": "string", + }, + "type": "array", + }, + "rootRole": { + "description": "Which [root role](https://docs.getunleash.io/reference/rbac#standard-roles) this user is assigned. Usually a numeric role ID, but can be a string when returning newly created user with an explicit string role.", + "oneOf": [ + { + "example": 1, + "minimum": 0, + "type": "integer", + }, + { + "enum": [ + "Admin", + "Editor", + "Viewer", + "Owner", + "Member", + ], + "example": "Admin", + "type": "string", + }, + ], + }, + "seenAt": { + "description": "The last time this user logged in", + "example": "2023-06-30T11:42:00.345Z", + "format": "date-time", + "nullable": true, + "type": "string", + }, + "username": { + "description": "A unique username for the user", + "example": "hunter", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, "createUserSchema": { "additionalProperties": false, + "description": "The payload must contain at least one of the name and email properties, though which one is up to you. For the user to be able to log in to the system, the user must have an email.", "properties": { "email": { + "description": "The user's email address. Must be provided if username is not provided.", + "example": "user@example.com", "type": "string", }, "name": { + "description": "The user's name (not the user's username).", + "example": "Sam Seawright", "type": "string", }, "password": { + "description": "Password for the user", + "example": "k!5As3HquUrQ", "type": "string", }, "rootRole": { - "type": "number", + "description": "The role to assign to the user. Can be either the role's ID or its unique name.", + "oneOf": [ + { + "example": 1, + "minimum": 0, + "type": "integer", + }, + { + "enum": [ + "Admin", + "Editor", + "Viewer", + "Owner", + "Member", + ], + "example": "Admin", + "type": "string", + }, + ], }, "sendEmail": { + "description": "Whether to send a welcome email with a login link to the user or not. Defaults to \`true\`.", + "example": false, "type": "boolean", }, "username": { + "description": "The user's username. Must be provided if email is not provided.", + "example": "hunter", "type": "string", }, }, @@ -3445,8 +3578,11 @@ The provider you choose for your addon dictates what properties the \`parameters }, "idSchema": { "additionalProperties": false, + "description": "Email id used for password reset", "properties": { "id": { + "description": "User email", + "example": "user@example.com", "type": "string", }, }, @@ -3819,14 +3955,21 @@ The provider you choose for your addon dictates what properties the \`parameters }, "passwordSchema": { "additionalProperties": false, + "description": "Fields used to create new password or update old password", "properties": { "confirmPassword": { + "description": "The confirmation of the new password. This field is for the non-admin users changing their own password.", + "example": "k!5As3HquUrQ", "type": "string", }, "oldPassword": { + "description": "The old password the user is changing. This field is for the non-admin users changing their own password.", + "example": "Oldk!5As3HquUrQ", "type": "string", }, "password": { + "description": "The new password to change or validate.", + "example": "k!5As3HquUrQ", "type": "string", }, }, @@ -5933,15 +6076,38 @@ Stats are divided into current and previous **windows**. }, "updateUserSchema": { "additionalProperties": true, + "description": "All fields that can be directly changed for the user", "properties": { "email": { + "description": "The user's email address. Must be provided if username is not provided.", + "example": "user@example.com", "type": "string", }, "name": { + "description": "The user's name (not the user's username).", + "example": "Sam Seawright", "type": "string", }, "rootRole": { - "type": "number", + "description": "The role to assign to the user. Can be either the role's ID or its unique name.", + "oneOf": [ + { + "example": 1, + "minimum": 0, + "type": "integer", + }, + { + "enum": [ + "Admin", + "Editor", + "Viewer", + "Owner", + "Member", + ], + "example": "Admin", + "type": "string", + }, + ], }, }, "type": "object", @@ -6076,6 +6242,13 @@ Stats are divided into current and previous **windows**. "example": "User", "type": "string", }, + "permissions": { + "description": "Deprecated", + "items": { + "type": "string", + }, + "type": "array", + }, "rootRole": { "description": "Which [root role](https://docs.getunleash.io/reference/rbac#standard-roles) this user is assigned", "example": 1, @@ -6120,14 +6293,17 @@ Stats are divided into current and previous **windows**. }, "usersSchema": { "additionalProperties": false, + "description": "Users and root roles", "properties": { "rootRoles": { + "description": "A list of [root roles](https://docs.getunleash.io/reference/rbac#standard-roles) in the Unleash instance.", "items": { "$ref": "#/components/schemas/roleSchema", }, "type": "array", }, "users": { + "description": "A list of users in the Unleash instance.", "items": { "$ref": "#/components/schemas/userSchema", }, @@ -14651,6 +14827,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin": { "get": { + "description": "Will return all users and all available root roles for the Unleash instance.", "operationId": "getUsers", "responses": { "200": { @@ -14663,12 +14840,68 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "description": "usersSchema", }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, }, + "summary": "Get all users and [root roles](https://docs.getunleash.io/reference/rbac#standard-roles)", "tags": [ "Users", ], }, "post": { + "description": "Creates a new user with the given root role.", "operationId": "createUser", "requestBody": { "content": { @@ -14682,17 +14915,108 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 "required": true, }, "responses": { - "200": { + "201": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/userSchema", + "$ref": "#/components/schemas/createUserResponseSchema", }, }, }, - "description": "userSchema", + "description": "The resource was successfully created.", + "headers": { + "location": { + "description": "The location of the newly created resource.", + "schema": { + "format": "uri", + "type": "string", + }, + }, + }, + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ValidationError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The request data does not match what we expect.", + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", }, }, + "summary": "Create a new user", "tags": [ "Users", ], @@ -14700,6 +15024,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/access": { "get": { + "description": "Get a subset of user and group information eligible even for non-admin users", "operationId": "getBaseUsersAndGroups", "responses": { "200": { @@ -14712,7 +15037,35 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "description": "usersGroupsBaseSchema", }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, }, + "summary": "Get basic user and group information", "tags": [ "Users", ], @@ -14720,6 +15073,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/admin-count": { "get": { + "description": "Get a total count of admins with password, without password and admin service accounts", "operationId": "getAdminCount", "responses": { "200": { @@ -14732,7 +15086,62 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "description": "adminCountSchema", }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, }, + "summary": "Get total count of admin accounts", "tags": [ "Users", ], @@ -14740,6 +15149,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/reset-password": { "post": { + "description": "Reset user password as an admin", "operationId": "resetUserPassword", "requestBody": { "content": { @@ -14763,7 +15173,116 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "description": "resetPasswordSchema", }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ValidationError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The request data does not match what we expect.", + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "Could not find the addon with ID "12345".", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NotFoundError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The requested resource was not found.", + }, }, + "summary": "Reset user password", "tags": [ "Users", ], @@ -14771,7 +15290,18 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/search": { "get": { + "description": " It will preform a simple search based on name and email matching the given query. Requires minimum 2 characters", "operationId": "searchUsers", + "parameters": [ + { + "description": "The pattern to search in the username or email", + "in": "query", + "name": "q", + "schema": { + "type": "string", + }, + }, + ], "responses": { "200": { "content": { @@ -14783,7 +15313,35 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "description": "usersSchema", }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, }, + "summary": "Search users", "tags": [ "Users", ], @@ -14791,6 +15349,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/validate-password": { "post": { + "description": "Validate the password strength. Minimum 10 characters, uppercase letter, number, special character.", "operationId": "validateUserPassword", "requestBody": { "content": { @@ -14807,7 +15366,89 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 "200": { "description": "This response has no body.", }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ValidationError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The request data does not match what we expect.", + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "415": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "We do not accept the content-type you provided (application/xml). Try using one of the content-types we do accept instead (application/json) and make sure the body is in the corresponding format.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ContentTypeerror", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The operation does not support request payloads of the provided type. Please ensure that you're using one of the listed payload types and that you have specified the right content type in the "content-type" header.", + }, }, + "summary": "Validate password for a user", "tags": [ "Users", ], @@ -14815,6 +15456,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/{id}": { "delete": { + "description": "Deletes the user with the given userId", "operationId": "deleteUser", "parameters": [ { @@ -14830,12 +15472,95 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 "200": { "description": "This response has no body.", }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "Could not find the addon with ID "12345".", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NotFoundError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The requested resource was not found.", + }, }, + "summary": "Delete a user", "tags": [ "Users", ], }, "get": { + "description": "Will return a single user by id", "operationId": "getUser", "parameters": [ { @@ -14858,12 +15583,95 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "description": "userSchema", }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ValidationError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The request data does not match what we expect.", + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "Could not find the addon with ID "12345".", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NotFoundError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The requested resource was not found.", + }, }, + "summary": "Get user", "tags": [ "Users", ], }, "put": { + "description": "Only the explicitly specified fields get updated.", "operationId": "updateUser", "parameters": [ { @@ -14891,13 +15699,122 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/userSchema", + "$ref": "#/components/schemas/createUserResponseSchema", }, }, }, - "description": "userSchema", + "description": "createUserResponseSchema", + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ValidationError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The request data does not match what we expect.", + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "Could not find the addon with ID "12345".", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NotFoundError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The requested resource was not found.", }, }, + "summary": "Update a user", "tags": [ "Users", ], @@ -14905,6 +15822,7 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 }, "/api/admin/user-admin/{id}/change-password": { "post": { + "description": "Change password for a user as an admin", "operationId": "changeUserPassword", "parameters": [ { @@ -14931,7 +15849,89 @@ true,false,"[{""range"":""allTime"",""count"":15},{""range"":""30d"",""count"":9 "200": { "description": "This response has no body.", }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "The request payload you provided doesn't conform to the schema. The .parameters property should be object. You sent [].", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "ValidationError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "The request data does not match what we expect.", + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You must log in to use Unleash. Your request had no authorization header, so we could not authorize you. Try logging in at /auth/simple/login.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "AuthenticationRequired", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "Authorization information is missing or invalid. Provide a valid API token as the \`authorization\` header, e.g. \`authorization:*.*.my-admin-token\`.", + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "description": "The ID of the error instance", + "example": "9c40958a-daac-400e-98fb-3bb438567008", + "type": "string", + }, + "message": { + "description": "A description of what went wrong.", + "example": "You need the "UPDATE_ADDON" permission to perform this action in the "development" environment.", + "type": "string", + }, + "name": { + "description": "The name of the error kind", + "example": "NoAccessError", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "User credentials are valid but does not have enough privileges to execute this operation", + }, }, + "summary": "Change password for a user", "tags": [ "Users", ], diff --git a/website/docs/reference/api/legacy/unleash/admin/user-admin.md b/website/docs/reference/api/legacy/unleash/admin/user-admin.md index 0894c12fc5..4e2ceaf96d 100644 --- a/website/docs/reference/api/legacy/unleash/admin/user-admin.md +++ b/website/docs/reference/api/legacy/unleash/admin/user-admin.md @@ -186,7 +186,7 @@ The payload **must** contain **at least one of** the `name` and `email` properti `PUT https://unleash.host.com/api/admin/user-admin/:userId` -Updates use with new fields +Updates user with new fields **Body**