mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
refactor: add schemas to feedback controller (#1698)
* refactor: remove previous getProjects route * refactor: add schemas to feedback controller
This commit is contained in:
parent
e64d5a1f97
commit
28ecb158a9
@ -12,6 +12,7 @@ import { featureTypeSchema } from './spec/feature-type-schema';
|
|||||||
import { featureTypesSchema } from './spec/feature-types-schema';
|
import { featureTypesSchema } from './spec/feature-types-schema';
|
||||||
import { featureVariantsSchema } from './spec/feature-variants-schema';
|
import { featureVariantsSchema } from './spec/feature-variants-schema';
|
||||||
import { featuresSchema } from './spec/features-schema';
|
import { featuresSchema } from './spec/features-schema';
|
||||||
|
import { feedbackSchema } from './spec/feedback-schema';
|
||||||
import { healthOverviewSchema } from './spec/health-overview-schema';
|
import { healthOverviewSchema } from './spec/health-overview-schema';
|
||||||
import { healthReportSchema } from './spec/health-report-schema';
|
import { healthReportSchema } from './spec/health-report-schema';
|
||||||
import { mapValues } from '../util/map-values';
|
import { mapValues } from '../util/map-values';
|
||||||
@ -54,6 +55,7 @@ export const schemas = {
|
|||||||
featureTypesSchema,
|
featureTypesSchema,
|
||||||
featureVariantsSchema,
|
featureVariantsSchema,
|
||||||
featuresSchema,
|
featuresSchema,
|
||||||
|
feedbackSchema,
|
||||||
healthOverviewSchema,
|
healthOverviewSchema,
|
||||||
healthReportSchema,
|
healthReportSchema,
|
||||||
overrideSchema,
|
overrideSchema,
|
||||||
|
27
src/lib/openapi/spec/feedback-schema.ts
Normal file
27
src/lib/openapi/spec/feedback-schema.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { FromSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
export const feedbackSchema = {
|
||||||
|
$id: '#/components/schemas/feedbackSchema',
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: false,
|
||||||
|
required: [],
|
||||||
|
properties: {
|
||||||
|
userId: {
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
feedbackId: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
neverShow: {
|
||||||
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
given: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type FeedbackSchema = FromSchema<typeof feedbackSchema>;
|
@ -26,8 +26,6 @@ export default class ProjectApi extends Controller {
|
|||||||
this.projectService = services.projectService;
|
this.projectService = services.projectService;
|
||||||
this.openApiService = services.openApiService;
|
this.openApiService = services.openApiService;
|
||||||
|
|
||||||
this.get('/', this.getProjects);
|
|
||||||
|
|
||||||
this.route({
|
this.route({
|
||||||
path: '',
|
path: '',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
|
|
||||||
import Controller from '../controller';
|
import Controller from '../controller';
|
||||||
import { Logger } from '../../logger';
|
import { Logger } from '../../logger';
|
||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
@ -7,73 +6,106 @@ import { IUnleashServices } from '../../types/services';
|
|||||||
import UserFeedbackService from '../../services/user-feedback-service';
|
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';
|
||||||
interface IFeedbackBody {
|
import {
|
||||||
neverShow?: boolean;
|
feedbackSchema,
|
||||||
feedbackId: string;
|
FeedbackSchema,
|
||||||
given?: Date;
|
} from '../../openapi/spec/feedback-schema';
|
||||||
}
|
import { serializeDates } from '../../types/serialize-dates';
|
||||||
|
import { parseISO } from 'date-fns';
|
||||||
|
import { createRequestSchema, createResponseSchema } from '../../openapi';
|
||||||
|
import BadDataError from '../../error/bad-data-error';
|
||||||
|
|
||||||
class UserFeedbackController extends Controller {
|
class UserFeedbackController extends Controller {
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
private userFeedbackService: UserFeedbackService;
|
private userFeedbackService: UserFeedbackService;
|
||||||
|
|
||||||
|
private openApiService: OpenApiService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{ userFeedbackService }: Pick<IUnleashServices, 'userFeedbackService'>,
|
{
|
||||||
|
userFeedbackService,
|
||||||
|
openApiService,
|
||||||
|
}: Pick<IUnleashServices, 'userFeedbackService' | 'openApiService'>,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
this.logger = config.getLogger('feedback-controller.ts');
|
this.logger = config.getLogger('feedback-controller.ts');
|
||||||
this.userFeedbackService = userFeedbackService;
|
this.userFeedbackService = userFeedbackService;
|
||||||
|
this.openApiService = openApiService;
|
||||||
|
|
||||||
this.post('/', this.recordFeedback, NONE);
|
this.route({
|
||||||
this.put('/:id', this.updateFeedbackSettings, NONE);
|
method: 'post',
|
||||||
|
path: '',
|
||||||
|
handler: this.createFeedback,
|
||||||
|
permission: NONE,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'createFeedback',
|
||||||
|
requestBody: createRequestSchema('feedbackSchema'),
|
||||||
|
responses: { 200: createResponseSchema('feedbackSchema') },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'put',
|
||||||
|
path: '/:id',
|
||||||
|
handler: this.updateFeedback,
|
||||||
|
permission: NONE,
|
||||||
|
middleware: [
|
||||||
|
openApiService.validPath({
|
||||||
|
tags: ['admin'],
|
||||||
|
operationId: 'updateFeedback',
|
||||||
|
requestBody: createRequestSchema('feedbackSchema'),
|
||||||
|
responses: { 200: createResponseSchema('feedbackSchema') },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async recordFeedback(
|
private async createFeedback(
|
||||||
req: IAuthRequest<any, any, IFeedbackBody, any>,
|
req: IAuthRequest<unknown, unknown, FeedbackSchema>,
|
||||||
res: Response,
|
res: Response<FeedbackSchema>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const BAD_REQUEST = 400;
|
if (!req.body.feedbackId) {
|
||||||
const { user } = req;
|
throw new BadDataError('Missing feedbackId');
|
||||||
|
|
||||||
const { feedbackId } = req.body;
|
|
||||||
|
|
||||||
if (!feedbackId) {
|
|
||||||
res.status(BAD_REQUEST).json({
|
|
||||||
error: 'feedbackId must be present.',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const feedback = {
|
const updated = await this.userFeedbackService.updateFeedback({
|
||||||
...req.body,
|
feedbackId: req.body.feedbackId,
|
||||||
userId: user.id,
|
userId: req.user.id,
|
||||||
given: new Date(),
|
given: new Date(),
|
||||||
neverShow: req.body.neverShow || false,
|
neverShow: req.body.neverShow || false,
|
||||||
};
|
});
|
||||||
|
|
||||||
const updated = await this.userFeedbackService.updateFeedback(feedback);
|
this.openApiService.respondWithValidation(
|
||||||
res.json(updated);
|
200,
|
||||||
|
res,
|
||||||
|
feedbackSchema.$id,
|
||||||
|
serializeDates(updated),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateFeedbackSettings(
|
private async updateFeedback(
|
||||||
req: IAuthRequest<any, any, IFeedbackBody, any>,
|
req: IAuthRequest<{ id: string }, unknown, FeedbackSchema>,
|
||||||
res: Response,
|
res: Response<FeedbackSchema>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { user } = req;
|
const updated = await this.userFeedbackService.updateFeedback({
|
||||||
const { id } = req.params;
|
feedbackId: req.params.id,
|
||||||
|
userId: req.user.id,
|
||||||
const feedback = {
|
|
||||||
...req.body,
|
|
||||||
feedbackId: id,
|
|
||||||
userId: user.id,
|
|
||||||
neverShow: req.body.neverShow || false,
|
neverShow: req.body.neverShow || false,
|
||||||
};
|
given: req.body.given && parseISO(req.body.given),
|
||||||
|
});
|
||||||
|
|
||||||
const updated = await this.userFeedbackService.updateFeedback(feedback);
|
this.openApiService.respondWithValidation(
|
||||||
res.json(updated);
|
200,
|
||||||
|
res,
|
||||||
|
feedbackSchema.$id,
|
||||||
|
serializeDates(updated),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ test('it gives 400 when feedback is not present', async () => {
|
|||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(400)
|
.expect(400)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
expect(res.body.error).toBeTruthy();
|
expect(res.body.name).toEqual('BadDataError');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -435,8 +435,5 @@ test(`should clean apitokens for not existing environment after import with drop
|
|||||||
.expect(202);
|
.expect(202);
|
||||||
|
|
||||||
const apiTokens = await app.services.apiTokenService.getAllTokens();
|
const apiTokens = await app.services.apiTokenService.getAllTokens();
|
||||||
|
|
||||||
console.log(apiTokens);
|
|
||||||
|
|
||||||
expect(apiTokens.length).toEqual(0);
|
expect(apiTokens.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
@ -422,6 +422,27 @@ Object {
|
|||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
},
|
},
|
||||||
|
"feedbackSchema": Object {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": Object {
|
||||||
|
"feedbackId": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"given": Object {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"neverShow": Object {
|
||||||
|
"type": "boolean",
|
||||||
|
},
|
||||||
|
"userId": Object {
|
||||||
|
"type": "number",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": Array [],
|
||||||
|
"type": "object",
|
||||||
|
},
|
||||||
"healthOverviewSchema": Object {
|
"healthOverviewSchema": Object {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": Object {
|
"properties": Object {
|
||||||
@ -1429,6 +1450,78 @@ Object {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/api/admin/feedback": Object {
|
||||||
|
"post": Object {
|
||||||
|
"operationId": "createFeedback",
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/feedbackSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "feedbackSchema",
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/feedbackSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "feedbackSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"/api/admin/feedback/{id}": Object {
|
||||||
|
"put": Object {
|
||||||
|
"operationId": "updateFeedback",
|
||||||
|
"parameters": Array [
|
||||||
|
Object {
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"schema": Object {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"requestBody": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/feedbackSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "feedbackSchema",
|
||||||
|
"required": true,
|
||||||
|
},
|
||||||
|
"responses": Object {
|
||||||
|
"200": Object {
|
||||||
|
"content": Object {
|
||||||
|
"application/json": Object {
|
||||||
|
"schema": Object {
|
||||||
|
"$ref": "#/components/schemas/feedbackSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"description": "feedbackSchema",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tags": Array [
|
||||||
|
"admin",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
"/api/admin/projects": Object {
|
"/api/admin/projects": Object {
|
||||||
"get": Object {
|
"get": Object {
|
||||||
"operationId": "getProjects",
|
"operationId": "getProjects",
|
||||||
|
Loading…
Reference in New Issue
Block a user