diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 1b77743..c87536e 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -29,7 +29,7 @@ export class UserController { @OpenAPI({ description: 'Lists all users.
This includes their groups and permissions directly granted to them (if existing/associated).' }) async getAll() { let responseUsers: ResponseUser[] = new Array(); - const users = await this.userRepository.find({ relations: ['permissions', 'groups'] }); + const users = await this.userRepository.find({ relations: ['permissions', 'groups', 'groups.permissions'] }); users.forEach(user => { responseUsers.push(new ResponseUser(user)); }); @@ -43,7 +43,7 @@ export class UserController { @OnUndefined(UserNotFoundError) @OpenAPI({ description: 'Lists all information about the user whose id got provided.
Please remember that only permissions granted directly to the user will show up here, not permissions inherited from groups.' }) async getOne(@Param('id') id: number) { - let user = await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups'] }) + let user = await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups', 'groups.permissions'] }) if (!user) { throw new UserNotFoundError(); } return new ResponseUser(user); } diff --git a/src/jwtcreator.ts b/src/jwtcreator.ts index 4290aec..0b8ff7e 100644 --- a/src/jwtcreator.ts +++ b/src/jwtcreator.ts @@ -106,23 +106,6 @@ export class JwtUser { this.refreshTokenCount = user.refreshTokenCount; this.uuid = user.uuid; this.profilePic = user.profilePic; - this.permissions = this.getPermissions(user); - } - - /** - * Handels getting the permissions granted to this user (direct or indirect). - * @param user User which's permissions shall be gotten. - */ - public getPermissions(user: User): string[] { - let returnPermissions: string[] = new Array(); - for (let permission of user.permissions) { - returnPermissions.push(permission.toString()); - } - for (let group of user.groups) { - for (let permission of group.permissions) { - returnPermissions.push(permission.toString()); - } - } - return Array.from(new Set(returnPermissions)); + this.permissions = user.allPermissions; } } \ No newline at end of file diff --git a/src/models/actions/CreateUser.ts b/src/models/actions/CreateUser.ts index 0203d99..ad0f905 100644 --- a/src/models/actions/CreateUser.ts +++ b/src/models/actions/CreateUser.ts @@ -1,5 +1,5 @@ import * as argon2 from "argon2"; -import { IsBoolean, IsEmail, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; +import { IsBoolean, IsEmail, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; import { getConnectionManager } from 'typeorm'; import * as uuid from 'uuid'; import { config } from '../../config'; @@ -78,7 +78,13 @@ export class CreateUser { @IsOptional() groups?: number[] | number - //TODO: ProfilePics + /** + * The user's profile pic (or rather a url pointing to it). + */ + @IsString() + @IsUrl() + @IsOptional() + profilePic?: string; /** * Converts this to a User entity. @@ -100,7 +106,9 @@ export class CreateUser { newUser.password = await argon2.hash(this.password + newUser.uuid); newUser.groups = await this.getGroups(); newUser.enabled = this.enabled; - //TODO: ProfilePics + + if (!this.profilePic) { newUser.profilePic = `https://dev.lauf-fuer-kaya.de/lfk-logo.png`; } + else { newUser.profilePic = this.profilePic; } return newUser; } diff --git a/src/models/actions/UpdateUser.ts b/src/models/actions/UpdateUser.ts index 626b096..37e186e 100644 --- a/src/models/actions/UpdateUser.ts +++ b/src/models/actions/UpdateUser.ts @@ -1,5 +1,5 @@ import * as argon2 from "argon2"; -import { IsBoolean, IsEmail, IsInt, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; +import { IsBoolean, IsEmail, IsInt, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; import { getConnectionManager } from 'typeorm'; import { config } from '../../config'; import { UsernameOrEmailNeededError } from '../../errors/AuthError'; @@ -87,7 +87,16 @@ export class UpdateUser { groups?: UserGroup[] /** - * Updates a provided User entity based on this. + * The user's profile pic (or rather a url pointing to it). + */ + @IsString() + @IsUrl() + @IsOptional() + profilePic?: string; + + /** + * Updates a user entity based on this. + * @param user The user that shall be updated. */ public async updateUser(user: User): Promise { user.email = this.email; @@ -106,7 +115,9 @@ export class UpdateUser { user.lastname = this.lastname user.phone = this.phone; user.groups = await this.getGroups(); - //TODO: ProfilePics + + if (!this.profilePic) { user.profilePic = `https://dev.lauf-fuer-kaya.de/lfk-logo.png`; } + else { user.profilePic = this.profilePic; } return user; } diff --git a/src/models/entities/User.ts b/src/models/entities/User.ts index a176934..94e091c 100644 --- a/src/models/entities/User.ts +++ b/src/models/entities/User.ts @@ -1,4 +1,4 @@ -import { IsBoolean, IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString, IsUUID } from "class-validator"; +import { IsBoolean, IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString, IsUrl, IsUUID } from "class-validator"; import { ChildEntity, Column, JoinTable, ManyToMany, OneToMany } from "typeorm"; import { config } from '../../config'; import { ResponsePrincipal } from '../responses/ResponsePrincipal'; @@ -106,10 +106,10 @@ export class User extends Principal { * The user's profile picture. * We haven't decided yet if this will be a bas64 encoded image or just a link to the profile picture. */ - @Column({ nullable: true, unique: false }) + @Column({ nullable: false, unique: false }) @IsString() - @IsOptional() - profilePic?: string; + @IsUrl() + profilePic: string; /** * The last time the user requested a password reset. @@ -128,6 +128,26 @@ export class User extends Principal { @OneToMany(() => UserAction, action => action.user, { nullable: true }) actions: UserAction[] + /** + * Resolves all permissions granted to this user through groups or directly to the string enum format. + */ + public get allPermissions(): string[] { + let returnPermissions: string[] = new Array(); + + if (!this.permissions) { return returnPermissions; } + for (let permission of this.permissions) { + returnPermissions.push(permission.toString()); + } + + if (!this.groups) { return returnPermissions; } + for (let group of this.groups) { + for (let permission of group.permissions) { + returnPermissions.push(permission.toString()); + } + } + return Array.from(new Set(returnPermissions)); + } + /** * Turns this entity into it's response class. */ diff --git a/src/models/responses/ResponseUser.ts b/src/models/responses/ResponseUser.ts index 67fad20..3da5434 100644 --- a/src/models/responses/ResponseUser.ts +++ b/src/models/responses/ResponseUser.ts @@ -5,7 +5,6 @@ import { IsOptional, IsString } from "class-validator"; -import { Permission } from '../entities/Permission'; import { User } from '../entities/User'; import { UserGroup } from '../entities/UserGroup'; import { ResponsePrincipal } from './ResponsePrincipal'; @@ -57,11 +56,10 @@ export class ResponseUser extends ResponsePrincipal { enabled: boolean = true; /** - * The user's profile pic. + * The user's profile pic (or rather a url pointing to it). */ @IsString() - @IsOptional() - profilePic?: string; + profilePic: string; /** * The groups that the user is a part of. @@ -75,7 +73,7 @@ export class ResponseUser extends ResponsePrincipal { */ @IsArray() @IsOptional() - permissions: Permission[]; + permissions: string[]; /** * Creates a ResponseUser object from a user. @@ -92,6 +90,7 @@ export class ResponseUser extends ResponsePrincipal { this.enabled = user.enabled; this.profilePic = user.profilePic; this.groups = user.groups; - this.permissions = user.permissions; + this.permissions = user.allPermissions; + this.groups.forEach(function (g) { delete g.permissions }); } }