From 3c37aafe1f5b044f524132c74c4642068d7cf559 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 8 Jan 2021 19:11:50 +0100 Subject: [PATCH 1/5] Added profile pics to all user related models ref #79 --- src/models/actions/CreateUser.ts | 14 +++++++++++--- src/models/actions/UpdateUser.ts | 17 ++++++++++++++--- src/models/entities/User.ts | 8 ++++---- src/models/responses/ResponseUser.ts | 5 ++--- 4 files changed, 31 insertions(+), 13 deletions(-) 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..802d10f 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. diff --git a/src/models/responses/ResponseUser.ts b/src/models/responses/ResponseUser.ts index 67fad20..e5e9eaf 100644 --- a/src/models/responses/ResponseUser.ts +++ b/src/models/responses/ResponseUser.ts @@ -57,11 +57,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. From a2c3dfbf85ea1514959dba05455bd1bf66bd2a2f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 8 Jan 2021 19:32:04 +0100 Subject: [PATCH 2/5] First part of the permission return (buggy!) ref #71 --- src/controllers/RunnerController.ts | 2 +- src/jwtcreator.ts | 19 +------------------ src/models/entities/User.ts | 18 ++++++++++++++++++ src/models/responses/ResponseUser.ts | 5 ++--- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 9eeb916..6375864 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -27,7 +27,7 @@ export class RunnerController { @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) async getAll() { let responseRunners: ResponseRunner[] = new Array(); - const runners = await this.runnerRepository.find({ relations: ['scans', 'group'] }); + const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'group.permissions', 'permissions'] }); runners.forEach(runner => { responseRunners.push(new ResponseRunner(runner)); }); 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/entities/User.ts b/src/models/entities/User.ts index 802d10f..00c18e4 100644 --- a/src/models/entities/User.ts +++ b/src/models/entities/User.ts @@ -128,6 +128,24 @@ 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 allPermissions = new Array(); + for (let permission in this.permissions) { + allPermissions.push(permission.toString()); + } + + for (let group of this.groups) { + for (let permission in group.permissions) { + allPermissions.push(permission.toString()); + } + } + console.log(allPermissions) + return Array.from(new Set(allPermissions)); + } + /** * Turns this entity into it's response class. */ diff --git a/src/models/responses/ResponseUser.ts b/src/models/responses/ResponseUser.ts index e5e9eaf..ff25c6a 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'; @@ -74,7 +73,7 @@ export class ResponseUser extends ResponsePrincipal { */ @IsArray() @IsOptional() - permissions: Permission[]; + permissions: string[]; /** * Creates a ResponseUser object from a user. @@ -91,6 +90,6 @@ 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; } } From f3cd1380be650837dadd47649eb59b82dea6c060 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 8 Jan 2021 19:32:04 +0100 Subject: [PATCH 3/5] First part of the permission return (buggy!) ref #79 --- src/controllers/RunnerController.ts | 2 +- src/jwtcreator.ts | 19 +------------------ src/models/entities/User.ts | 18 ++++++++++++++++++ src/models/responses/ResponseUser.ts | 5 ++--- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 9eeb916..6375864 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -27,7 +27,7 @@ export class RunnerController { @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) async getAll() { let responseRunners: ResponseRunner[] = new Array(); - const runners = await this.runnerRepository.find({ relations: ['scans', 'group'] }); + const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'group.permissions', 'permissions'] }); runners.forEach(runner => { responseRunners.push(new ResponseRunner(runner)); }); 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/entities/User.ts b/src/models/entities/User.ts index 802d10f..00c18e4 100644 --- a/src/models/entities/User.ts +++ b/src/models/entities/User.ts @@ -128,6 +128,24 @@ 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 allPermissions = new Array(); + for (let permission in this.permissions) { + allPermissions.push(permission.toString()); + } + + for (let group of this.groups) { + for (let permission in group.permissions) { + allPermissions.push(permission.toString()); + } + } + console.log(allPermissions) + return Array.from(new Set(allPermissions)); + } + /** * Turns this entity into it's response class. */ diff --git a/src/models/responses/ResponseUser.ts b/src/models/responses/ResponseUser.ts index e5e9eaf..ff25c6a 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'; @@ -74,7 +73,7 @@ export class ResponseUser extends ResponsePrincipal { */ @IsArray() @IsOptional() - permissions: Permission[]; + permissions: string[]; /** * Creates a ResponseUser object from a user. @@ -91,6 +90,6 @@ 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; } } From aa0337ea33b0b68d5a8eed9d520cab4ee064c23d Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 8 Jan 2021 20:17:05 +0100 Subject: [PATCH 4/5] Fixed getting all permissions for users ref #79 --- src/controllers/UserController.ts | 4 ++-- src/models/entities/User.ts | 16 +++++++++------- src/models/responses/ResponseUser.ts | 1 + 3 files changed, 12 insertions(+), 9 deletions(-) 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/models/entities/User.ts b/src/models/entities/User.ts index 00c18e4..94e091c 100644 --- a/src/models/entities/User.ts +++ b/src/models/entities/User.ts @@ -132,18 +132,20 @@ export class User extends Principal { * Resolves all permissions granted to this user through groups or directly to the string enum format. */ public get allPermissions(): string[] { - let allPermissions = new Array(); - for (let permission in this.permissions) { - allPermissions.push(permission.toString()); + 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 in group.permissions) { - allPermissions.push(permission.toString()); + for (let permission of group.permissions) { + returnPermissions.push(permission.toString()); } } - console.log(allPermissions) - return Array.from(new Set(allPermissions)); + return Array.from(new Set(returnPermissions)); } /** diff --git a/src/models/responses/ResponseUser.ts b/src/models/responses/ResponseUser.ts index ff25c6a..3da5434 100644 --- a/src/models/responses/ResponseUser.ts +++ b/src/models/responses/ResponseUser.ts @@ -91,5 +91,6 @@ export class ResponseUser extends ResponsePrincipal { this.profilePic = user.profilePic; this.groups = user.groups; this.permissions = user.allPermissions; + this.groups.forEach(function (g) { delete g.permissions }); } } From d0deb9d647262a05f6239c273868e715d28777fe Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 8 Jan 2021 20:40:15 +0100 Subject: [PATCH 5/5] Fixed wrong relation getting resolved ref #79 --- src/controllers/RunnerController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 6375864..9eeb916 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -27,7 +27,7 @@ export class RunnerController { @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) async getAll() { let responseRunners: ResponseRunner[] = new Array(); - const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'group.permissions', 'permissions'] }); + const runners = await this.runnerRepository.find({ relations: ['scans', 'group'] }); runners.forEach(runner => { responseRunners.push(new ResponseRunner(runner)); });