mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-04 13:48:56 +02:00
refactor: add OpenAPI schema to api-token controller (#1716)
* refactor: add OpenAPI schema to api-token controller * refactor: address PR comments * fix: status codes on environment toggling * fix tests * refactor: address PR comments * refactor: expiresAtSchema -> update-api-token-schema
This commit is contained in:
parent
bb3c722f67
commit
2354656632
@ -1,8 +1,11 @@
|
|||||||
import { OpenAPIV3 } from 'openapi-types';
|
import { OpenAPIV3 } from 'openapi-types';
|
||||||
|
import { apiTokenSchema } from './spec/api-token-schema';
|
||||||
|
import { apiTokensSchema } from './spec/api-tokens-schema';
|
||||||
import { cloneFeatureSchema } from './spec/clone-feature-schema';
|
import { cloneFeatureSchema } from './spec/clone-feature-schema';
|
||||||
import { constraintSchema } from './spec/constraint-schema';
|
import { constraintSchema } from './spec/constraint-schema';
|
||||||
import { contextFieldSchema } from './spec/context-field-schema';
|
import { contextFieldSchema } from './spec/context-field-schema';
|
||||||
import { contextFieldsSchema } from './spec/context-fields-schema';
|
import { contextFieldsSchema } from './spec/context-fields-schema';
|
||||||
|
import { createApiTokenSchema } from './spec/create-api-token-schema';
|
||||||
import { createFeatureSchema } from './spec/create-feature-schema';
|
import { createFeatureSchema } from './spec/create-feature-schema';
|
||||||
import { createStrategySchema } from './spec/create-strategy-schema';
|
import { createStrategySchema } from './spec/create-strategy-schema';
|
||||||
import { environmentSchema } from './spec/environment-schema';
|
import { environmentSchema } from './spec/environment-schema';
|
||||||
@ -33,24 +36,28 @@ import { splashSchema } from './spec/splash-schema';
|
|||||||
import { strategySchema } from './spec/strategy-schema';
|
import { strategySchema } from './spec/strategy-schema';
|
||||||
import { tagSchema } from './spec/tag-schema';
|
import { tagSchema } from './spec/tag-schema';
|
||||||
import { tagsSchema } from './spec/tags-schema';
|
import { tagsSchema } from './spec/tags-schema';
|
||||||
|
import { tagTypeSchema } from './spec/tag-type-schema';
|
||||||
|
import { tagTypesSchema } from './spec/tag-types-schema';
|
||||||
import { uiConfigSchema } from './spec/ui-config-schema';
|
import { uiConfigSchema } from './spec/ui-config-schema';
|
||||||
import { updateFeatureSchema } from './spec/update-feature-schema';
|
import { updateFeatureSchema } from './spec/update-feature-schema';
|
||||||
import { updateStrategySchema } from './spec/update-strategy-schema';
|
import { updateStrategySchema } from './spec/update-strategy-schema';
|
||||||
|
import { updateApiTokenSchema } from './spec/update-api-token-schema';
|
||||||
|
import { updateTagTypeSchema } from './spec/update-tag-type-schema';
|
||||||
import { upsertContextFieldSchema } from './spec/upsert-context-field-schema';
|
import { upsertContextFieldSchema } from './spec/upsert-context-field-schema';
|
||||||
|
import { validateTagTypeSchema } from './spec/validate-tag-type-schema';
|
||||||
import { variantSchema } from './spec/variant-schema';
|
import { variantSchema } from './spec/variant-schema';
|
||||||
import { variantsSchema } from './spec/variants-schema';
|
import { variantsSchema } from './spec/variants-schema';
|
||||||
import { versionSchema } from './spec/version-schema';
|
import { versionSchema } from './spec/version-schema';
|
||||||
import { tagTypeSchema } from './spec/tag-type-schema';
|
|
||||||
import { tagTypesSchema } from './spec/tag-types-schema';
|
|
||||||
import { updateTagTypeSchema } from './spec/update-tag-type-schema';
|
|
||||||
import { validateTagTypeSchema } from './spec/validate-tag-type-schema';
|
|
||||||
|
|
||||||
// All schemas in `openapi/spec` should be listed here.
|
// All schemas in `openapi/spec` should be listed here.
|
||||||
export const schemas = {
|
export const schemas = {
|
||||||
|
apiTokenSchema,
|
||||||
|
apiTokensSchema,
|
||||||
cloneFeatureSchema,
|
cloneFeatureSchema,
|
||||||
constraintSchema,
|
constraintSchema,
|
||||||
contextFieldSchema,
|
contextFieldSchema,
|
||||||
contextFieldsSchema,
|
contextFieldsSchema,
|
||||||
|
createApiTokenSchema,
|
||||||
createFeatureSchema,
|
createFeatureSchema,
|
||||||
createStrategySchema,
|
createStrategySchema,
|
||||||
environmentSchema,
|
environmentSchema,
|
||||||
@ -84,6 +91,7 @@ export const schemas = {
|
|||||||
uiConfigSchema,
|
uiConfigSchema,
|
||||||
updateFeatureSchema,
|
updateFeatureSchema,
|
||||||
updateStrategySchema,
|
updateStrategySchema,
|
||||||
|
updateApiTokenSchema,
|
||||||
updateTagTypeSchema,
|
updateTagTypeSchema,
|
||||||
upsertContextFieldSchema,
|
upsertContextFieldSchema,
|
||||||
validateTagTypeSchema,
|
validateTagTypeSchema,
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`apiTokenSchema empty 1`] = `
|
||||||
|
Object {
|
||||||
|
"data": Object {},
|
||||||
|
"errors": Array [
|
||||||
|
Object {
|
||||||
|
"instancePath": "",
|
||||||
|
"keyword": "required",
|
||||||
|
"message": "must have required property 'username'",
|
||||||
|
"params": Object {
|
||||||
|
"missingProperty": "username",
|
||||||
|
},
|
||||||
|
"schemaPath": "#/required",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"schema": "#/components/schemas/apiTokenSchema",
|
||||||
|
}
|
||||||
|
`;
|
27
src/lib/openapi/spec/api-token-schema.test.ts
Normal file
27
src/lib/openapi/spec/api-token-schema.test.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { ApiTokenType } from '../../types/models/api-token';
|
||||||
|
import { validateSchema } from '../validate';
|
||||||
|
import { ApiTokenSchema } from './api-token-schema';
|
||||||
|
|
||||||
|
test('apiTokenSchema', () => {
|
||||||
|
const data: ApiTokenSchema = {
|
||||||
|
secret: '',
|
||||||
|
username: '',
|
||||||
|
type: ApiTokenType.CLIENT,
|
||||||
|
environment: '',
|
||||||
|
projects: [],
|
||||||
|
expiresAt: '2022-01-01T00:00:00.000Z',
|
||||||
|
createdAt: '2022-01-01T00:00:00.000Z',
|
||||||
|
seenAt: '2022-01-01T00:00:00.000Z',
|
||||||
|
project: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/apiTokenSchema', data),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('apiTokenSchema empty', () => {
|
||||||
|
expect(
|
||||||
|
validateSchema('#/components/schemas/apiTokenSchema', {}),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
51
src/lib/openapi/spec/api-token-schema.ts
Normal file
51
src/lib/openapi/spec/api-token-schema.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
import { ApiTokenType } from '../../types/models/api-token';
|
||||||
|
|
||||||
|
export const apiTokenSchema = {
|
||||||
|
$id: '#/components/schemas/apiTokenSchema',
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ['username', 'type'],
|
||||||
|
properties: {
|
||||||
|
secret: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
description: `${Object.values(ApiTokenType).join(', ')}.`,
|
||||||
|
},
|
||||||
|
environment: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
projects: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expiresAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
seenAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type ApiTokenSchema = FromSchema<typeof apiTokenSchema>;
|
24
src/lib/openapi/spec/api-tokens-schema.ts
Normal file
24
src/lib/openapi/spec/api-tokens-schema.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
import { apiTokenSchema } from './api-token-schema';
|
||||||
|
|
||||||
|
export const apiTokensSchema = {
|
||||||
|
$id: '#/components/schemas/apiTokensSchema',
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ['tokens'],
|
||||||
|
properties: {
|
||||||
|
tokens: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
$ref: '#/components/schemas/apiTokenSchema',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
schemas: {
|
||||||
|
apiTokenSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type ApiTokensSchema = FromSchema<typeof apiTokensSchema>;
|
41
src/lib/openapi/spec/create-api-token-schema.ts
Normal file
41
src/lib/openapi/spec/create-api-token-schema.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
import { ApiTokenType } from '../../types/models/api-token';
|
||||||
|
|
||||||
|
export const createApiTokenSchema = {
|
||||||
|
$id: '#/components/schemas/createApiTokenSchema',
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ['username', 'type'],
|
||||||
|
properties: {
|
||||||
|
secret: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
description: `${Object.values(ApiTokenType).join(', ')}.`,
|
||||||
|
},
|
||||||
|
environment: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
projects: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expiresAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type CreateApiTokenSchema = FromSchema<typeof createApiTokenSchema>;
|
17
src/lib/openapi/spec/update-api-token-schema.ts
Normal file
17
src/lib/openapi/spec/update-api-token-schema.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
export const updateApiTokenSchema = {
|
||||||
|
$id: '#/components/schemas/updateApiTokenSchema',
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ['expiresAt'],
|
||||||
|
properties: {
|
||||||
|
expiresAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type UpdateApiTokenSchema = FromSchema<typeof updateApiTokenSchema>;
|
@ -16,51 +16,150 @@ import User from '../../types/user';
|
|||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
import { ApiTokenType, IApiToken } from '../../types/models/api-token';
|
import { ApiTokenType, IApiToken } from '../../types/models/api-token';
|
||||||
import { createApiToken } from '../../schema/api-token-schema';
|
import { createApiToken } from '../../schema/api-token-schema';
|
||||||
|
import { OpenApiService } from '../../services/openapi-service';
|
||||||
|
import { IUnleashServices } from '../../types';
|
||||||
|
import { createRequestSchema, createResponseSchema } from '../../openapi';
|
||||||
|
import {
|
||||||
|
apiTokensSchema,
|
||||||
|
ApiTokensSchema,
|
||||||
|
} from '../../openapi/spec/api-tokens-schema';
|
||||||
|
import { serializeDates } from '../../types/serialize-dates';
|
||||||
|
import {
|
||||||
|
apiTokenSchema,
|
||||||
|
ApiTokenSchema,
|
||||||
|
} from '../../openapi/spec/api-token-schema';
|
||||||
|
import { emptyResponse } from '../../openapi/spec/empty-response';
|
||||||
|
import { UpdateApiTokenSchema } from '../../openapi/spec/update-api-token-schema';
|
||||||
|
|
||||||
interface IServices {
|
interface TokenParam {
|
||||||
apiTokenService: ApiTokenService;
|
token: string;
|
||||||
accessService: AccessService;
|
|
||||||
}
|
}
|
||||||
|
export class ApiTokenController extends Controller {
|
||||||
class ApiTokenController extends Controller {
|
|
||||||
private apiTokenService: ApiTokenService;
|
private apiTokenService: ApiTokenService;
|
||||||
|
|
||||||
private accessService: AccessService;
|
private accessService: AccessService;
|
||||||
|
|
||||||
|
private openApiService: OpenApiService;
|
||||||
|
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
constructor(config: IUnleashConfig, services: IServices) {
|
constructor(
|
||||||
|
config: IUnleashConfig,
|
||||||
|
{
|
||||||
|
apiTokenService,
|
||||||
|
accessService,
|
||||||
|
openApiService,
|
||||||
|
}: Pick<
|
||||||
|
IUnleashServices,
|
||||||
|
'apiTokenService' | 'accessService' | 'openApiService'
|
||||||
|
>,
|
||||||
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.apiTokenService = services.apiTokenService;
|
this.apiTokenService = apiTokenService;
|
||||||
this.accessService = services.accessService;
|
this.accessService = accessService;
|
||||||
|
this.openApiService = openApiService;
|
||||||
this.logger = config.getLogger('api-token-controller.js');
|
this.logger = config.getLogger('api-token-controller.js');
|
||||||
|
|
||||||
this.get('/', this.getAllApiTokens, READ_API_TOKEN);
|
this.route({
|
||||||
this.post('/', this.createApiToken, CREATE_API_TOKEN);
|
method: 'get',
|
||||||
this.put('/:token', this.updateApiToken, UPDATE_API_TOKEN);
|
path: '',
|
||||||
this.delete('/:token', this.deleteApiToken, DELETE_API_TOKEN);
|
handler: this.getAllApiTokens,
|
||||||
|
permission: READ_API_TOKEN,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'getAllApiTokens',
|
||||||
|
responses: {
|
||||||
|
200: createResponseSchema('apiTokensSchema'),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'post',
|
||||||
|
path: '',
|
||||||
|
handler: this.createApiToken,
|
||||||
|
permission: CREATE_API_TOKEN,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'createApiToken',
|
||||||
|
requestBody: createRequestSchema('createApiTokenSchema'),
|
||||||
|
responses: {
|
||||||
|
201: createResponseSchema('apiTokenSchema'),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'put',
|
||||||
|
path: '/:token',
|
||||||
|
handler: this.updateApiToken,
|
||||||
|
permission: UPDATE_API_TOKEN,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'updateApiToken',
|
||||||
|
requestBody: createRequestSchema('updateApiTokenSchema'),
|
||||||
|
responses: {
|
||||||
|
200: emptyResponse,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'delete',
|
||||||
|
path: '/:token',
|
||||||
|
handler: this.deleteApiToken,
|
||||||
|
acceptAnyContentType: true,
|
||||||
|
permission: DELETE_API_TOKEN,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'deleteApiToken',
|
||||||
|
responses: {
|
||||||
|
200: emptyResponse,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllApiTokens(req: IAuthRequest, res: Response): Promise<void> {
|
async getAllApiTokens(
|
||||||
|
req: IAuthRequest,
|
||||||
|
res: Response<ApiTokensSchema>,
|
||||||
|
): Promise<void> {
|
||||||
const { user } = req;
|
const { user } = req;
|
||||||
const tokens = await this.accessibleTokens(user);
|
const tokens = await this.accessibleTokens(user);
|
||||||
res.json({ tokens });
|
this.openApiService.respondWithValidation(
|
||||||
|
200,
|
||||||
|
res,
|
||||||
|
apiTokensSchema.$id,
|
||||||
|
{ tokens: serializeDates(tokens) },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createApiToken(req: IAuthRequest, res: Response): Promise<any> {
|
async createApiToken(
|
||||||
|
req: IAuthRequest,
|
||||||
|
res: Response<ApiTokenSchema>,
|
||||||
|
): Promise<any> {
|
||||||
const createToken = await createApiToken.validateAsync(req.body);
|
const createToken = await createApiToken.validateAsync(req.body);
|
||||||
const token = await this.apiTokenService.createApiToken(createToken);
|
const token = await this.apiTokenService.createApiToken(createToken);
|
||||||
return res.status(201).json(token);
|
this.openApiService.respondWithValidation(
|
||||||
|
201,
|
||||||
|
res,
|
||||||
|
apiTokenSchema.$id,
|
||||||
|
serializeDates(token),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteApiToken(req: IAuthRequest, res: Response): Promise<void> {
|
async updateApiToken(
|
||||||
const { token } = req.params;
|
req: IAuthRequest<TokenParam, void, UpdateApiTokenSchema>,
|
||||||
|
res: Response,
|
||||||
await this.apiTokenService.delete(token);
|
): Promise<any> {
|
||||||
res.status(200).end();
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateApiToken(req: IAuthRequest, res: Response): Promise<any> {
|
|
||||||
const { token } = req.params;
|
const { token } = req.params;
|
||||||
const { expiresAt } = req.body;
|
const { expiresAt } = req.body;
|
||||||
|
|
||||||
@ -69,10 +168,20 @@ class ApiTokenController extends Controller {
|
|||||||
return res.status(400).send();
|
return res.status(400).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.apiTokenService.updateExpiry(token, expiresAt);
|
await this.apiTokenService.updateExpiry(token, new Date(expiresAt));
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteApiToken(
|
||||||
|
req: IAuthRequest<TokenParam>,
|
||||||
|
res: Response,
|
||||||
|
): Promise<void> {
|
||||||
|
const { token } = req.params;
|
||||||
|
|
||||||
|
await this.apiTokenService.delete(token);
|
||||||
|
res.status(200).end();
|
||||||
|
}
|
||||||
|
|
||||||
private async accessibleTokens(user: User): Promise<IApiToken[]> {
|
private async accessibleTokens(user: User): Promise<IApiToken[]> {
|
||||||
const allTokens = await this.apiTokenService.getAllTokens();
|
const allTokens = await this.apiTokenService.getAllTokens();
|
||||||
|
|
||||||
@ -84,9 +193,6 @@ class ApiTokenController extends Controller {
|
|||||||
return allTokens;
|
return allTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
return allTokens.filter((t) => t.type !== ApiTokenType.ADMIN);
|
return allTokens.filter((token) => token.type !== ApiTokenType.ADMIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ApiTokenController;
|
|
||||||
export default ApiTokenController;
|
|
||||||
|
@ -96,7 +96,7 @@ export class EnvironmentsController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
operationId: 'toggleEnvironmentOn',
|
operationId: 'toggleEnvironmentOn',
|
||||||
responses: { 200: emptyResponse },
|
responses: { 204: emptyResponse },
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -111,7 +111,7 @@ export class EnvironmentsController extends Controller {
|
|||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
tags: ['admin'],
|
tags: ['admin'],
|
||||||
operationId: 'toggleEnvironmentOff',
|
operationId: 'toggleEnvironmentOff',
|
||||||
responses: { 200: emptyResponse },
|
responses: { 204: emptyResponse },
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ import StateController from './state';
|
|||||||
import TagController from './tag';
|
import TagController from './tag';
|
||||||
import TagTypeController from './tag-type';
|
import TagTypeController from './tag-type';
|
||||||
import AddonController from './addon';
|
import AddonController from './addon';
|
||||||
import ApiTokenController from './api-token';
|
import { ApiTokenController } from './api-token';
|
||||||
import UserAdminController from './user-admin';
|
import UserAdminController from './user-admin';
|
||||||
import EmailController from './email';
|
import EmailController from './email';
|
||||||
import UserFeedbackController from './user-feedback';
|
import UserFeedbackController from './user-feedback';
|
||||||
|
@ -51,6 +51,68 @@ exports[`should serve the OpenAPI spec 1`] = `
|
|||||||
Object {
|
Object {
|
||||||
"components": Object {
|
"components": Object {
|
||||||
"schemas": Object {
|
"schemas": Object {
|
||||||
|
"apiTokenSchema": Object {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": Object {
|
||||||
|
"createdAt": Object {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"environment": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"expiresAt": Object {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"project": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"projects": Object {
|
||||||
|
"items": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
|
"secret": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"seenAt": Object {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"type": Object {
|
||||||
|
"description": "client, admin.",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"username": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": Array [
|
||||||
|
"username",
|
||||||
|
"type",
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
|
"apiTokensSchema": Object {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": Object {
|
||||||
|
"tokens": Object {
|
||||||
|
"items": Object {
|
||||||
|
"$ref": "#/components/schemas/apiTokenSchema",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": Array [
|
||||||
|
"tokens",
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
"cloneFeatureSchema": Object {
|
"cloneFeatureSchema": Object {
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
"name": Object {
|
"name": Object {
|
||||||
@ -151,6 +213,43 @@ Object {
|
|||||||
},
|
},
|
||||||
"type": "array",
|
"type": "array",
|
||||||
},
|
},
|
||||||
|
"createApiTokenSchema": Object {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": Object {
|
||||||
|
"environment": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"expiresAt": Object {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"project": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"projects": Object {
|
||||||
|
"items": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
},
|
||||||
|
"secret": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"type": Object {
|
||||||
|
"description": "client, admin.",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"username": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": Array [
|
||||||
|
"username",
|
||||||
|
"type",
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
"createFeatureSchema": Object {
|
"createFeatureSchema": Object {
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
"description": Object {
|
"description": Object {
|
||||||
@ -919,6 +1018,19 @@ Object {
|
|||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
},
|
},
|
||||||
|
"updateApiTokenSchema": Object {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": Object {
|
||||||
|
"expiresAt": Object {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": Array [
|
||||||
|
"expiresAt",
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
"updateFeatureSchema": Object {
|
"updateFeatureSchema": Object {
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
"archived": Object {
|
"archived": Object {
|
||||||
@ -1142,6 +1254,110 @@ Object {
|
|||||||
},
|
},
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"paths": Object {
|
"paths": Object {
|
||||||
|
"/api/admin/api-tokens": Object {
|
||||||
|
"get": Object {
|
||||||
|
"operationId": "getAllApiTokens",
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/apiTokensSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "apiTokensSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"post": Object {
|
||||||
|
"operationId": "createApiToken",
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/createApiTokenSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "createApiTokenSchema",
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"201": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/apiTokenSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "apiTokenSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"/api/admin/api-tokens/{token}": Object {
|
||||||
|
"delete": Object {
|
||||||
|
"operationId": "deleteApiToken",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "token",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"description": "emptyResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"put": Object {
|
||||||
|
"operationId": "updateApiToken",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "token",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/updateApiTokenSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "updateApiTokenSchema",
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"description": "emptyResponse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
"/api/admin/archive/features": Object {
|
"/api/admin/archive/features": Object {
|
||||||
"get": Object {
|
"get": Object {
|
||||||
"deprecated": true,
|
"deprecated": true,
|
||||||
@ -1497,7 +1713,7 @@ Object {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
"responses": Object {
|
"responses": Object {
|
||||||
"200": Object {
|
"204": Object {
|
||||||
"description": "emptyResponse",
|
"description": "emptyResponse",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1520,7 +1736,7 @@ Object {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
"responses": Object {
|
"responses": Object {
|
||||||
"200": Object {
|
"204": Object {
|
||||||
"description": "emptyResponse",
|
"description": "emptyResponse",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user