mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	
							parent
							
								
									00bef41836
								
							
						
					
					
						commit
						1821af8fe7
					
				| @ -49,6 +49,7 @@ import { validateTagTypeSchema } from './spec/validate-tag-type-schema'; | ||||
| import { variantSchema } from './spec/variant-schema'; | ||||
| import { variantsSchema } from './spec/variants-schema'; | ||||
| import { versionSchema } from './spec/version-schema'; | ||||
| import { tagWithVersionSchema } from './spec/tag-with-version-schema'; | ||||
| 
 | ||||
| // All schemas in `openapi/spec` should be listed here.
 | ||||
| export const schemas = { | ||||
| @ -87,6 +88,7 @@ export const schemas = { | ||||
|     splashSchema, | ||||
|     strategySchema, | ||||
|     tagSchema, | ||||
|     tagWithVersionSchema, | ||||
|     tagsSchema, | ||||
|     tagTypeSchema, | ||||
|     tagTypesSchema, | ||||
|  | ||||
							
								
								
									
										22
									
								
								src/lib/openapi/spec/tag-with-version-schema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/lib/openapi/spec/tag-with-version-schema.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| import { tagSchema } from './tag-schema'; | ||||
| import { FromSchema } from 'json-schema-to-ts'; | ||||
| 
 | ||||
| export const tagWithVersionSchema = { | ||||
|     $id: '#/components/schemas/tagWithVersionSchema', | ||||
|     type: 'object', | ||||
|     additionalProperties: false, | ||||
|     required: ['version', 'tag'], | ||||
|     properties: { | ||||
|         version: { | ||||
|             type: 'integer', | ||||
|         }, | ||||
|         tag: { | ||||
|             $ref: '#/components/schemas/tagSchema', | ||||
|         }, | ||||
|     }, | ||||
|     components: { | ||||
|         schemas: { tagSchema }, | ||||
|     }, | ||||
| } as const; | ||||
| 
 | ||||
| export type TagWithVersionSchema = FromSchema<typeof tagWithVersionSchema>; | ||||
| @ -72,9 +72,9 @@ test('should get all tags added', () => { | ||||
|         }); | ||||
| }); | ||||
| 
 | ||||
