import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { UserDeletionNotConfirmedError, UserIdsNotMatchingError, UsernameContainsIllegalCharacterError, UserNotFoundError } from '../errors/UserErrors'; import { UserGroupNotFoundError } from '../errors/UserGroupErrors'; import { CreateUser } from '../models/actions/create/CreateUser'; import { UpdateUser } from '../models/actions/update/UpdateUser'; import { User } from '../models/entities/User'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseUser } from '../models/responses/ResponseUser'; import { ResponseUserPermissions } from '../models/responses/ResponseUserPermissions'; import { PermissionController } from './PermissionController'; @JsonController('/users') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class UserController { private userRepository: Repository; /** * Gets the repository of this controller's model/entity. */ constructor() { this.userRepository = getConnectionManager().get().getRepository(User); } @Get() @Authorized("USER:GET") @ResponseSchema(ResponseUser, { isArray: true }) @OpenAPI({ description: 'Lists all users.
This includes their groups and permissions granted to them.' }) async getAll() { let responseUsers: ResponseUser[] = new Array(); const users = await this.userRepository.find({ relations: ['permissions', 'groups', 'groups.permissions'] }); users.forEach(user => { responseUsers.push(new ResponseUser(user)); }); return responseUsers; } @Get('/:id') @Authorized("USER:GET") @ResponseSchema(ResponseUser) @ResponseSchema(UserNotFoundError, { statusCode: 404 }) @OnUndefined(UserNotFoundError) @OpenAPI({ description: 'Lists all information about the user whose id got provided.
Please remember that all permissions granted to the user will show up here.' }) async getOne(@Param('id') id: number) { let user = await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups', 'groups.permissions'] }) if (!user) { throw new UserNotFoundError(); } return new ResponseUser(user); } @Get('/:id/permissions') @Authorized("USER:GET") @ResponseSchema(ResponseUser) @ResponseSchema(UserNotFoundError, { statusCode: 404 }) @OnUndefined(UserNotFoundError) @OpenAPI({ description: 'Lists all permissions granted to the user sorted into directly granted and inherited as permission response objects.' }) async getPermissions(@Param('id') id: number) { let user = await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups', 'groups.permissions', 'permissions.principal', 'groups.permissions.principal'] }) if (!user) { throw new UserNotFoundError(); } return new ResponseUserPermissions(user); } @Post() @Authorized("USER:CREATE") @ResponseSchema(ResponseUser) @ResponseSchema(UserGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(UsernameContainsIllegalCharacterError, { statusCode: 406 }) @OpenAPI({ description: 'Create a new user.
If you want to grant permissions to the user you have to create them seperately by posting to /api/permissions after creating the user.' }) async post(@Body({ validate: true }) createUser: CreateUser) { let user; try { user = await createUser.toEntity(); } catch (error) { throw error; } user = await this.userRepository.save(user) return new ResponseUser(await this.userRepository.findOne({ id: user.id }, { relations: ['permissions', 'groups', 'groups.permissions'] })); } @Put('/:id') @Authorized("USER:UPDATE") @ResponseSchema(ResponseUser) @ResponseSchema(UserNotFoundError, { statusCode: 404 }) @ResponseSchema(UserIdsNotMatchingError, { statusCode: 406 }) @ResponseSchema(UsernameContainsIllegalCharacterError, { statusCode: 406 }) @OpenAPI({ description: "Update the user whose id you provided.
To change the permissions directly granted to the user please use /api/permissions instead.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) updateUser: UpdateUser) { let oldUser = await this.userRepository.findOne({ id: id }); if (!oldUser) { throw new UserNotFoundError(); } if (oldUser.id != updateUser.id) { throw new UserIdsNotMatchingError(); } await this.userRepository.save(await updateUser.update(oldUser)); return new ResponseUser(await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups', 'groups.permissions'] })); } @Delete('/:id') @Authorized("USER:DELETE") @ResponseSchema(ResponseUser) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @ResponseSchema(UserDeletionNotConfirmedError, { statusCode: 406 }) @OnUndefined(204) @OpenAPI({ description: 'Delete the user whose id you provided.
You have to confirm your decision by providing the ?force=true query param.
If there are any permissions directly granted to the user they will get deleted as well.
If no user with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { if (!force) { throw new UserDeletionNotConfirmedError; } let user = await this.userRepository.findOne({ id: id }); if (!user) { return null; } const responseUser = await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups', 'groups.permissions'] });; const permissionControler = new PermissionController(); for (let permission of responseUser.permissions) { await permissionControler.remove(permission.id, true); } await this.userRepository.delete(user); return new ResponseUser(responseUser); } }