mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	fix: Remove idNumberMiddleware and change to use parameters in validPath method instead (#8734)
				
					
				
			## About the changes
- Remove `idNumberMiddleware` method and change to use `parameters`
field in `openApiService.validPath` method for the flexibility.
- Remove unnecessary `Number` type converting method and change them to
use `<{id: number}>` to specify the type.
### Reference
The changed response looks like the one below.
```JSON
{
   "id":"8174a692-7427-4d35-b7b9-6543b9d3db6e",
   "name":"BadDataError",
   "message":"Request validation failed: your request body or params contain invalid data. Refer to the `details` list for more information.",
   "details":[
      {
         "message":"The `/params/id` property must be integer. You sent undefined.",
         "path":"/params/id"
      }
   ]
}
```
I think it might be better to customize the error response, especially
`"You sent undefined."`, on another pull request if this one is
accepted. I prefer to separate jobs to divide the context and believe
that it helps reviewer easier to understand.
			
			
This commit is contained in:
		
							parent
							
								
									18591dd017
								
							
						
					
					
						commit
						695873132e
					
				@ -204,14 +204,8 @@ test('should create segments', async () => {
 | 
				
			|||||||
    expect(segments.map((s) => s.name)).toEqual(['a', 'b', 'c']);
 | 
					    expect(segments.map((s) => s.name)).toEqual(['a', 'b', 'c']);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('should return 400 for non numeeric segment ID', async () => {
 | 
					test('should return 400 for non numeric segment ID', async () => {
 | 
				
			||||||
    const { body } = await app.request
 | 
					    await app.request.get(`${SEGMENTS_BASE_PATH}/stringName`).expect(400);
 | 
				
			||||||
        .get(`${SEGMENTS_BASE_PATH}/stringName`)
 | 
					 | 
				
			||||||
        .expect(400);
 | 
					 | 
				
			||||||
    expect(body).toMatchObject({
 | 
					 | 
				
			||||||
        message:
 | 
					 | 
				
			||||||
            'Request validation failed: your request body or params contain invalid data: ID should be an integer',
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('should update segments', async () => {
 | 
					test('should update segments', async () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,6 @@ import {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { anonymiseKeys, extractUserIdFromUser } from '../../util';
 | 
					import { anonymiseKeys, extractUserIdFromUser } from '../../util';
 | 
				
			||||||
import { BadDataError } from '../../error';
 | 
					import { BadDataError } from '../../error';
 | 
				
			||||||
import idNumberMiddleware from '../../middleware/id-number-middleware';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IUpdateFeatureStrategySegmentsRequest = IAuthRequest<
 | 
					type IUpdateFeatureStrategySegmentsRequest = IAuthRequest<
 | 
				
			||||||
    {},
 | 
					    {},
 | 
				
			||||||
@ -156,11 +155,21 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
                    summary: 'Get strategies that reference segment',
 | 
					                    summary: 'Get strategies that reference segment',
 | 
				
			||||||
                    description:
 | 
					                    description:
 | 
				
			||||||
                        'Retrieve all strategies that reference the specified segment.',
 | 
					                        'Retrieve all strategies that reference the specified segment.',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a segment id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        200: createResponseSchema('segmentStrategiesSchema'),
 | 
					                        200: createResponseSchema('segmentStrategiesSchema'),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -175,6 +184,17 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
                    summary: 'Deletes a segment by id',
 | 
					                    summary: 'Deletes a segment by id',
 | 
				
			||||||
                    description:
 | 
					                    description:
 | 
				
			||||||
                        'Deletes a segment by its id, if not found returns a 409 error',
 | 
					                        'Deletes a segment by its id, if not found returns a 409 error',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a segment id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    tags: ['Segments'],
 | 
					                    tags: ['Segments'],
 | 
				
			||||||
                    operationId: 'removeSegment',
 | 
					                    operationId: 'removeSegment',
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
@ -182,7 +202,6 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
                        ...getStandardResponses(401, 403, 409),
 | 
					                        ...getStandardResponses(401, 403, 409),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -198,13 +217,23 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
                        'Updates the content of the segment with the provided payload. Requires `name` and `constraints` to be present. If `project` is not present, it will be set to `null`. Any other fields not specified will be left untouched.',
 | 
					                        'Updates the content of the segment with the provided payload. Requires `name` and `constraints` to be present. If `project` is not present, it will be set to `null`. Any other fields not specified will be left untouched.',
 | 
				
			||||||
                    tags: ['Segments'],
 | 
					                    tags: ['Segments'],
 | 
				
			||||||
                    operationId: 'updateSegment',
 | 
					                    operationId: 'updateSegment',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a segment id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    requestBody: createRequestSchema('upsertSegmentSchema'),
 | 
					                    requestBody: createRequestSchema('upsertSegmentSchema'),
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        204: emptyResponse,
 | 
					                        204: emptyResponse,
 | 
				
			||||||
                        ...getStandardResponses(400, 401, 403, 409, 415),
 | 
					                        ...getStandardResponses(400, 401, 403, 409, 415),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -219,12 +248,22 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
                    description: 'Retrieves a segment based on its ID.',
 | 
					                    description: 'Retrieves a segment based on its ID.',
 | 
				
			||||||
                    tags: ['Segments'],
 | 
					                    tags: ['Segments'],
 | 
				
			||||||
                    operationId: 'getSegment',
 | 
					                    operationId: 'getSegment',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a segment id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        200: createResponseSchema('adminSegmentSchema'),
 | 
					                        200: createResponseSchema('adminSegmentSchema'),
 | 
				
			||||||
                        ...getStandardResponses(404),
 | 
					                        ...getStandardResponses(404),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -353,7 +392,7 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
        req: IAuthRequest<{ id: number }>,
 | 
					        req: IAuthRequest<{ id: number }>,
 | 
				
			||||||
        res: Response<SegmentStrategiesSchema>,
 | 
					        res: Response<SegmentStrategiesSchema>,
 | 
				
			||||||
    ): Promise<void> {
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const id = Number(req.params.id);
 | 
					        const id = req.params.id;
 | 
				
			||||||
        const { user } = req;
 | 
					        const { user } = req;
 | 
				
			||||||
        const strategies = await this.segmentService.getVisibleStrategies(
 | 
					        const strategies = await this.segmentService.getVisibleStrategies(
 | 
				
			||||||
            id,
 | 
					            id,
 | 
				
			||||||
@ -386,10 +425,10 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async removeSegment(
 | 
					    async removeSegment(
 | 
				
			||||||
        req: IAuthRequest<{ id: string }>,
 | 
					        req: IAuthRequest<{ id: number }>,
 | 
				
			||||||
        res: Response,
 | 
					        res: Response,
 | 
				
			||||||
    ): Promise<void> {
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const id = Number(req.params.id);
 | 
					        const id = req.params.id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let segmentIsInUse = false;
 | 
					        let segmentIsInUse = false;
 | 
				
			||||||
        segmentIsInUse = await this.segmentService.isInUse(id);
 | 
					        segmentIsInUse = await this.segmentService.isInUse(id);
 | 
				
			||||||
@ -403,10 +442,10 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async updateSegment(
 | 
					    async updateSegment(
 | 
				
			||||||
        req: IAuthRequest<{ id: string }>,
 | 
					        req: IAuthRequest<{ id: number }>,
 | 
				
			||||||
        res: Response,
 | 
					        res: Response,
 | 
				
			||||||
    ): Promise<void> {
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const id = Number(req.params.id);
 | 
					        const id = req.params.id;
 | 
				
			||||||
        const updateRequest: UpsertSegmentSchema = {
 | 
					        const updateRequest: UpsertSegmentSchema = {
 | 
				
			||||||
            name: req.body.name,
 | 
					            name: req.body.name,
 | 
				
			||||||
            description: req.body.description,
 | 
					            description: req.body.description,
 | 
				
			||||||
@ -423,10 +462,10 @@ export class SegmentsController extends Controller {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getSegment(
 | 
					    async getSegment(
 | 
				
			||||||
        req: Request<{ id: string }>,
 | 
					        req: Request<{ id: number }>,
 | 
				
			||||||
        res: Response,
 | 
					        res: Response,
 | 
				
			||||||
    ): Promise<void> {
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const id = Number(req.params.id);
 | 
					        const id = req.params.id;
 | 
				
			||||||
        const segment = await this.segmentService.get(id);
 | 
					        const segment = await this.segmentService.get(id);
 | 
				
			||||||
        if (this.flagResolver.isEnabled('anonymiseEventLog')) {
 | 
					        if (this.flagResolver.isEnabled('anonymiseEventLog')) {
 | 
				
			||||||
            res.json(anonymiseKeys(segment, ['createdBy']));
 | 
					            res.json(anonymiseKeys(segment, ['createdBy']));
 | 
				
			||||||
 | 
				
			|||||||
@ -1,32 +0,0 @@
 | 
				
			|||||||
import express from 'express';
 | 
					 | 
				
			||||||
import supertest from 'supertest';
 | 
					 | 
				
			||||||
import idNumberMiddleware from './id-number-middleware';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
describe('idNumberMiddleware', () => {
 | 
					 | 
				
			||||||
    it('should pass when id is a valid integer', async () => {
 | 
					 | 
				
			||||||
        const app = express();
 | 
					 | 
				
			||||||
        app.use('/:id', idNumberMiddleware());
 | 
					 | 
				
			||||||
        app.get('/:id', (req, res) => {
 | 
					 | 
				
			||||||
            res.status(200).send('Valid ID');
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        await supertest(app)
 | 
					 | 
				
			||||||
            .get('/123')
 | 
					 | 
				
			||||||
            .expect(200)
 | 
					 | 
				
			||||||
            .expect((res) => {
 | 
					 | 
				
			||||||
                expect(res.text).toBe('Valid ID');
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    it('should throw BadDataError when id is not a valid integer', async () => {
 | 
					 | 
				
			||||||
        const app = express();
 | 
					 | 
				
			||||||
        app.use('/:id', idNumberMiddleware());
 | 
					 | 
				
			||||||
        app.get('/:id', (req, res) => {
 | 
					 | 
				
			||||||
            res.status(200).send('This should not be executed');
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const { body } = await supertest(app).get('/abc').expect(400);
 | 
					 | 
				
			||||||
        expect(body).toMatchObject({
 | 
					 | 
				
			||||||
            details: [{ message: 'ID should be an integer' }],
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
@ -1,16 +0,0 @@
 | 
				
			|||||||
import { BadDataError } from '../error';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const idNumberMiddleware = (): any => {
 | 
					 | 
				
			||||||
    return async (req, res, next) => {
 | 
					 | 
				
			||||||
        const { id } = req.params;
 | 
					 | 
				
			||||||
        if (!Number.isInteger(Number(id))) {
 | 
					 | 
				
			||||||
            res.status(400).send(
 | 
					 | 
				
			||||||
                new BadDataError('ID should be an integer').toJSON(),
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        next();
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default idNumberMiddleware;
 | 
					 | 
				
			||||||
@ -55,7 +55,6 @@ import {
 | 
				
			|||||||
    type CreateUserResponseSchema,
 | 
					    type CreateUserResponseSchema,
 | 
				
			||||||
} from '../../openapi/spec/create-user-response-schema';
 | 
					} from '../../openapi/spec/create-user-response-schema';
 | 
				
			||||||
import type { IRoleWithPermissions } from '../../types/stores/access-store';
 | 
					import type { IRoleWithPermissions } from '../../types/stores/access-store';
 | 
				
			||||||
import idNumberMiddleware from '../../middleware/id-number-middleware';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class UserAdminController extends Controller {
 | 
					export default class UserAdminController extends Controller {
 | 
				
			||||||
    private flagResolver: IFlagResolver;
 | 
					    private flagResolver: IFlagResolver;
 | 
				
			||||||
@ -144,6 +143,17 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
                    operationId: 'changeUserPassword',
 | 
					                    operationId: 'changeUserPassword',
 | 
				
			||||||
                    summary: 'Change password for a user',
 | 
					                    summary: 'Change password for a user',
 | 
				
			||||||
                    description: 'Change password for a user as an admin',
 | 
					                    description: 'Change password for a user as an admin',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a user id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    requestBody: createRequestSchema('passwordSchema'),
 | 
					                    requestBody: createRequestSchema('passwordSchema'),
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        200: emptyResponse,
 | 
					                        200: emptyResponse,
 | 
				
			||||||
@ -256,6 +266,15 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
                    description:
 | 
					                    description:
 | 
				
			||||||
                        'Gets a list of permissions for a user, additional project and environment can be specified.',
 | 
					                        'Gets a list of permissions for a user, additional project and environment can be specified.',
 | 
				
			||||||
                    parameters: [
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a user id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            name: 'project',
 | 
					                            name: 'project',
 | 
				
			||||||
                            in: 'query',
 | 
					                            in: 'query',
 | 
				
			||||||
@ -341,12 +360,22 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
                    operationId: 'getUser',
 | 
					                    operationId: 'getUser',
 | 
				
			||||||
                    summary: 'Get user',
 | 
					                    summary: 'Get user',
 | 
				
			||||||
                    description: 'Will return a single user by id',
 | 
					                    description: 'Will return a single user by id',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a user id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        200: createResponseSchema('userSchema'),
 | 
					                        200: createResponseSchema('userSchema'),
 | 
				
			||||||
                        ...getStandardResponses(400, 401, 404),
 | 
					                        ...getStandardResponses(400, 401, 404),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -367,9 +396,11 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            name: 'id',
 | 
					                            name: 'id',
 | 
				
			||||||
                            in: 'path',
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
                            schema: {
 | 
					                            schema: {
 | 
				
			||||||
                                type: 'integer',
 | 
					                                type: 'integer',
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a user id',
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
@ -377,7 +408,6 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
                        ...getStandardResponses(400, 401, 403, 404),
 | 
					                        ...getStandardResponses(400, 401, 403, 404),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -393,12 +423,22 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
                    operationId: 'deleteUser',
 | 
					                    operationId: 'deleteUser',
 | 
				
			||||||
                    summary: 'Delete a user',
 | 
					                    summary: 'Delete a user',
 | 
				
			||||||
                    description: 'Deletes the user with the given userId',
 | 
					                    description: 'Deletes the user with the given userId',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a user id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        200: emptyResponse,
 | 
					                        200: emptyResponse,
 | 
				
			||||||
                        ...getStandardResponses(401, 403, 404),
 | 
					                        ...getStandardResponses(401, 403, 404),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -507,9 +547,12 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getUser(req: Request, res: Response<UserSchema>): Promise<void> {
 | 
					    async getUser(
 | 
				
			||||||
 | 
					        req: Request<{ id: number }>,
 | 
				
			||||||
 | 
					        res: Response<UserSchema>,
 | 
				
			||||||
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const { id } = req.params;
 | 
					        const { id } = req.params;
 | 
				
			||||||
        const user = await this.userService.getUser(Number(id));
 | 
					        const user = await this.userService.getUser(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.openApiService.respondWithValidation(
 | 
					        this.openApiService.respondWithValidation(
 | 
				
			||||||
            200,
 | 
					            200,
 | 
				
			||||||
@ -568,7 +611,7 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    async updateUser(
 | 
					    async updateUser(
 | 
				
			||||||
        req: IAuthRequest<
 | 
					        req: IAuthRequest<
 | 
				
			||||||
            { id: string },
 | 
					            { id: number },
 | 
				
			||||||
            CreateUserResponseSchema,
 | 
					            CreateUserResponseSchema,
 | 
				
			||||||
            UpdateUserSchema
 | 
					            UpdateUserSchema
 | 
				
			||||||
        >,
 | 
					        >,
 | 
				
			||||||
@ -578,14 +621,14 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
        const { id } = params;
 | 
					        const { id } = params;
 | 
				
			||||||
        const { name, email, rootRole } = body;
 | 
					        const { name, email, rootRole } = body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this.throwIfScimUser({ id: Number(id) });
 | 
					        await this.throwIfScimUser({ id });
 | 
				
			||||||
        const normalizedRootRole = Number.isInteger(Number(rootRole))
 | 
					        const normalizedRootRole = Number.isInteger(Number(rootRole))
 | 
				
			||||||
            ? Number(rootRole)
 | 
					            ? Number(rootRole)
 | 
				
			||||||
            : (rootRole as RoleName);
 | 
					            : (rootRole as RoleName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const updateUser = await this.userService.updateUser(
 | 
					        const updateUser = await this.userService.updateUser(
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                id: Number(id),
 | 
					                id,
 | 
				
			||||||
                name,
 | 
					                name,
 | 
				
			||||||
                email,
 | 
					                email,
 | 
				
			||||||
                rootRole: normalizedRootRole,
 | 
					                rootRole: normalizedRootRole,
 | 
				
			||||||
@ -604,11 +647,14 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async deleteUser(req: IAuthRequest, res: Response): Promise<void> {
 | 
					    async deleteUser(
 | 
				
			||||||
 | 
					        req: IAuthRequest<{ id: number }>,
 | 
				
			||||||
 | 
					        res: Response,
 | 
				
			||||||
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const { user, params } = req;
 | 
					        const { user, params } = req;
 | 
				
			||||||
        const { id } = params;
 | 
					        const { id } = params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this.throwIfScimUser({ id: Number(id) });
 | 
					        await this.throwIfScimUser({ id });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this.userService.deleteUser(+id, req.audit);
 | 
					        await this.userService.deleteUser(+id, req.audit);
 | 
				
			||||||
        res.status(200).send();
 | 
					        res.status(200).send();
 | 
				
			||||||
@ -625,13 +671,13 @@ export default class UserAdminController extends Controller {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async changeUserPassword(
 | 
					    async changeUserPassword(
 | 
				
			||||||
        req: IAuthRequest<{ id: string }, unknown, PasswordSchema>,
 | 
					        req: IAuthRequest<{ id: number }, unknown, PasswordSchema>,
 | 
				
			||||||
        res: Response,
 | 
					        res: Response,
 | 
				
			||||||
    ): Promise<void> {
 | 
					    ): Promise<void> {
 | 
				
			||||||
        const { id } = req.params;
 | 
					        const { id } = req.params;
 | 
				
			||||||
        const { password } = req.body;
 | 
					        const { password } = req.body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this.throwIfScimUser({ id: Number(id) });
 | 
					        await this.throwIfScimUser({ id });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this.userService.changePassword(+id, password);
 | 
					        await this.userService.changePassword(+id, password);
 | 
				
			||||||
        res.status(200).send();
 | 
					        res.status(200).send();
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,6 @@ import {
 | 
				
			|||||||
    createPatSchema,
 | 
					    createPatSchema,
 | 
				
			||||||
} from '../../../openapi/spec/create-pat-schema';
 | 
					} from '../../../openapi/spec/create-pat-schema';
 | 
				
			||||||
import { ForbiddenError, NotFoundError } from '../../../error';
 | 
					import { ForbiddenError, NotFoundError } from '../../../error';
 | 
				
			||||||
import idNumberMiddleware from '../../../middleware/id-number-middleware';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class PatController extends Controller {
 | 
					export default class PatController extends Controller {
 | 
				
			||||||
    private patService: PatService;
 | 
					    private patService: PatService;
 | 
				
			||||||
@ -107,12 +106,22 @@ export default class PatController extends Controller {
 | 
				
			|||||||
                        'Delete a personal access token (PAT) for the current user.',
 | 
					                        'Delete a personal access token (PAT) for the current user.',
 | 
				
			||||||
                    description:
 | 
					                    description:
 | 
				
			||||||
                        'Deletes a [personal access token](https://docs.getunleash.io/how-to/how-to-create-personal-access-tokens) (PAT) belonging to the current user.',
 | 
					                        'Deletes a [personal access token](https://docs.getunleash.io/how-to/how-to-create-personal-access-tokens) (PAT) belonging to the current user.',
 | 
				
			||||||
 | 
					                    parameters: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'id',
 | 
				
			||||||
 | 
					                            in: 'path',
 | 
				
			||||||
 | 
					                            required: true,
 | 
				
			||||||
 | 
					                            schema: {
 | 
				
			||||||
 | 
					                                type: 'integer',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            description: 'a personal access token id',
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                    responses: {
 | 
					                    responses: {
 | 
				
			||||||
                        200: emptyResponse,
 | 
					                        200: emptyResponse,
 | 
				
			||||||
                        ...getStandardResponses(401, 403, 404),
 | 
					                        ...getStandardResponses(401, 403, 404),
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                idNumberMiddleware(),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user