| test('should be able to get single tag by type and value', () => { | ||||
| test('should be able to get single tag by type and value', async () => { | ||||
|     expect.assertions(1); | ||||
|     tagStore.createTag({ value: 'TeamRed', type: 'simple' }); | ||||
|     await tagStore.createTag({ value: 'TeamRed', type: 'simple' }); | ||||
|     return request | ||||
|         .get(`${base}/api/admin/tags/simple/TeamRed`) | ||||
|         .expect('Content-Type', /json/) | ||||
|  | ||||
| @ -6,9 +6,18 @@ import { Logger } from '../../logger'; | ||||
| 
 | ||||
| import Controller from '../controller'; | ||||
| 
 | ||||
| import { UPDATE_FEATURE } from '../../types/permissions'; | ||||
| import { NONE, UPDATE_FEATURE } from '../../types/permissions'; | ||||
| import { extractUsername } from '../../util/extract-user'; | ||||
| import { IAuthRequest } from '../unleash-types'; | ||||
| import { createRequestSchema, createResponseSchema } from '../../openapi'; | ||||
| import { emptyResponse } from '../../openapi/spec/empty-response'; | ||||
| import { tagsSchema, TagsSchema } from '../../openapi/spec/tags-schema'; | ||||
| import { TagSchema } from '../../openapi/spec/tag-schema'; | ||||
| import { OpenApiService } from '../../services/openapi-service'; | ||||
| import { | ||||
|     tagWithVersionSchema, | ||||
|     TagWithVersionSchema, | ||||
| } from '../../openapi/spec/tag-with-version-schema'; | ||||
| 
 | ||||
| const version = 1; | ||||
| 
 | ||||
| @ -17,44 +26,147 @@ class TagController extends Controller { | ||||
| 
 | ||||
|     private tagService: TagService; | ||||
| 
 | ||||
|     private openApiService: OpenApiService; | ||||
| 
 | ||||
|     constructor( | ||||
|         config: IUnleashConfig, | ||||
|         { tagService }: Pick<IUnleashServices, 'tagService'>, | ||||
|         { | ||||
|             tagService, | ||||
|             openApiService, | ||||
|         }: Pick<IUnleashServices, 'tagService' | 'openApiService'>, | ||||
|     ) { | ||||
|         super(config); | ||||
|         this.tagService = tagService; | ||||
|         this.openApiService = openApiService; | ||||
|         this.logger = config.getLogger('/admin-api/tag.js'); | ||||
| 
 | ||||
|         this.get('/', this.getTags); | ||||
|         this.post('/', this.createTag, UPDATE_FEATURE); | ||||
|         this.get('/:type', this.getTagsByType); | ||||
|         this.get('/:type/:value', this.getTag); | ||||
|         this.delete('/:type/:value', this.deleteTag, UPDATE_FEATURE); | ||||
|         this.route({ | ||||
|             method: 'get', | ||||
|             path: '', | ||||
|             handler: this.getTags, | ||||
|             permission: NONE, | ||||
|             middleware: [ | ||||
|                 openApiService.validPath({ | ||||
|                     tags: ['admin'], | ||||
|                     operationId: 'getTags', | ||||
|                     responses: { 200: createResponseSchema('tagsSchema') }, | ||||
|                 }), | ||||
|             ], | ||||
|         }); | ||||
|         this.route({ | ||||
|             method: 'post', | ||||
|             path: '', | ||||
|             handler: this.createTag, | ||||
|             permission: UPDATE_FEATURE, | ||||
|             middleware: [ | ||||
|                 openApiService.validPath({ | ||||
|                     tags: ['admin'], | ||||
|                     operationId: 'createTag', | ||||
|                     responses: { | ||||
|                         201: emptyResponse, | ||||
|                     }, | ||||
|                     requestBody: createRequestSchema('tagSchema'), | ||||
|                 }), | ||||
|             ], | ||||
|         }); | ||||
|         this.route({ | ||||
|             method: 'get', | ||||
|             path: '/:type', | ||||
|             handler: this.getTagsByType, | ||||
|             permission: NONE, | ||||
|             middleware: [ | ||||
|                 openApiService.validPath({ | ||||
|                     tags: ['admin'], | ||||
|                     operationId: 'getTagsByType', | ||||
|                     responses: { | ||||
|                         200: createResponseSchema('tagsSchema'), | ||||
|                     }, | ||||
|                 }), | ||||
|             ], | ||||
|         }); | ||||
|         this.route({ | ||||
|             method: 'get', | ||||
|             path: '/:type/:value', | ||||
|             handler: this.getTag, | ||||
|             permission: NONE, | ||||
|             middleware: [ | ||||
|                 openApiService.validPath({ | ||||
|                     tags: ['admin'], | ||||
|                     operationId: 'getTag', | ||||
|                     responses: { | ||||
|                         200: createResponseSchema('tagWithVersionSchema'), | ||||
|                     }, | ||||
|                 }), | ||||
|             ], | ||||
|         }); | ||||
|         this.route({ | ||||
|             method: 'delete', | ||||
|             path: '/:type/:value', | ||||
|             handler: this.deleteTag, | ||||
|             acceptAnyContentType: true, | ||||
|             permission: UPDATE_FEATURE, | ||||
|             middleware: [ | ||||
|                 openApiService.validPath({ | ||||
|                     tags: ['admin'], | ||||
|                     operationId: 'deleteTag', | ||||
|                     responses: { | ||||
|                         200: emptyResponse, | ||||
|                     }, | ||||
|                 }), | ||||
|             ], | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     async getTags(req: Request, res: Response): Promise<void> { | ||||
|     async getTags(req: Request, res: Response<TagsSchema>): Promise<void> { | ||||
|         const tags = await this.tagService.getTags(); | ||||
|         res.json({ version, tags }); | ||||
|         this.openApiService.respondWithValidation<TagsSchema>( | ||||
|             200, | ||||
|             res, | ||||
|             tagsSchema.$id, | ||||
|             { version, tags }, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     async getTagsByType(req: Request, res: Response): Promise<void> { | ||||
|     async getTagsByType( | ||||
|         req: Request, | ||||
|         res: Response<TagsSchema>, | ||||
|     ): Promise<void> { | ||||
|         const tags = await this.tagService.getTagsByType(req.params.type); | ||||
|         res.json({ version, tags }); | ||||
|         this.openApiService.respondWithValidation<TagsSchema>( | ||||
|             200, | ||||
|             res, | ||||
|             tagsSchema.$id, | ||||
|             { version, tags }, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     async getTag(req: Request, res: Response): Promise<void> { | ||||
|     async getTag( | ||||
|         req: Request<TagSchema>, | ||||
|         res: Response<TagWithVersionSchema>, | ||||
|     ): Promise<void> { | ||||
|         const { type, value } = req.params; | ||||
|         const tag = await this.tagService.getTag({ type, value }); | ||||
|         res.json({ version, tag }); | ||||
|         this.openApiService.respondWithValidation<TagWithVersionSchema>( | ||||
|             200, | ||||
|             res, | ||||
|             tagWithVersionSchema.$id, | ||||
|             { version, tag }, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     async createTag(req: IAuthRequest, res: Response): Promise<void> { | ||||
|     async createTag( | ||||
|         req: IAuthRequest<unknown, unknown, TagSchema>, | ||||
|         res: Response, | ||||
|     ): Promise<void> { | ||||
|         const userName = extractUsername(req); | ||||
|         await this.tagService.createTag(req.body, userName); | ||||
|         res.status(201).end(); | ||||
|     } | ||||
| 
 | ||||
|     async deleteTag(req: IAuthRequest, res: Response): Promise<void> { | ||||
|     async deleteTag( | ||||
|         req: IAuthRequest<TagSchema>, | ||||
|         res: Response, | ||||
|     ): Promise<void> { | ||||
|         const { type, value } = req.params; | ||||
|         const userName = extractUsername(req); | ||||
|         await this.tagService.deleteTag({ type, value }, userName); | ||||
|  | ||||
| @ -62,13 +62,13 @@ test('Can create a tag', async () => | ||||
|     app.request | ||||
|         .post('/api/admin/tags') | ||||
|         .send({ | ||||
|             id: 1, | ||||
|             value: 'TeamRed', | ||||
|             type: 'simple', | ||||
|         }) | ||||
|         .expect((res) => { | ||||
|             expect(res.status).toBe(201); | ||||
|         })); | ||||
| 
 | ||||
| test('Can validate a tag', async () => | ||||
|     app.request | ||||
|         .post('/api/admin/tags') | ||||
| @ -79,11 +79,8 @@ test('Can validate a tag', async () => | ||||
|         .expect('Content-Type', /json/) | ||||
|         .expect(400) | ||||
|         .expect((res) => { | ||||
|             expect(res.body.details.length).toBe(2); | ||||
|             expect(res.body.details.length).toBe(1); | ||||
|             expect(res.body.details[0].message).toBe( | ||||
|                 '"value" must be a string', | ||||
|             ); | ||||
|             expect(res.body.details[1].message).toBe( | ||||
|                 '"type" must be URL friendly', | ||||
|             ); | ||||
|         })); | ||||
|  | ||||
| @ -950,6 +950,22 @@ Object { | ||||
|         ], | ||||
|         "type": "object", | ||||
|       }, | ||||
|       "tagWithVersionSchema": Object { | ||||
|         "additionalProperties": false, | ||||
|         "properties": Object { | ||||
|           "tag": Object { | ||||
|             "$ref": "#/components/schemas/tagSchema", | ||||
|           }, | ||||
|           "version": Object { | ||||
|             "type": "integer", | ||||
|           }, | ||||
|         }, | ||||
|         "required": Array [ | ||||
|           "version", | ||||
|           "tag", | ||||
|         ], | ||||
|         "type": "object", | ||||
|       }, | ||||
|       "tagsSchema": Object { | ||||
|         "additionalProperties": false, | ||||
|         "properties": Object { | ||||
| @ -3208,6 +3224,145 @@ Object { | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|     "/api/admin/tags": Object { | ||||
|       "get": Object { | ||||
|         "operationId": "getTags", | ||||
|         "responses": Object { | ||||
|           "200": Object { | ||||
|             "content": Object { | ||||
|               "application/json": Object { | ||||
|                 "schema": Object { | ||||
|                   "$ref": "#/components/schemas/tagsSchema", | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             "description": "tagsSchema", | ||||
|           }, | ||||
|         }, | ||||
|         "tags": Array [ | ||||
|           "admin", | ||||
|         ], | ||||
|       }, | ||||
|       "post": Object { | ||||
|         "operationId": "createTag", | ||||
|         "requestBody": Object { | ||||
|           "content": Object { | ||||
|             "application/json": Object { | ||||
|               "schema": Object { | ||||
|                 "$ref": "#/components/schemas/tagSchema", | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
|           "description": "tagSchema", | ||||
|           "required": true, | ||||
|         }, | ||||
|         "responses": Object { | ||||
|           "201": Object { | ||||
|             "description": "emptyResponse", | ||||
|           }, | ||||
|         }, | ||||
|         "tags": Array [ | ||||
|           "admin", | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|     "/api/admin/tags/{type}": Object { | ||||
|       "get": Object { | ||||
|         "operationId": "getTagsByType", | ||||
|         "parameters": Array [ | ||||
|           Object { | ||||
|             "in": "path", | ||||
|             "name": "type", | ||||
|             "required": true, | ||||
|             "schema": Object { | ||||
|               "type": "string", | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|         "responses": Object { | ||||
|           "200": Object { | ||||
|             "content": Object { | ||||
|               "application/json": Object { | ||||
|                 "schema": Object { | ||||
|                   "$ref": "#/components/schemas/tagsSchema", | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             "description": "tagsSchema", | ||||
|           }, | ||||
|         }, | ||||
|         "tags": Array [ | ||||
|           "admin", | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|     "/api/admin/tags/{type}/{value}": Object { | ||||
|       "delete": Object { | ||||
|         "operationId": "deleteTag", | ||||
|         "parameters": Array [ | ||||
|           Object { | ||||
|             "in": "path", | ||||
|             "name": "type", | ||||
|             "required": true, | ||||
|             "schema": Object { | ||||
|               "type": "string", | ||||
|             }, | ||||
|           }, | ||||
|           Object { | ||||
|             "in": "path", | ||||
|             "name": "value", | ||||
|             "required": true, | ||||
|             "schema": Object { | ||||
|               "type": "string", | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|         "responses": Object { | ||||
|           "200": Object { | ||||
|             "description": "emptyResponse", | ||||
|           }, | ||||
|         }, | ||||
|         "tags": Array [ | ||||
|           "admin", | ||||
|         ], | ||||
|       }, | ||||
|       "get": Object { | ||||
|         "operationId": "getTag", | ||||
|         "parameters": Array [ | ||||
|           Object { | ||||
|             "in": "path", | ||||
|             "name": "type", | ||||
|             "required": true, | ||||
|             "schema": Object { | ||||
|               "type": "string", | ||||
|             }, | ||||
|           }, | ||||
|           Object { | ||||
|             "in": "path", | ||||
|             "name": "value", | ||||
|             "required": true, | ||||
|             "schema": Object { | ||||
|               "type": "string", | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|         "responses": Object { | ||||
|           "200": Object { | ||||
|             "content": Object { | ||||
|               "application/json": Object { | ||||
|                 "schema": Object { | ||||
|                   "$ref": "#/components/schemas/tagWithVersionSchema", | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             "description": "tagWithVersionSchema", | ||||
|           }, | ||||
|         }, | ||||
|         "tags": Array [ | ||||
|           "admin", | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|     "/api/admin/ui-config": Object { | ||||
|       "get": Object { | ||||
|         "operationId": "getUIConfig", | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user