1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-20 00:08:02 +01:00

openapi: document operations for admin ui feedback (#4226)

This PR updates the endpoint documentation and schemas related to Admin
UI feedback.
This commit is contained in:
Thomas Heartman 2023-07-13 13:27:52 +02:00 committed by GitHub
parent 3da1cbba47
commit 8f5bda6b8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 111 additions and 33 deletions

View File

@ -54,7 +54,9 @@ import {
featureTypesSchema, featureTypesSchema,
featureUsageSchema, featureUsageSchema,
featureVariantsSchema, featureVariantsSchema,
feedbackSchema, feedbackCreateSchema,
feedbackUpdateSchema,
feedbackResponseSchema,
groupSchema, groupSchema,
groupsSchema, groupsSchema,
groupUserModelSchema, groupUserModelSchema,
@ -254,7 +256,9 @@ export const schemas: UnleashSchemas = {
featureTypesSchema, featureTypesSchema,
featureUsageSchema, featureUsageSchema,
featureVariantsSchema, featureVariantsSchema,
feedbackSchema, feedbackCreateSchema,
feedbackUpdateSchema,
feedbackResponseSchema,
groupSchema, groupSchema,
groupsSchema, groupsSchema,
groupUserModelSchema, groupUserModelSchema,

View File

@ -0,0 +1,24 @@
import { FromSchema } from 'json-schema-to-ts';
export const feedbackCreateSchema = {
$id: '#/components/schemas/feedbackCreateSchema',
required: ['feedbackId'],
type: 'object',
description: 'User feedback information to be created.',
properties: {
neverShow: {
description:
'`true` if the user has asked never to see this feedback questionnaire again. Defaults to `false`.',
type: 'boolean',
example: false,
},
feedbackId: {
description: 'The name of the feedback session',
type: 'string',
example: 'pnps',
},
},
components: {},
} as const;
export type FeedbackCreateSchema = FromSchema<typeof feedbackCreateSchema>;

View File

@ -1,24 +1,19 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
export const feedbackSchema = { export const feedbackResponseSchema = {
$id: '#/components/schemas/feedbackSchema', $id: '#/components/schemas/feedbackResponseSchema',
type: 'object',
additionalProperties: false, additionalProperties: false,
description: 'User feedback information', type: 'object',
description: 'User feedback information about a particular feedback item.',
properties: { properties: {
userId: { userId: {
description: 'Identifier of the current user giving feedback', description: 'The ID of the user that gave the feedback.',
type: 'integer', type: 'integer',
example: 2, example: 2,
}, },
feedbackId: {
description: 'The name of the feedback session',
type: 'string',
example: 'pnps',
},
neverShow: { neverShow: {
description: description:
'`true` when user opts-in to never show the feedback again.', '`true` if the user has asked never to see this feedback questionnaire again.',
type: 'boolean', type: 'boolean',
example: false, example: false,
}, },
@ -29,8 +24,13 @@ export const feedbackSchema = {
nullable: true, nullable: true,
example: '2023-07-06T08:29:21.282Z', example: '2023-07-06T08:29:21.282Z',
}, },
feedbackId: {
description: 'The name of the feedback session',
type: 'string',
example: 'pnps',
},
}, },
components: {}, components: {},
} as const; } as const;
export type FeedbackSchema = FromSchema<typeof feedbackSchema>; export type FeedbackResponseSchema = FromSchema<typeof feedbackResponseSchema>;

View File

@ -0,0 +1,30 @@
import { FromSchema } from 'json-schema-to-ts';
export const feedbackUpdateSchema = {
$id: '#/components/schemas/feedbackUpdateSchema',
type: 'object',
description: 'User feedback information to be updated.',
properties: {
userId: {
description: 'The ID of the user that gave the feedback.',
type: 'integer',
example: 2,
},
neverShow: {
description:
'`true` if the user has asked never to see this feedback questionnaire again.',
type: 'boolean',
example: false,
},
given: {
description: 'When this feedback was given',
type: 'string',
format: 'date-time',
nullable: true,
example: '2023-07-06T08:29:21.282Z',
},
},
components: {},
} as const;
export type FeedbackUpdateSchema = FromSchema<typeof feedbackUpdateSchema>;

View File

@ -32,7 +32,9 @@ export * from './variant-schema';
export * from './variant-flag-schema'; export * from './variant-flag-schema';
export * from './version-schema'; export * from './version-schema';
export * from './features-schema'; export * from './features-schema';
export * from './feedback-schema'; export * from './feedback-create-schema';
export * from './feedback-update-schema';
export * from './feedback-response-schema';
export * from './override-schema'; export * from './override-schema';
export * from './password-schema'; export * from './password-schema';
export * from './projects-schema'; export * from './projects-schema';

View File

@ -1,7 +1,7 @@
import { FromSchema } from 'json-schema-to-ts'; import { FromSchema } from 'json-schema-to-ts';
import { userSchema } from './user-schema'; import { userSchema } from './user-schema';
import { permissionSchema } from './permission-schema'; import { permissionSchema } from './permission-schema';
import { feedbackSchema } from './feedback-schema'; import { feedbackResponseSchema } from './feedback-response-schema';
export const meSchema = { export const meSchema = {
$id: '#/components/schemas/meSchema', $id: '#/components/schemas/meSchema',
@ -24,7 +24,7 @@ export const meSchema = {
description: 'User feedback information', description: 'User feedback information',
type: 'array', type: 'array',
items: { items: {
$ref: '#/components/schemas/feedbackSchema', $ref: '#/components/schemas/feedbackResponseSchema',
}, },
}, },
splash: { splash: {
@ -39,7 +39,7 @@ export const meSchema = {
schemas: { schemas: {
userSchema, userSchema,
permissionSchema, permissionSchema,
feedbackSchema, feedbackResponseSchema,
}, },
}, },
} as const; } as const;

View File

@ -7,15 +7,15 @@ import UserFeedbackService from '../../services/user-feedback-service';
import { IAuthRequest } from '../unleash-types'; import { IAuthRequest } from '../unleash-types';
import { NONE } from '../../types/permissions'; import { NONE } from '../../types/permissions';
import { OpenApiService } from '../../services/openapi-service'; import { OpenApiService } from '../../services/openapi-service';
import { import { FeedbackCreateSchema } from '../../openapi/spec/feedback-create-schema';
feedbackSchema, import { FeedbackUpdateSchema } from '../../openapi/spec/feedback-update-schema';
FeedbackSchema, import { FeedbackResponseSchema } from '../../openapi/spec/feedback-response-schema';
} from '../../openapi/spec/feedback-schema';
import { serializeDates } from '../../types/serialize-dates'; import { serializeDates } from '../../types/serialize-dates';
import { parseISO } from 'date-fns'; import { parseISO } from 'date-fns';
import { createRequestSchema } from '../../openapi/util/create-request-schema'; import { createRequestSchema } from '../../openapi/util/create-request-schema';
import { createResponseSchema } from '../../openapi/util/create-response-schema'; import { createResponseSchema } from '../../openapi/util/create-response-schema';
import BadDataError from '../../error/bad-data-error'; import BadDataError from '../../error/bad-data-error';
import { feedbackResponseSchema, getStandardResponses } from '../../openapi';
class UserFeedbackController extends Controller { class UserFeedbackController extends Controller {
private logger: Logger; private logger: Logger;
@ -45,8 +45,14 @@ class UserFeedbackController extends Controller {
openApiService.validPath({ openApiService.validPath({
tags: ['Admin UI'], tags: ['Admin UI'],
operationId: 'createFeedback', operationId: 'createFeedback',
requestBody: createRequestSchema('feedbackSchema'), summary: 'Send Unleash feedback',
responses: { 200: createResponseSchema('feedbackSchema') }, description:
'Sends feedback gathered from the Unleash UI to the Unleash server. Must be called with a token with an identifiable user (either from being sent from the UI or from using a [PAT](https://docs.getunleash.io/reference/api-tokens-and-client-keys#personal-access-tokens)).',
requestBody: createRequestSchema('feedbackCreateSchema'),
responses: {
200: createResponseSchema('feedbackResponseSchema'),
...getStandardResponses(400, 401, 415),
},
}), }),
], ],
}); });
@ -60,16 +66,22 @@ class UserFeedbackController extends Controller {
openApiService.validPath({ openApiService.validPath({
tags: ['Admin UI'], tags: ['Admin UI'],
operationId: 'updateFeedback', operationId: 'updateFeedback',
requestBody: createRequestSchema('feedbackSchema'), summary: 'Update Unleash feedback',
responses: { 200: createResponseSchema('feedbackSchema') }, description:
'Updates the feedback with the provided ID. Only provided fields are updated. Fields left out are left untouched. Must be called with a token with an identifiable user (either from being sent from the UI or from using a [PAT](https://docs.getunleash.io/reference/api-tokens-and-client-keys#personal-access-tokens)).',
requestBody: createRequestSchema('feedbackUpdateSchema'),
responses: {
200: createResponseSchema('feedbackResponseSchema'),
...getStandardResponses(400, 401, 415),
},
}), }),
], ],
}); });
} }
private async createFeedback( private async createFeedback(
req: IAuthRequest<unknown, unknown, FeedbackSchema>, req: IAuthRequest<unknown, unknown, FeedbackCreateSchema>,
res: Response<FeedbackSchema>, res: Response<FeedbackResponseSchema>,
): Promise<void> { ): Promise<void> {
if (!req.body.feedbackId) { if (!req.body.feedbackId) {
throw new BadDataError('Missing feedbackId'); throw new BadDataError('Missing feedbackId');
@ -85,14 +97,14 @@ class UserFeedbackController extends Controller {
this.openApiService.respondWithValidation( this.openApiService.respondWithValidation(
200, 200,
res, res,
feedbackSchema.$id, feedbackResponseSchema.$id,
serializeDates(updated), serializeDates(updated),
); );
} }
private async updateFeedback( private async updateFeedback(
req: IAuthRequest<{ id: string }, unknown, FeedbackSchema>, req: IAuthRequest<{ id: string }, unknown, FeedbackUpdateSchema>,
res: Response<FeedbackSchema>, res: Response<FeedbackResponseSchema>,
): Promise<void> { ): Promise<void> {
const updated = await this.userFeedbackService.updateFeedback({ const updated = await this.userFeedbackService.updateFeedback({
feedbackId: req.params.id, feedbackId: req.params.id,
@ -104,7 +116,7 @@ class UserFeedbackController extends Controller {
this.openApiService.respondWithValidation( this.openApiService.respondWithValidation(
200, 200,
res, res,
feedbackSchema.$id, feedbackResponseSchema.$id,
serializeDates(updated), serializeDates(updated),
); );
} }

View File

@ -33,7 +33,13 @@ beforeAll(async () => {
); );
}; };
app = await setupAppWithCustomAuth(stores, preHook); app = await setupAppWithCustomAuth(stores, preHook, {
experimental: {
flags: {
strictSchemaValidation: true,
},
},
});
}); });
afterAll(async () => { afterAll(async () => {