From 1d0d79f3da52adb9e070812f2a8428bad0303f2e Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Mon, 21 Dec 2020 16:08:10 +0100 Subject: [PATCH] First part of the action comment refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref #39 Why did i volunteer for this? It's just a glorified sleeping aid 😴 --- src/models/actions/CreateAuth.ts | 30 ++++++++++++++-- src/models/actions/HandleLogout.ts | 12 +++++++ src/models/actions/ImportRunner.ts | 34 +++++++++++++------ src/models/actions/RefreshAuth.ts | 12 +++++++ src/models/actions/UpdatePermission.ts | 13 ++++--- src/models/actions/UpdateRunner.ts | 9 +++-- .../actions/UpdateRunnerOrganisation.ts | 10 ++++-- src/models/actions/UpdateRunnerTeam.ts | 12 +++++-- src/models/actions/UpdateUser.ts | 23 ++++++++----- 9 files changed, 123 insertions(+), 32 deletions(-) diff --git a/src/models/actions/CreateAuth.ts b/src/models/actions/CreateAuth.ts index adec57c..375cf2f 100644 --- a/src/models/actions/CreateAuth.ts +++ b/src/models/actions/CreateAuth.ts @@ -1,5 +1,5 @@ import * as argon2 from "argon2"; -import { IsEmail, IsOptional, IsString } from 'class-validator'; +import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator'; import { getConnectionManager } from 'typeorm'; import { InvalidCredentialsError, PasswordNeededError, UserNotFoundError } from '../../errors/AuthError'; import { UsernameOrEmailNeededError } from '../../errors/UserErrors'; @@ -7,17 +7,41 @@ import { JwtCreator } from '../../jwtcreator'; import { User } from '../entities/User'; import { Auth } from '../responses/ResponseAuth'; +/** + * This class is used to create auth credentials. + * To be a little bit more exact: Is takes in a username/email + password and creates a new access and refresh token for the user. + * It of course checks for user existance, password validity and so on. + */ export class CreateAuth { + /** + * The username of the user that want's to login. + * Either username or email have to be provided. + */ @IsOptional() @IsString() username?: string; - @IsString() - password: string; + + /** + * The email address of the user that want's to login. + * Either username or email have to be provided. + */ @IsOptional() @IsEmail() @IsString() email?: string; + /** + * The user's password. + * Will be checked against an argon2 hash. + */ + @IsNotEmpty() + @IsString() + password: string; + + + /** + * Creates a new auth object based on this. + */ public async toAuth(): Promise { let newAuth: Auth = new Auth(); diff --git a/src/models/actions/HandleLogout.ts b/src/models/actions/HandleLogout.ts index 165c78e..40bd572 100644 --- a/src/models/actions/HandleLogout.ts +++ b/src/models/actions/HandleLogout.ts @@ -6,11 +6,23 @@ import { IllegalJWTError, JwtNotProvidedError, RefreshTokenCountInvalidError, Us import { User } from '../entities/User'; import { Logout } from '../responses/ResponseLogout'; +/** + * This class handels a user logging out of the system. + * Of course it check's the user's provided credential (token) before logging him out. + */ export class HandleLogout { + /** + * A stringyfied jwt access token. + * Will get checked for validity. + */ @IsString() @IsOptional() token?: string; + /** + * Logs the user out. + * This gets achived by increasing the user's refresh token count, thereby invalidateing all currently existing jwts for that user. + */ public async logout(): Promise { let logout: Logout = new Logout(); if (!this.token || this.token === undefined) { diff --git a/src/models/actions/ImportRunner.ts b/src/models/actions/ImportRunner.ts index 3f5d97e..b1da7f7 100644 --- a/src/models/actions/ImportRunner.ts +++ b/src/models/actions/ImportRunner.ts @@ -7,6 +7,10 @@ import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { RunnerTeam } from '../entities/RunnerTeam'; import { CreateRunner } from './CreateRunner'; +/** + * Special class used to import runners from csv files - or json arrays created from csv to be exact. + * Why you ask? Because the past has shown us that a non excel/csv based workflow is too much for most schools. + */ export class ImportRunner { /** @@ -18,7 +22,6 @@ export class ImportRunner { /** * The new runner's middle name. - * Optional. */ @IsString() @IsOptional() @@ -32,18 +35,26 @@ export class ImportRunner { lastname: string; /** - * The new runner's class (if not provided otherwise). + * The new runner's team's name (if not provided otherwise). + * The team will automaticly get generated if it doesn't exist in this org yet. */ @IsString() @IsOptional() team?: string; + /** + * Just an alias for team, because this is usually only used for importing data from schools. + */ @IsOptional() @IsString() public set class(value: string) { this.team = value; } + /** + * Creates a CreateRunner object based on this. + * @param groupID Either the id of the new runner's group or the id of the org that the new runner's team is a part of. + */ public async toCreateRunner(groupID: number): Promise { let newRunner: CreateRunner = new CreateRunner(); @@ -55,25 +66,28 @@ export class ImportRunner { return newRunner; } + /** + * Get's the new runners group. + * @param groupID Either the id of the new runner's group or the id of the org that the new runner's team is a part of. + */ public async getGroup(groupID: number): Promise { if (this.team === undefined && groupID === undefined) { throw new RunnerGroupNeededError(); } - let team = await getConnectionManager().get().getRepository(RunnerTeam).findOne({ id: groupID }); - if (team) { return team; } - - let org = await getConnectionManager().get().getRepository(RunnerOrganisation).findOne({ id: groupID }); - if (!org) { + let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: groupID }); + if (group instanceof RunnerTeam) { return group; } + if (!(group instanceof RunnerOrganisation) || !group) { throw new RunnerOrganisationNotFoundError(); } - if (this.team === undefined) { return org; } - team = await getConnectionManager().get().getRepository(RunnerTeam).findOne({ name: this.team, parentGroup: org }); + if (this.team === undefined) { return group; } + + let team = await getConnectionManager().get().getRepository(RunnerTeam).findOne({ name: this.team, parentGroup: org }); if (!team) { let newRunnerTeam: RunnerTeam = new RunnerTeam(); newRunnerTeam.name = this.team; - newRunnerTeam.parentGroup = org; + newRunnerTeam.parentGroup = group; team = await getConnectionManager().get().getRepository(RunnerTeam).save(newRunnerTeam); } diff --git a/src/models/actions/RefreshAuth.ts b/src/models/actions/RefreshAuth.ts index 963c83c..12470c7 100644 --- a/src/models/actions/RefreshAuth.ts +++ b/src/models/actions/RefreshAuth.ts @@ -7,11 +7,23 @@ import { JwtCreator } from "../../jwtcreator"; import { User } from '../entities/User'; import { Auth } from '../responses/ResponseAuth'; +/** + * This class is used to create refreshed auth credentials. + * To be a little bit more exact: Is takes in a refresh token and creates a new access and refresh token for it's user. + * It of course checks for user existance, jwt validity and so on. + */ export class RefreshAuth { + /** + * A stringyfied jwt refresh token. + * Will get checked for validity. + */ @IsString() @IsOptional() token?: string; + /** + * Creates a new auth object based on this. + */ public async toAuth(): Promise { let newAuth: Auth = new Auth(); if (!this.token || this.token === undefined) { diff --git a/src/models/actions/UpdatePermission.ts b/src/models/actions/UpdatePermission.ts index 8c31bbe..5241a1b 100644 --- a/src/models/actions/UpdatePermission.ts +++ b/src/models/actions/UpdatePermission.ts @@ -7,16 +7,21 @@ import { Principal } from '../entities/Principal'; import { PermissionAction } from '../enums/PermissionAction'; import { PermissionTarget } from '../enums/PermissionTargets'; +/** + * This class is used to update a Permission entity (via put request). + */ export class UpdatePermission { /** - * The updated runner's id. + * The updated permission's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). */ @IsInt() id: number; /** - * The permissions's principal's id. + * The updated permissions's principal. + * Just has to contain the principal's id -everything else won't be checked or changed. */ @IsObject() @IsNotEmpty() @@ -35,7 +40,7 @@ export class UpdatePermission { action: PermissionAction; /** - * Converts a Permission object based on this. + * Updates a provided Permission entity based on this. */ public async updatePermission(permission: Permission): Promise { permission.principal = await this.getPrincipal(); @@ -46,7 +51,7 @@ export class UpdatePermission { } /** - * Manages all the different ways a group can be provided. + * Loads the updated permission's principal based on it's id. */ public async getPrincipal(): Promise { if (this.principal === undefined || this.principal === null) { diff --git a/src/models/actions/UpdateRunner.ts b/src/models/actions/UpdateRunner.ts index 62667ec..abc71e0 100644 --- a/src/models/actions/UpdateRunner.ts +++ b/src/models/actions/UpdateRunner.ts @@ -7,22 +7,27 @@ import { Runner } from '../entities/Runner'; import { RunnerGroup } from '../entities/RunnerGroup'; import { CreateParticipant } from './CreateParticipant'; +/** + * This class is used to update a Runner entity (via put request). + */ export class UpdateRunner extends CreateParticipant { /** * The updated runner's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). */ @IsInt() id: number; /** * The updated runner's new team/org. + * Just has to contain the group's id -everything else won't be checked or changed. */ @IsObject() group: RunnerGroup; /** - * Creates a Runner entity from this. + * Updates a provided Runner entity based on this. */ public async updateRunner(runner: Runner): Promise { runner.firstname = this.firstname; @@ -37,7 +42,7 @@ export class UpdateRunner extends CreateParticipant { } /** - * Manages all the different ways a group can be provided. + * Loads the updated runner's group based on it's id. */ public async getGroup(): Promise { if (this.group === undefined || this.group === null) { diff --git a/src/models/actions/UpdateRunnerOrganisation.ts b/src/models/actions/UpdateRunnerOrganisation.ts index 6917698..3a5b1fb 100644 --- a/src/models/actions/UpdateRunnerOrganisation.ts +++ b/src/models/actions/UpdateRunnerOrganisation.ts @@ -5,17 +5,21 @@ import { Address } from '../entities/Address'; import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { CreateRunnerGroup } from './CreateRunnerGroup'; +/** + * This class is used to update a RunnerOrganisation entity (via put request). + */ export class UpdateRunnerOrganisation extends CreateRunnerGroup { /** * The updated orgs's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). */ @IsInt() id: number; /** * The updated organisation's address. - * Must be of type number (address id). + * Just has to contain the address's id - everything else won't be checked or changed. * Optional. */ @IsInt() @@ -23,7 +27,7 @@ export class UpdateRunnerOrganisation extends CreateRunnerGroup { address?: Address; /** - * Get's this org's address from this.address. + * Loads the organisation's address based on it's id. */ public async getAddress(): Promise
{ if (this.address === undefined || this.address === null) { @@ -35,7 +39,7 @@ export class UpdateRunnerOrganisation extends CreateRunnerGroup { } /** - * Creates a RunnerTeam entity from this. + * Updates a provided RunnerOrganisation entity based on this. */ public async updateRunnerOrganisation(organisation: RunnerOrganisation): Promise { diff --git a/src/models/actions/UpdateRunnerTeam.ts b/src/models/actions/UpdateRunnerTeam.ts index 62b71d5..756d7df 100644 --- a/src/models/actions/UpdateRunnerTeam.ts +++ b/src/models/actions/UpdateRunnerTeam.ts @@ -6,21 +6,29 @@ import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { RunnerTeam } from '../entities/RunnerTeam'; import { CreateRunnerGroup } from './CreateRunnerGroup'; +/** + * This class is used to update a RunnerTeam entity (via put request). + */ export class UpdateRunnerTeam extends CreateRunnerGroup { /** * The updated team's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). */ @IsInt() id: number; /** - * The team's parent group (organisation). + * The updated team's parentGroup. + * Just has to contain the organisation's id - everything else won't be checked or changed. */ @IsObject() @IsNotEmpty() parentGroup: RunnerOrganisation; + /** + * Loads the updated teams's parentGroup based on it's id. + */ public async getParent(): Promise { if (this.parentGroup === undefined || this.parentGroup === null) { throw new RunnerTeamNeedsParentError(); @@ -35,7 +43,7 @@ export class UpdateRunnerTeam extends CreateRunnerGroup { } /** - * Creates a RunnerTeam entity from this. + * Updates a provided RunnerTeam entity based on this. */ public async updateRunnerTeam(team: RunnerTeam): Promise { diff --git a/src/models/actions/UpdateUser.ts b/src/models/actions/UpdateUser.ts index f91e7a5..626b096 100644 --- a/src/models/actions/UpdateUser.ts +++ b/src/models/actions/UpdateUser.ts @@ -7,10 +7,14 @@ import { UserGroupNotFoundError } from '../../errors/UserGroupErrors'; import { User } from '../entities/User'; import { UserGroup } from '../entities/UserGroup'; +/** + * This class is used to update a User entity (via put request). + */ export class UpdateUser { /** - * The updated users's id. + * The updated user's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). */ @IsInt() id: number; @@ -23,7 +27,6 @@ export class UpdateUser { /** * The updated user's middle name. - * Optinal. */ @IsString() @IsOptional() @@ -54,14 +57,16 @@ export class UpdateUser { /** * The updated user's phone number. - * Optional + * This will be validated against the configured country phone numer syntax (default: international). */ @IsPhoneNumber(config.phone_validation_countrycode) @IsOptional() phone?: string; /** - * The new updated's password. Only provide if you want it updated. + * The new updated's password. + * Only provide it if you want it updated. + * Changeing the password will invalidate all of the user's jwts. * This will of course not be saved in plaintext :) */ @IsString() @@ -75,15 +80,14 @@ export class UpdateUser { enabled: boolean = true; /** - * The new user's groups' id(s). - * You can provide either one groupId or an array of groupIDs. - * Optional. + * The updated user's groups. + * This just has to contain the group's id - everything else won't be changed. */ @IsOptional() groups?: UserGroup[] /** - * Creates a User entity from this. + * Updates a provided User entity based on this. */ public async updateUser(user: User): Promise { user.email = this.email; @@ -107,6 +111,9 @@ export class UpdateUser { return user; } + /** + * Loads the updated user's groups based on their ids. + */ public async getGroups() { if (!this.groups) { return null; } let groups = new Array();