Merge pull request 'Updated the put methods and cleaned up a shitload of comments' (#42) from feature/39-update_puts into dev
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #42 closes #39
This commit is contained in:
commit
1bf6d3d564
@ -96,7 +96,7 @@ export class PermissionController {
|
|||||||
return new ResponsePermission(existingPermission);
|
return new ResponsePermission(existingPermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.permissionRepository.update(oldPermission, await permission.toPermission());
|
await this.permissionRepository.save(await permission.updatePermission(oldPermission));
|
||||||
|
|
||||||
return new ResponsePermission(await this.permissionRepository.findOne({ id: permission.id }, { relations: ['principal'] }));
|
return new ResponsePermission(await this.permissionRepository.findOne({ id: permission.id }, { relations: ['principal'] }));
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ export class RunnerController {
|
|||||||
throw new RunnerIdsNotMatchingError();
|
throw new RunnerIdsNotMatchingError();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.runnerRepository.update(oldRunner, await runner.toRunner());
|
await this.runnerRepository.save(await runner.updateRunner(oldRunner));
|
||||||
return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] }));
|
return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers';
|
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers';
|
||||||
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
|
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
|
||||||
import { getConnectionManager, Repository } from 'typeorm';
|
import { getConnectionManager, Repository } from 'typeorm';
|
||||||
import { EntityFromBody } from 'typeorm-routing-controllers-extensions';
|
|
||||||
import { RunnerOrganisationHasRunnersError, RunnerOrganisationHasTeamsError, RunnerOrganisationIdsNotMatchingError, RunnerOrganisationNotFoundError } from '../errors/RunnerOrganisationErrors';
|
import { RunnerOrganisationHasRunnersError, RunnerOrganisationHasTeamsError, RunnerOrganisationIdsNotMatchingError, RunnerOrganisationNotFoundError } from '../errors/RunnerOrganisationErrors';
|
||||||
import { CreateRunnerOrganisation } from '../models/actions/CreateRunnerOrganisation';
|
import { CreateRunnerOrganisation } from '../models/actions/CreateRunnerOrganisation';
|
||||||
|
import { UpdateRunnerOrganisation } from '../models/actions/UpdateRunnerOrganisation';
|
||||||
import { RunnerOrganisation } from '../models/entities/RunnerOrganisation';
|
import { RunnerOrganisation } from '../models/entities/RunnerOrganisation';
|
||||||
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
|
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
|
||||||
import { ResponseRunnerOrganisation } from '../models/responses/ResponseRunnerOrganisation';
|
import { ResponseRunnerOrganisation } from '../models/responses/ResponseRunnerOrganisation';
|
||||||
@ -71,21 +71,20 @@ export class RunnerOrganisationController {
|
|||||||
@ResponseSchema(RunnerOrganisationNotFoundError, { statusCode: 404 })
|
@ResponseSchema(RunnerOrganisationNotFoundError, { statusCode: 404 })
|
||||||
@ResponseSchema(RunnerOrganisationIdsNotMatchingError, { statusCode: 406 })
|
@ResponseSchema(RunnerOrganisationIdsNotMatchingError, { statusCode: 406 })
|
||||||
@OpenAPI({ description: "Update a runnerOrganisation object (id can't be changed)." })
|
@OpenAPI({ description: "Update a runnerOrganisation object (id can't be changed)." })
|
||||||
async put(@Param('id') id: number, @EntityFromBody() runnerOrganisation: RunnerOrganisation) {
|
async put(@Param('id') id: number, @Body({ validate: true }) updateOrganisation: UpdateRunnerOrganisation) {
|
||||||
let oldRunnerOrganisation = await this.runnerOrganisationRepository.findOne({ id: id });
|
let oldRunnerOrganisation = await this.runnerOrganisationRepository.findOne({ id: id });
|
||||||
|
|
||||||
if (!oldRunnerOrganisation) {
|
if (!oldRunnerOrganisation) {
|
||||||
throw new RunnerOrganisationNotFoundError();
|
throw new RunnerOrganisationNotFoundError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldRunnerOrganisation.id != runnerOrganisation.id) {
|
if (oldRunnerOrganisation.id != updateOrganisation.id) {
|
||||||
throw new RunnerOrganisationIdsNotMatchingError();
|
throw new RunnerOrganisationIdsNotMatchingError();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.runnerOrganisationRepository.update(oldRunnerOrganisation, runnerOrganisation);
|
await this.runnerOrganisationRepository.save(await updateOrganisation.updateRunnerOrganisation(oldRunnerOrganisation));
|
||||||
|
|
||||||
runnerOrganisation = await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['address', 'contact', 'teams'] });
|
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['address', 'contact', 'teams'] }));
|
||||||
return new ResponseRunnerOrganisation(runnerOrganisation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete('/:id')
|
@Delete('/:id')
|
||||||
|
@ -82,7 +82,7 @@ export class RunnerTeamController {
|
|||||||
throw new RunnerTeamIdsNotMatchingError();
|
throw new RunnerTeamIdsNotMatchingError();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.runnerTeamRepository.update(oldRunnerTeam, await runnerTeam.toRunnerTeam());
|
await this.runnerTeamRepository.save(await runnerTeam.updateRunnerTeam(oldRunnerTeam));
|
||||||
|
|
||||||
return new ResponseRunnerTeam(await this.runnerTeamRepository.findOne({ id: runnerTeam.id }, { relations: ['parentGroup', 'contact'] }));
|
return new ResponseRunnerTeam(await this.runnerTeamRepository.findOne({ id: runnerTeam.id }, { relations: ['parentGroup', 'contact'] }));
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ export class TrackController {
|
|||||||
throw new TrackIdsNotMatchingError();
|
throw new TrackIdsNotMatchingError();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.trackRepository.update(oldTrack, track);
|
await this.trackRepository.save(track);
|
||||||
return new ResponseTrack(track);
|
return new ResponseTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +73,6 @@ export class UserController {
|
|||||||
@OpenAPI({ description: "Update a user object (id can't be changed)." })
|
@OpenAPI({ description: "Update a user object (id can't be changed)." })
|
||||||
async put(@Param('id') id: number, @Body({ validate: true }) updateUser: UpdateUser) {
|
async put(@Param('id') id: number, @Body({ validate: true }) updateUser: UpdateUser) {
|
||||||
let oldUser = await this.userRepository.findOne({ id: id });
|
let oldUser = await this.userRepository.findOne({ id: id });
|
||||||
delete oldUser.permissions;
|
|
||||||
delete oldUser.groups;
|
|
||||||
delete oldUser.actions;
|
|
||||||
|
|
||||||
if (!oldUser) {
|
if (!oldUser) {
|
||||||
throw new UserNotFoundError();
|
throw new UserNotFoundError();
|
||||||
@ -84,7 +81,7 @@ export class UserController {
|
|||||||
if (oldUser.id != updateUser.id) {
|
if (oldUser.id != updateUser.id) {
|
||||||
throw new UserIdsNotMatchingError();
|
throw new UserIdsNotMatchingError();
|
||||||
}
|
}
|
||||||
await this.userRepository.save(await updateUser.toUser(oldUser));
|
await this.userRepository.save(await updateUser.updateUser(oldUser));
|
||||||
|
|
||||||
return new ResponseUser(await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups'] }));
|
return new ResponseUser(await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups'] }));
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ export class UserGroupController {
|
|||||||
throw new UserGroupIdsNotMatchingError();
|
throw new UserGroupIdsNotMatchingError();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.userGroupsRepository.update(oldUserGroup, userGroup);
|
await this.userGroupsRepository.save(userGroup);
|
||||||
return userGroup;
|
return userGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,63 +1,57 @@
|
|||||||
import { IsString } from 'class-validator';
|
import { IsString } from 'class-validator';
|
||||||
import { ForbiddenError, NotAcceptableError, NotFoundError, UnauthorizedError } from 'routing-controllers';
|
import { ForbiddenError, NotAcceptableError, NotFoundError, UnauthorizedError } from 'routing-controllers';
|
||||||
|
|
||||||
/**
|
|
||||||
* Error to throw when a jwt is expired.
|
|
||||||
*/
|
|
||||||
export class ExpiredJWTError extends UnauthorizedError {
|
|
||||||
@IsString()
|
|
||||||
name = "ExpiredJWTError"
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
message = "your provided jwt is expired"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a jwt could not be parsed.
|
* Error to throw when a jwt could not be parsed.
|
||||||
|
* For example: Wrong signature or expired.
|
||||||
*/
|
*/
|
||||||
export class IllegalJWTError extends UnauthorizedError {
|
export class IllegalJWTError extends UnauthorizedError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "IllegalJWTError"
|
name = "IllegalJWTError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "your provided jwt could not be parsed"
|
message = "Your provided jwt could not be parsed."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when user is nonexistant or refreshtoken is invalid.
|
* Error to throw when user is nonexistant or refreshtoken is invalid.
|
||||||
|
* This can happen if someone provides a JWT with a invalid user id or the refreshTokenCount of the user is higher that the provided jwt's is.
|
||||||
*/
|
*/
|
||||||
export class UserNonexistantOrRefreshtokenInvalidError extends UnauthorizedError {
|
export class UserNonexistantOrRefreshtokenInvalidError extends UnauthorizedError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "UserNonexistantOrRefreshtokenInvalidError"
|
name = "UserNonexistantOrRefreshtokenInvalidError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "user is nonexistant or refreshtoken is invalid"
|
message = "User is nonexistant or refreshtoken is invalid."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when provided credentials are invalid.
|
* Error to throw when provided credentials are invalid.
|
||||||
|
* We don't have seperate errors for username/mail and passwords to protect against guessing attacks.
|
||||||
*/
|
*/
|
||||||
export class InvalidCredentialsError extends UnauthorizedError {
|
export class InvalidCredentialsError extends UnauthorizedError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "InvalidCredentialsError"
|
name = "InvalidCredentialsError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "your provided credentials are invalid"
|
message = "Your provided credentials are invalid."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a jwt does not have permission for this route/action.
|
* Error to throw when a jwt does not have permission for this route/action.
|
||||||
|
* Mainly used be the @Authorized decorator (via the authchecker).
|
||||||
*/
|
*/
|
||||||
export class NoPermissionError extends ForbiddenError {
|
export class NoPermissionError extends ForbiddenError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "NoPermissionError"
|
name = "NoPermissionError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "your provided jwt does not have permission for this route/ action"
|
message = "Your provided jwt does not have permission for this route/ action."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when no username and no email is set.
|
* Error to throw when no username and no email is set.
|
||||||
|
* Because we have to identify users somehow.
|
||||||
*/
|
*/
|
||||||
export class UsernameOrEmailNeededError extends NotAcceptableError {
|
export class UsernameOrEmailNeededError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -68,47 +62,48 @@ export class UsernameOrEmailNeededError extends NotAcceptableError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when no password is provided.
|
* Error to throw when no password is provided for a new user.
|
||||||
|
* Passwords are the minimum we need for user security.
|
||||||
*/
|
*/
|
||||||
export class PasswordNeededError extends NotAcceptableError {
|
export class PasswordNeededError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "PasswordNeededError"
|
name = "PasswordNeededError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "no password is provided - you need to provide it"
|
message = "No password is provided - you need to provide it."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when no user could be found mating the provided credential.
|
* Error to throw when no user could be found for a certain query.
|
||||||
*/
|
*/
|
||||||
export class UserNotFoundError extends NotFoundError {
|
export class UserNotFoundError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "UserNotFoundError"
|
name = "UserNotFoundError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "no user could be found for provided credential"
|
message = "The user you provided couldn't be located in the system. \n Please check your request."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when no jwt token was provided (but one had to be).
|
* Error to throw when no jwt was provided (but one had to be).
|
||||||
*/
|
*/
|
||||||
export class JwtNotProvidedError extends NotAcceptableError {
|
export class JwtNotProvidedError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "JwtNotProvidedError"
|
name = "JwtNotProvidedError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "no jwt token was provided"
|
message = "No jwt was provided."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when user was not found or refresh token count was invalid.
|
* Error to throw when user was not found or the jwt's refresh token count was invalid.
|
||||||
*/
|
*/
|
||||||
export class UserNotFoundOrRefreshTokenCountInvalidError extends NotAcceptableError {
|
export class UserNotFoundOrRefreshTokenCountInvalidError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "UserNotFoundOrRefreshTokenCountInvalidError"
|
name = "UserNotFoundOrRefreshTokenCountInvalidError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "user was not found or refresh token count was invalid"
|
message = "User was not found or the refresh token count is invalid."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,5 +114,5 @@ export class RefreshTokenCountInvalidError extends NotAcceptableError {
|
|||||||
name = "RefreshTokenCountInvalidError"
|
name = "RefreshTokenCountInvalidError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "refresh token count was invalid"
|
message = "Refresh token count is invalid."
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ export class PermissionNotFoundError extends NotFoundError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when two permission' ids don't match.
|
* Error to throw when two permissions' ids don't match.
|
||||||
* Usually occurs when a user tries to change a permission's id.
|
* Usually occurs when a user tries to change a permission's id.
|
||||||
*/
|
*/
|
||||||
export class PermissionIdsNotMatchingError extends NotAcceptableError {
|
export class PermissionIdsNotMatchingError extends NotAcceptableError {
|
||||||
@ -21,11 +21,11 @@ export class PermissionIdsNotMatchingError extends NotAcceptableError {
|
|||||||
name = "PermissionIdsNotMatchingError"
|
name = "PermissionIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n And if you wanted to change a permission's id: This isn't allowed"
|
message = "The ids don't match! \n And if you wanted to change a permission's id: This isn't allowed!"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a permission get's provided without a principal.
|
* Error to throw when a permission gets provided without a principal.
|
||||||
*/
|
*/
|
||||||
export class PermissionNeedsPrincipalError extends NotAcceptableError {
|
export class PermissionNeedsPrincipalError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -3,7 +3,6 @@ import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a runner couldn't be found.
|
* Error to throw when a runner couldn't be found.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerNotFoundError extends NotFoundError {
|
export class RunnerNotFoundError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -16,14 +15,13 @@ export class RunnerNotFoundError extends NotFoundError {
|
|||||||
/**
|
/**
|
||||||
* Error to throw when two runners' ids don't match.
|
* Error to throw when two runners' ids don't match.
|
||||||
* Usually occurs when a user tries to change a runner's id.
|
* Usually occurs when a user tries to change a runner's id.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerIdsNotMatchingError extends NotAcceptableError {
|
export class RunnerIdsNotMatchingError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "RunnerIdsNotMatchingError"
|
name = "RunnerIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n And if you wanted to change a runner's id: This isn't allowed"
|
message = "The ids don't match! \n And if you wanted to change a runner's id: This isn't allowed!"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,6 @@ import { NotFoundError } from 'routing-controllers';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a runner group couldn't be found.
|
* Error to throw when a runner group couldn't be found.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerGroupNotFoundError extends NotFoundError {
|
export class RunnerGroupNotFoundError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -3,7 +3,6 @@ import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a runner organisation couldn't be found.
|
* Error to throw when a runner organisation couldn't be found.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerOrganisationNotFoundError extends NotFoundError {
|
export class RunnerOrganisationNotFoundError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -15,39 +14,36 @@ export class RunnerOrganisationNotFoundError extends NotFoundError {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when two runner organisations' ids don't match.
|
* Error to throw when two runner organisations' ids don't match.
|
||||||
* Usually occurs when a user tries to change a runner's id.
|
* Usually occurs when a user tries to change a runner organisation's id.
|
||||||
* Implemented this way to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerOrganisationIdsNotMatchingError extends NotAcceptableError {
|
export class RunnerOrganisationIdsNotMatchingError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "RunnerOrganisationIdsNotMatchingError"
|
name = "RunnerOrganisationIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n And if you wanted to change a runner's id: This isn't allowed"
|
message = "The ids don't match! \n And if you wanted to change a runner organisation's id: This isn't allowed!"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a organisation still has runners associated.
|
* Error to throw when a organisation still has runners associated.
|
||||||
* Implemented this waysto work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerOrganisationHasRunnersError extends NotAcceptableError {
|
export class RunnerOrganisationHasRunnersError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "RunnerOrganisationHasRunnersError"
|
name = "RunnerOrganisationHasRunnersError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "This organisation still has runners associated with it. \n If you want to delete this organisation with all it's runners and teams ass `?force` to your query."
|
message = "This organisation still has runners associated with it. \n If you want to delete this organisation with all it's runners and teams add `?force` to your query."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a organisation still has runners associated.
|
* Error to throw when a organisation still has teams associated.
|
||||||
* Implemented this waysto work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerOrganisationHasTeamsError extends NotAcceptableError {
|
export class RunnerOrganisationHasTeamsError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "RunnerOrganisationHasTeamsError"
|
name = "RunnerOrganisationHasTeamsError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "This organisation still has teams associated with it. \n If you want to delete this organisation with all it's runners and teams ass `?force` to your query."
|
message = "This organisation still has teams associated with it. \n If you want to delete this organisation with all it's runners and teams add `?force` to your query."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,6 @@ import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a runner team couldn't be found.
|
* Error to throw when a runner team couldn't be found.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerTeamNotFoundError extends NotFoundError {
|
export class RunnerTeamNotFoundError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -15,32 +14,29 @@ export class RunnerTeamNotFoundError extends NotFoundError {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when two runner teams' ids don't match.
|
* Error to throw when two runner teams' ids don't match.
|
||||||
* Usually occurs when a user tries to change a runner's id.
|
* Usually occurs when a user tries to change a runner team's id.
|
||||||
* Implemented this way to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerTeamIdsNotMatchingError extends NotAcceptableError {
|
export class RunnerTeamIdsNotMatchingError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "RunnerTeamIdsNotMatchingError"
|
name = "RunnerTeamIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n And if you wanted to change a runner's id: This isn't allowed"
|
message = "The ids don't match! \n And if you wanted to change a runner's id: This isn't allowed!"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a team still has runners associated.
|
* Error to throw when a team still has runners associated.
|
||||||
* Implemented this waysto work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerTeamHasRunnersError extends NotAcceptableError {
|
export class RunnerTeamHasRunnersError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "RunnerTeamHasRunnersError"
|
name = "RunnerTeamHasRunnersError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "This team still has runners associated with it. \n If you want to delete this team with all it's runners and teams ass `?force` to your query."
|
message = "This team still has runners associated with it. \n If you want to delete this team with all it's runners and teams add `?force` to your query."
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a team still has runners associated.
|
* Error to throw when a team still has runners associated.
|
||||||
* Implemented this waysto work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class RunnerTeamNeedsParentError extends NotAcceptableError {
|
export class RunnerTeamNeedsParentError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { JsonController, Param, Body, Get, Post, Put, Delete, NotFoundError, OnUndefined, NotAcceptableError } from 'routing-controllers';
|
import { IsString } from 'class-validator';
|
||||||
import { IsInt, IsNotEmpty, IsPositive, IsString } from 'class-validator';
|
import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when a track couldn't be found.
|
* Error to throw when a track couldn't be found.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class TrackNotFoundError extends NotFoundError {
|
export class TrackNotFoundError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -16,12 +15,11 @@ export class TrackNotFoundError extends NotFoundError {
|
|||||||
/**
|
/**
|
||||||
* Error to throw when two tracks' ids don't match.
|
* Error to throw when two tracks' ids don't match.
|
||||||
* Usually occurs when a user tries to change a track's id.
|
* Usually occurs when a user tries to change a track's id.
|
||||||
* Implemented this ways to work with the json-schema conversion for openapi.
|
|
||||||
*/
|
*/
|
||||||
export class TrackIdsNotMatchingError extends NotAcceptableError {
|
export class TrackIdsNotMatchingError extends NotAcceptableError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "TrackIdsNotMatchingError"
|
name = "TrackIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n And if you wanted to change a track's id: This isn't allowed"
|
message = "The ids don't match! \n And if you wanted to change a track's id: This isn't allowed"
|
||||||
}
|
}
|
@ -3,14 +3,15 @@ import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when no username or email is set
|
* Error to throw when no username or email is set.
|
||||||
|
* We somehow need to identify you :)
|
||||||
*/
|
*/
|
||||||
export class UsernameOrEmailNeededError extends NotFoundError {
|
export class UsernameOrEmailNeededError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "UsernameOrEmailNeededError"
|
name = "UsernameOrEmailNeededError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "no username or email is set!"
|
message = "No username or email is set!"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,5 +34,5 @@ export class UserIdsNotMatchingError extends NotAcceptableError {
|
|||||||
name = "UserIdsNotMatchingError"
|
name = "UserIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n And if you wanted to change a user's id: This isn't allowed"
|
message = "The ids don't match!! \n And if you wanted to change a user's id: This isn't allowed!"
|
||||||
}
|
}
|
@ -2,14 +2,14 @@ import { IsString } from 'class-validator';
|
|||||||
import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error to throw when no groupname is set
|
* Error to throw when no groupname is set.
|
||||||
*/
|
*/
|
||||||
export class GroupNameNeededError extends NotFoundError {
|
export class GroupNameNeededError extends NotFoundError {
|
||||||
@IsString()
|
@IsString()
|
||||||
name = "GroupNameNeededError"
|
name = "GroupNameNeededError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "no groupname is set!"
|
message = "No name is set for this group!"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,5 +32,5 @@ export class UserGroupIdsNotMatchingError extends NotAcceptableError {
|
|||||||
name = "UserGroupIdsNotMatchingError"
|
name = "UserGroupIdsNotMatchingError"
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
message = "The id's don't match!! \n If you wanted to change a usergroup's id: This isn't allowed"
|
message = "The ids don't match!! \n If you wanted to change a usergroup's id: This isn't allowed!"
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import { User } from '../models/entities/User';
|
|||||||
import SeedUsers from '../seeds/SeedUsers';
|
import SeedUsers from '../seeds/SeedUsers';
|
||||||
/**
|
/**
|
||||||
* Loader for the database that creates the database connection and initializes the database tabels.
|
* Loader for the database that creates the database connection and initializes the database tabels.
|
||||||
|
* It also triggers the seeding process if no users got detected in the database.
|
||||||
*/
|
*/
|
||||||
export default async () => {
|
export default async () => {
|
||||||
const connection = await createConnection();
|
const connection = await createConnection();
|
||||||
|
@ -2,7 +2,7 @@ import cookieParser from "cookie-parser";
|
|||||||
import { Application } from "express";
|
import { Application } from "express";
|
||||||
/**
|
/**
|
||||||
* Loader for express related configurations.
|
* Loader for express related configurations.
|
||||||
* Currently only enables the proxy trust.
|
* Configures proxy trusts, globally used middlewares and other express features.
|
||||||
*/
|
*/
|
||||||
export default async (app: Application) => {
|
export default async (app: Application) => {
|
||||||
app.enable('trust proxy');
|
app.enable('trust proxy');
|
||||||
|
@ -5,6 +5,7 @@ import openapiLoader from "./openapi";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Index Loader that executes the other loaders in the right order.
|
* Index Loader that executes the other loaders in the right order.
|
||||||
|
* This basicly exists for abstraction and a overall better dev experience.
|
||||||
*/
|
*/
|
||||||
export default async (app: Application) => {
|
export default async (app: Application) => {
|
||||||
await databaseLoader();
|
await databaseLoader();
|
||||||
|
@ -5,7 +5,8 @@ import { routingControllersToSpec } from "routing-controllers-openapi";
|
|||||||
import * as swaggerUiExpress from "swagger-ui-express";
|
import * as swaggerUiExpress from "swagger-ui-express";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loader for everything openapi related - from creating the schema to serving it via a static route.
|
* Loader for everything openapi related - from creating the schema to serving it via a static route and swaggerUiExpress.
|
||||||
|
* All auth schema related stuff also has to be configured here
|
||||||
*/
|
*/
|
||||||
export default async (app: Application) => {
|
export default async (app: Application) => {
|
||||||
const storage = getMetadataArgsStorage();
|
const storage = getMetadataArgsStorage();
|
||||||
@ -26,7 +27,8 @@ export default async (app: Application) => {
|
|||||||
"AuthToken": {
|
"AuthToken": {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"scheme": "bearer",
|
"scheme": "bearer",
|
||||||
"bearerFormat": "JWT"
|
"bearerFormat": "JWT",
|
||||||
|
description: "A JWT based access token. Use /api/auth/login or /api/auth/refresh to get one."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ExpressErrorMiddlewareInterface, Middleware } from "routing-controllers";
|
import { ExpressErrorMiddlewareInterface, Middleware } from "routing-controllers";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our Error handling middlware that returns our custom httperrors to the user
|
* Our Error handling middlware that returns our custom httperrors to the user.
|
||||||
*/
|
*/
|
||||||
@Middleware({ type: "after" })
|
@Middleware({ type: "after" })
|
||||||
export class ErrorHandler implements ExpressErrorMiddlewareInterface {
|
export class ErrorHandler implements ExpressErrorMiddlewareInterface {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom express middleware that appends the raw body to the request obeject.
|
||||||
|
* Mainly used for parsing csvs from boddies.
|
||||||
|
*/
|
||||||
|
|
||||||
const RawBodyMiddleware = (req: Request, res: Response, next: () => void) => {
|
const RawBodyMiddleware = (req: Request, res: Response, next: () => void) => {
|
||||||
const body = []
|
const body = []
|
||||||
req.on('data', chunk => {
|
req.on('data', chunk => {
|
||||||
@ -8,15 +13,6 @@ const RawBodyMiddleware = (req: Request, res: Response, next: () => void) => {
|
|||||||
req.on('end', () => {
|
req.on('end', () => {
|
||||||
const rawBody = Buffer.concat(body)
|
const rawBody = Buffer.concat(body)
|
||||||
req['rawBody'] = rawBody
|
req['rawBody'] = rawBody
|
||||||
/*
|
|
||||||
switch (req.header('content-type')) {
|
|
||||||
case 'application/json':
|
|
||||||
req.body = JSON.parse(rawBody.toString())
|
|
||||||
break
|
|
||||||
// add more body parsing if needs be
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
req.on('error', () => {
|
req.on('error', () => {
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { IsNotEmpty, IsOptional, IsPostalCode, IsString } from 'class-validator';
|
import { IsNotEmpty, IsOptional, IsPostalCode, IsString } from 'class-validator';
|
||||||
import { Address } from '../entities/Address';
|
import { Address } from '../entities/Address';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new Address entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateAddress {
|
export class CreateAddress {
|
||||||
/**
|
/**
|
||||||
* The address's description.
|
* The newaddress's description.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's first line.
|
* The new address's first line.
|
||||||
* Containing the street and house number.
|
* Containing the street and house number.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -18,7 +21,7 @@ export class CreateAddress {
|
|||||||
address1: string;
|
address1: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's second line.
|
* The new address's second line.
|
||||||
* Containing optional information.
|
* Containing optional information.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -26,7 +29,9 @@ export class CreateAddress {
|
|||||||
address2?: string;
|
address2?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's postal code.
|
* The new address's postal code.
|
||||||
|
* This will get checked against the postal code syntax for the configured country.
|
||||||
|
* TODO: Implement the config option.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -34,21 +39,21 @@ export class CreateAddress {
|
|||||||
postalcode: string;
|
postalcode: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's city.
|
* The new address's city.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
city: string;
|
city: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's country.
|
* The new address's country.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
country: string;
|
country: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Address object based on this.
|
* Creates a new Address entity from this.
|
||||||
*/
|
*/
|
||||||
public toAddress(): Address {
|
public toAddress(): Address {
|
||||||
let newAddress: Address = new Address();
|
let newAddress: Address = new Address();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import * as argon2 from "argon2";
|
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 { getConnectionManager } from 'typeorm';
|
||||||
import { InvalidCredentialsError, PasswordNeededError, UserNotFoundError } from '../../errors/AuthError';
|
import { InvalidCredentialsError, PasswordNeededError, UserNotFoundError } from '../../errors/AuthError';
|
||||||
import { UsernameOrEmailNeededError } from '../../errors/UserErrors';
|
import { UsernameOrEmailNeededError } from '../../errors/UserErrors';
|
||||||
@ -7,17 +7,41 @@ import { JwtCreator } from '../../jwtcreator';
|
|||||||
import { User } from '../entities/User';
|
import { User } from '../entities/User';
|
||||||
import { Auth } from '../responses/ResponseAuth';
|
import { Auth } from '../responses/ResponseAuth';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to create auth credentials based on user credentials provided in a json body (post request).
|
||||||
|
* 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 {
|
export class CreateAuth {
|
||||||
|
/**
|
||||||
|
* The username of the user that want's to login.
|
||||||
|
* Either username or email have to be provided.
|
||||||
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
username?: string;
|
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()
|
@IsOptional()
|
||||||
@IsEmail()
|
@IsEmail()
|
||||||
@IsString()
|
@IsString()
|
||||||
email?: string;
|
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<Auth> {
|
public async toAuth(): Promise<Auth> {
|
||||||
let newAuth: Auth = new Auth();
|
let newAuth: Auth = new Auth();
|
||||||
|
|
||||||
|
@ -5,32 +5,34 @@ import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/Addres
|
|||||||
import { Address } from '../entities/Address';
|
import { Address } from '../entities/Address';
|
||||||
import { GroupContact } from '../entities/GroupContact';
|
import { GroupContact } from '../entities/GroupContact';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new Group entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateGroupContact {
|
export class CreateGroupContact {
|
||||||
/**
|
/**
|
||||||
* The contact's first name.
|
* The new contact's first name.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
firstname: string;
|
firstname: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's middle name.
|
* The new contact's middle name.
|
||||||
* Optional
|
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
middlename?: string;
|
middlename?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's last name.
|
* The new contact's last name.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
lastname: string;
|
lastname: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's address.
|
* The new contact's address.
|
||||||
* Optional
|
* Must be the address's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -38,7 +40,7 @@ export class CreateGroupContact {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's phone number.
|
* The contact's phone number.
|
||||||
* Optional
|
* This will be validated against the configured country phone numer syntax (default: international).
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsPhoneNumber(config.phone_validation_countrycode)
|
@IsPhoneNumber(config.phone_validation_countrycode)
|
||||||
@ -46,17 +48,16 @@ export class CreateGroupContact {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's email address.
|
* The contact's email address.
|
||||||
* Optional
|
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsEmail()
|
@IsEmail()
|
||||||
email?: string;
|
email?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get's this participant's address from this.address.
|
* Gets the new contact's address by it's id.
|
||||||
*/
|
*/
|
||||||
public async getAddress(): Promise<Address> {
|
public async getAddress(): Promise<Address> {
|
||||||
if (this.address === undefined) {
|
if (this.address === undefined || this.address === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!isNaN(this.address)) {
|
if (!isNaN(this.address)) {
|
||||||
@ -69,7 +70,7 @@ export class CreateGroupContact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Address object based on this.
|
* Creates a new Address entity from this.
|
||||||
*/
|
*/
|
||||||
public async toGroupContact(): Promise<GroupContact> {
|
public async toGroupContact(): Promise<GroupContact> {
|
||||||
let contact: GroupContact = new GroupContact();
|
let contact: GroupContact = new GroupContact();
|
||||||
|
@ -4,6 +4,9 @@ import { config } from '../../config';
|
|||||||
import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors';
|
import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors';
|
||||||
import { Address } from '../entities/Address';
|
import { Address } from '../entities/Address';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new Participant entity from a json body (post request).
|
||||||
|
*/
|
||||||
export abstract class CreateParticipant {
|
export abstract class CreateParticipant {
|
||||||
/**
|
/**
|
||||||
* The new participant's first name.
|
* The new participant's first name.
|
||||||
@ -14,7 +17,6 @@ export abstract class CreateParticipant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The new participant's middle name.
|
* The new participant's middle name.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -29,7 +31,7 @@ export abstract class CreateParticipant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The new participant's phone number.
|
* The new participant's phone number.
|
||||||
* Optional.
|
* This will be validated against the configured country phone numer syntax (default: international).
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -38,7 +40,6 @@ export abstract class CreateParticipant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The new participant's e-mail address.
|
* The new participant's e-mail address.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -48,17 +49,16 @@ export abstract class CreateParticipant {
|
|||||||
/**
|
/**
|
||||||
* The new participant's address.
|
* The new participant's address.
|
||||||
* Must be of type number (address id).
|
* Must be of type number (address id).
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
address?: number;
|
address?: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get's this participant's address from this.address.
|
* Gets the new participant's address by it's address.
|
||||||
*/
|
*/
|
||||||
public async getAddress(): Promise<Address> {
|
public async getAddress(): Promise<Address> {
|
||||||
if (this.address === undefined) {
|
if (this.address === undefined || this.address === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!isNaN(this.address)) {
|
if (!isNaN(this.address)) {
|
||||||
|
@ -11,33 +11,33 @@ import { PermissionAction } from '../enums/PermissionAction';
|
|||||||
import { PermissionTarget } from '../enums/PermissionTargets';
|
import { PermissionTarget } from '../enums/PermissionTargets';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a track of given length.
|
* This classed is used to create a new Permission entity from a json body (post request).
|
||||||
*/
|
*/
|
||||||
export class CreatePermission {
|
export class CreatePermission {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The permissions's principal's id.
|
* The new permissions's principal's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
principal: number;
|
principal: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The permissions's target.
|
* The new permissions's target.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsEnum(PermissionTarget)
|
@IsEnum(PermissionTarget)
|
||||||
target: PermissionTarget;
|
target: PermissionTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The permissions's action.
|
* The new permissions's action.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsEnum(PermissionAction)
|
@IsEnum(PermissionAction)
|
||||||
action: PermissionAction;
|
action: PermissionAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Permission object based on this.
|
* Creates a new Permission entity from this.
|
||||||
*/
|
*/
|
||||||
public async toPermission(): Promise<Permission> {
|
public async toPermission(): Promise<Permission> {
|
||||||
let newPermission: Permission = new Permission();
|
let newPermission: Permission = new Permission();
|
||||||
@ -49,6 +49,9 @@ export class CreatePermission {
|
|||||||
return newPermission;
|
return newPermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the new permission's principal by it's id.
|
||||||
|
*/
|
||||||
public async getPrincipal(): Promise<Principal> {
|
public async getPrincipal(): Promise<Principal> {
|
||||||
let principal = await getConnectionManager().get().getRepository(Principal).findOne({ id: this.principal })
|
let principal = await getConnectionManager().get().getRepository(Principal).findOne({ id: this.principal })
|
||||||
if (!principal) { throw new PrincipalNotFoundError(); }
|
if (!principal) { throw new PrincipalNotFoundError(); }
|
||||||
|
@ -7,6 +7,9 @@ import { Runner } from '../entities/Runner';
|
|||||||
import { RunnerGroup } from '../entities/RunnerGroup';
|
import { RunnerGroup } from '../entities/RunnerGroup';
|
||||||
import { CreateParticipant } from './CreateParticipant';
|
import { CreateParticipant } from './CreateParticipant';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new Runner entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateRunner extends CreateParticipant {
|
export class CreateRunner extends CreateParticipant {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,7 +19,7 @@ export class CreateRunner extends CreateParticipant {
|
|||||||
group: number;
|
group: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Runner entity from this.
|
* Creates a new Runner entity from this.
|
||||||
*/
|
*/
|
||||||
public async toRunner(): Promise<Runner> {
|
public async toRunner(): Promise<Runner> {
|
||||||
let newRunner: Runner = new Runner();
|
let newRunner: Runner = new Runner();
|
||||||
@ -33,10 +36,10 @@ export class CreateRunner extends CreateParticipant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages all the different ways a group can be provided.
|
* Gets the new runner's group by it's id.
|
||||||
*/
|
*/
|
||||||
public async getGroup(): Promise<RunnerGroup> {
|
public async getGroup(): Promise<RunnerGroup> {
|
||||||
if (this.group === undefined) {
|
if (this.group === undefined || this.group === null) {
|
||||||
throw new RunnerTeamNeedsParentError();
|
throw new RunnerTeamNeedsParentError();
|
||||||
}
|
}
|
||||||
if (!isNaN(this.group)) {
|
if (!isNaN(this.group)) {
|
||||||
|
@ -3,16 +3,19 @@ import { getConnectionManager } from 'typeorm';
|
|||||||
import { GroupContactNotFoundError, GroupContactWrongTypeError } from '../../errors/GroupContactErrors';
|
import { GroupContactNotFoundError, GroupContactWrongTypeError } from '../../errors/GroupContactErrors';
|
||||||
import { GroupContact } from '../entities/GroupContact';
|
import { GroupContact } from '../entities/GroupContact';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new RunnerGroup entity from a json body (post request).
|
||||||
|
*/
|
||||||
export abstract class CreateRunnerGroup {
|
export abstract class CreateRunnerGroup {
|
||||||
/**
|
/**
|
||||||
* The group's name.
|
* The new group's name.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The group's contact.
|
* The new group's contact.
|
||||||
* Optional
|
* Optional
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@ -20,7 +23,7 @@ export abstract class CreateRunnerGroup {
|
|||||||
contact?: number;
|
contact?: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get's this group's contact from this.address.
|
* Gets the new group's contact by it's id.
|
||||||
*/
|
*/
|
||||||
public async getContact(): Promise<GroupContact> {
|
public async getContact(): Promise<GroupContact> {
|
||||||
if (this.contact === undefined || this.contact === null) {
|
if (this.contact === undefined || this.contact === null) {
|
||||||
|
@ -5,21 +5,23 @@ import { Address } from '../entities/Address';
|
|||||||
import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
||||||
import { CreateRunnerGroup } from './CreateRunnerGroup';
|
import { CreateRunnerGroup } from './CreateRunnerGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new RunnerOrganisation entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateRunnerOrganisation extends CreateRunnerGroup {
|
export class CreateRunnerOrganisation extends CreateRunnerGroup {
|
||||||
/**
|
/**
|
||||||
* The new organisation's address.
|
* The new organisation's address.
|
||||||
* Must be of type number (address id).
|
* Must be of type number (address id).
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
address?: number;
|
address?: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get's this org's address from this.address.
|
* Gets the org's address by it's id.
|
||||||
*/
|
*/
|
||||||
public async getAddress(): Promise<Address> {
|
public async getAddress(): Promise<Address> {
|
||||||
if (this.address === undefined) {
|
if (this.address === undefined || this.address === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!isNaN(this.address)) {
|
if (!isNaN(this.address)) {
|
||||||
@ -32,7 +34,7 @@ export class CreateRunnerOrganisation extends CreateRunnerGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a RunnerOrganisation entity from this.
|
* Creates a new RunnerOrganisation entity from this.
|
||||||
*/
|
*/
|
||||||
public async toRunnerOrganisation(): Promise<RunnerOrganisation> {
|
public async toRunnerOrganisation(): Promise<RunnerOrganisation> {
|
||||||
let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation();
|
let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation();
|
||||||
|
@ -6,17 +6,23 @@ import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
|||||||
import { RunnerTeam } from '../entities/RunnerTeam';
|
import { RunnerTeam } from '../entities/RunnerTeam';
|
||||||
import { CreateRunnerGroup } from './CreateRunnerGroup';
|
import { CreateRunnerGroup } from './CreateRunnerGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new RunnerTeam entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateRunnerTeam extends CreateRunnerGroup {
|
export class CreateRunnerTeam extends CreateRunnerGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The team's parent group (organisation).
|
* The new team's parent group (organisation).
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
parentGroup: number;
|
parentGroup: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the new team's parent org based on it's id.
|
||||||
|
*/
|
||||||
public async getParent(): Promise<RunnerOrganisation> {
|
public async getParent(): Promise<RunnerOrganisation> {
|
||||||
if (this.parentGroup === undefined) {
|
if (this.parentGroup === undefined || this.parentGroup === null) {
|
||||||
throw new RunnerTeamNeedsParentError();
|
throw new RunnerTeamNeedsParentError();
|
||||||
}
|
}
|
||||||
if (!isNaN(this.parentGroup)) {
|
if (!isNaN(this.parentGroup)) {
|
||||||
@ -29,7 +35,7 @@ export class CreateRunnerTeam extends CreateRunnerGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a RunnerTeam entity from this.
|
* Creates a new RunnerTeam entity from this.
|
||||||
*/
|
*/
|
||||||
public async toRunnerTeam(): Promise<RunnerTeam> {
|
public async toRunnerTeam(): Promise<RunnerTeam> {
|
||||||
let newRunnerTeam: RunnerTeam = new RunnerTeam();
|
let newRunnerTeam: RunnerTeam = new RunnerTeam();
|
||||||
|
@ -1,23 +1,26 @@
|
|||||||
import { IsInt, IsNotEmpty, IsPositive, IsString } from 'class-validator';
|
import { IsInt, IsNotEmpty, IsPositive, IsString } from 'class-validator';
|
||||||
import { Track } from '../entities/Track';
|
import { Track } from '../entities/Track';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new Track entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateTrack {
|
export class CreateTrack {
|
||||||
/**
|
/**
|
||||||
* The track's name.
|
* The new track's name.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The track's distance in meters (must be greater than 0).
|
* The new track's distance in meters (must be greater than 0).
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
distance: number;
|
distance: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Track object based on this.
|
* Creates a new Track entity from this.
|
||||||
*/
|
*/
|
||||||
public toTrack(): Track {
|
public toTrack(): Track {
|
||||||
let newTrack: Track = new Track();
|
let newTrack: Track = new Track();
|
||||||
|
@ -8,6 +8,9 @@ import { UserGroupNotFoundError } from '../../errors/UserGroupErrors';
|
|||||||
import { User } from '../entities/User';
|
import { User } from '../entities/User';
|
||||||
import { UserGroup } from '../entities/UserGroup';
|
import { UserGroup } from '../entities/UserGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new User entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateUser {
|
export class CreateUser {
|
||||||
/**
|
/**
|
||||||
* The new user's first name.
|
* The new user's first name.
|
||||||
@ -17,7 +20,6 @@ export class CreateUser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The new user's middle name.
|
* The new user's middle name.
|
||||||
* Optinal.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -48,7 +50,7 @@ export class CreateUser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The new user's phone number.
|
* The new user's phone number.
|
||||||
* Optional
|
* This will be validated against the configured country phone numer syntax (default: international).
|
||||||
*/
|
*/
|
||||||
@IsPhoneNumber(config.phone_validation_countrycode)
|
@IsPhoneNumber(config.phone_validation_countrycode)
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -64,7 +66,6 @@ export class CreateUser {
|
|||||||
/**
|
/**
|
||||||
* The new user's groups' id(s).
|
* The new user's groups' id(s).
|
||||||
* You can provide either one groupId or an array of groupIDs.
|
* You can provide either one groupId or an array of groupIDs.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
groups?: number[] | number
|
groups?: number[] | number
|
||||||
@ -72,7 +73,7 @@ export class CreateUser {
|
|||||||
//TODO: ProfilePics
|
//TODO: ProfilePics
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this to a User Entity.
|
* Converts this to a User entity.
|
||||||
*/
|
*/
|
||||||
public async toUser(): Promise<User> {
|
public async toUser(): Promise<User> {
|
||||||
let newUser: User = new User();
|
let newUser: User = new User();
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { IsOptional, IsString } from 'class-validator';
|
import { IsOptional, IsString } from 'class-validator';
|
||||||
import { UserGroup } from '../entities/UserGroup';
|
import { UserGroup } from '../entities/UserGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This classed is used to create a new UserGroup entity from a json body (post request).
|
||||||
|
*/
|
||||||
export class CreateUserGroup {
|
export class CreateUserGroup {
|
||||||
/**
|
/**
|
||||||
* The new group's name.
|
* The new group's name.
|
||||||
@ -17,7 +20,7 @@ export class CreateUserGroup {
|
|||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this to a UserGroup entity.
|
* Creates a new UserGroup entity from this.
|
||||||
*/
|
*/
|
||||||
public async toUserGroup(): Promise<UserGroup> {
|
public async toUserGroup(): Promise<UserGroup> {
|
||||||
let newUserGroup: UserGroup = new UserGroup();
|
let newUserGroup: UserGroup = new UserGroup();
|
||||||
|
@ -6,11 +6,23 @@ import { IllegalJWTError, JwtNotProvidedError, RefreshTokenCountInvalidError, Us
|
|||||||
import { User } from '../entities/User';
|
import { User } from '../entities/User';
|
||||||
import { Logout } from '../responses/ResponseLogout';
|
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 {
|
export class HandleLogout {
|
||||||
|
/**
|
||||||
|
* A stringyfied jwt access token.
|
||||||
|
* Will get checked for validity.
|
||||||
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
token?: string;
|
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<Logout> {
|
public async logout(): Promise<Logout> {
|
||||||
let logout: Logout = new Logout();
|
let logout: Logout = new Logout();
|
||||||
if (!this.token || this.token === undefined) {
|
if (!this.token || this.token === undefined) {
|
||||||
|
@ -7,6 +7,10 @@ import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
|||||||
import { RunnerTeam } from '../entities/RunnerTeam';
|
import { RunnerTeam } from '../entities/RunnerTeam';
|
||||||
import { CreateRunner } from './CreateRunner';
|
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 {
|
export class ImportRunner {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,7 +22,6 @@ export class ImportRunner {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The new runner's middle name.
|
* The new runner's middle name.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -32,18 +35,26 @@ export class ImportRunner {
|
|||||||
lastname: string;
|
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()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
team?: string;
|
team?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just an alias for team, because this is usually only used for importing data from schools.
|
||||||
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
public set class(value: string) {
|
public set class(value: string) {
|
||||||
this.team = value;
|
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<CreateRunner> {
|
public async toCreateRunner(groupID: number): Promise<CreateRunner> {
|
||||||
let newRunner: CreateRunner = new CreateRunner();
|
let newRunner: CreateRunner = new CreateRunner();
|
||||||
|
|
||||||
@ -55,6 +66,10 @@ export class ImportRunner {
|
|||||||
return newRunner;
|
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<RunnerGroup> {
|
public async getGroup(groupID: number): Promise<RunnerGroup> {
|
||||||
if (this.team === undefined && groupID === undefined) {
|
if (this.team === undefined && groupID === undefined) {
|
||||||
throw new RunnerGroupNeededError();
|
throw new RunnerGroupNeededError();
|
||||||
|
@ -7,11 +7,23 @@ import { JwtCreator } from "../../jwtcreator";
|
|||||||
import { User } from '../entities/User';
|
import { User } from '../entities/User';
|
||||||
import { Auth } from '../responses/ResponseAuth';
|
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 {
|
export class RefreshAuth {
|
||||||
|
/**
|
||||||
|
* A stringyfied jwt refresh token.
|
||||||
|
* Will get checked for validity.
|
||||||
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
token?: string;
|
token?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new auth object based on this.
|
||||||
|
*/
|
||||||
public async toAuth(): Promise<Auth> {
|
public async toAuth(): Promise<Auth> {
|
||||||
let newAuth: Auth = new Auth();
|
let newAuth: Auth = new Auth();
|
||||||
if (!this.token || this.token === undefined) {
|
if (!this.token || this.token === undefined) {
|
||||||
|
@ -7,16 +7,21 @@ import { Principal } from '../entities/Principal';
|
|||||||
import { PermissionAction } from '../enums/PermissionAction';
|
import { PermissionAction } from '../enums/PermissionAction';
|
||||||
import { PermissionTarget } from '../enums/PermissionTargets';
|
import { PermissionTarget } from '../enums/PermissionTargets';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to update a Permission entity (via put request).
|
||||||
|
*/
|
||||||
export class UpdatePermission {
|
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()
|
@IsInt()
|
||||||
id: number;
|
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()
|
@IsObject()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -35,23 +40,21 @@ export class UpdatePermission {
|
|||||||
action: PermissionAction;
|
action: PermissionAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Permission object based on this.
|
* Updates a provided Permission entity based on this.
|
||||||
*/
|
*/
|
||||||
public async toPermission(): Promise<Permission> {
|
public async updatePermission(permission: Permission): Promise<Permission> {
|
||||||
let newPermission: Permission = new Permission();
|
permission.principal = await this.getPrincipal();
|
||||||
|
permission.target = this.target;
|
||||||
|
permission.action = this.action;
|
||||||
|
|
||||||
newPermission.principal = await this.getPrincipal();
|
return permission;
|
||||||
newPermission.target = this.target;
|
|
||||||
newPermission.action = this.action;
|
|
||||||
|
|
||||||
return newPermission;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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<Principal> {
|
public async getPrincipal(): Promise<Principal> {
|
||||||
if (this.principal === undefined) {
|
if (this.principal === undefined || this.principal === null) {
|
||||||
throw new PermissionNeedsPrincipalError();
|
throw new PermissionNeedsPrincipalError();
|
||||||
}
|
}
|
||||||
if (!isNaN(this.principal.id)) {
|
if (!isNaN(this.principal.id)) {
|
||||||
|
@ -7,43 +7,45 @@ import { Runner } from '../entities/Runner';
|
|||||||
import { RunnerGroup } from '../entities/RunnerGroup';
|
import { RunnerGroup } from '../entities/RunnerGroup';
|
||||||
import { CreateParticipant } from './CreateParticipant';
|
import { CreateParticipant } from './CreateParticipant';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to update a Runner entity (via put request).
|
||||||
|
*/
|
||||||
export class UpdateRunner extends CreateParticipant {
|
export class UpdateRunner extends CreateParticipant {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The updated runner's id.
|
* 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()
|
@IsInt()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The updated runner's new team/org.
|
* The updated runner's new team/org.
|
||||||
|
* Just has to contain the group's id -everything else won't be checked or changed.
|
||||||
*/
|
*/
|
||||||
@IsObject()
|
@IsObject()
|
||||||
group: RunnerGroup;
|
group: RunnerGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Runner entity from this.
|
* Updates a provided Runner entity based on this.
|
||||||
*/
|
*/
|
||||||
public async toRunner(): Promise<Runner> {
|
public async updateRunner(runner: Runner): Promise<Runner> {
|
||||||
let newRunner: Runner = new Runner();
|
runner.firstname = this.firstname;
|
||||||
|
runner.middlename = this.middlename;
|
||||||
|
runner.lastname = this.lastname;
|
||||||
|
runner.phone = this.phone;
|
||||||
|
runner.email = this.email;
|
||||||
|
runner.group = await this.getGroup();
|
||||||
|
runner.address = await this.getAddress();
|
||||||
|
|
||||||
newRunner.id = this.id;
|
return runner;
|
||||||
newRunner.firstname = this.firstname;
|
|
||||||
newRunner.middlename = this.middlename;
|
|
||||||
newRunner.lastname = this.lastname;
|
|
||||||
newRunner.phone = this.phone;
|
|
||||||
newRunner.email = this.email;
|
|
||||||
newRunner.group = await this.getGroup();
|
|
||||||
newRunner.address = await this.getAddress();
|
|
||||||
|
|
||||||
return newRunner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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<RunnerGroup> {
|
public async getGroup(): Promise<RunnerGroup> {
|
||||||
if (this.group === undefined) {
|
if (this.group === undefined || this.group === null) {
|
||||||
throw new RunnerTeamNeedsParentError();
|
throw new RunnerTeamNeedsParentError();
|
||||||
}
|
}
|
||||||
if (!isNaN(this.group.id)) {
|
if (!isNaN(this.group.id)) {
|
||||||
|
52
src/models/actions/UpdateRunnerOrganisation.ts
Normal file
52
src/models/actions/UpdateRunnerOrganisation.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { IsInt, IsOptional } from 'class-validator';
|
||||||
|
import { getConnectionManager } from 'typeorm';
|
||||||
|
import { AddressNotFoundError } from '../../errors/AddressErrors';
|
||||||
|
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.
|
||||||
|
* Just has to contain the address's id - everything else won't be checked or changed.
|
||||||
|
* Optional.
|
||||||
|
*/
|
||||||
|
@IsInt()
|
||||||
|
@IsOptional()
|
||||||
|
address?: Address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the organisation's address based on it's id.
|
||||||
|
*/
|
||||||
|
public async getAddress(): Promise<Address> {
|
||||||
|
if (this.address === undefined || this.address === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address.id });
|
||||||
|
if (!address) { throw new AddressNotFoundError; }
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a provided RunnerOrganisation entity based on this.
|
||||||
|
*/
|
||||||
|
public async updateRunnerOrganisation(organisation: RunnerOrganisation): Promise<RunnerOrganisation> {
|
||||||
|
|
||||||
|
organisation.name = this.name;
|
||||||
|
organisation.contact = await this.getContact();
|
||||||
|
organisation.address = await this.getAddress();
|
||||||
|
|
||||||
|
return organisation;
|
||||||
|
}
|
||||||
|
}
|
@ -6,23 +6,31 @@ import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
|||||||
import { RunnerTeam } from '../entities/RunnerTeam';
|
import { RunnerTeam } from '../entities/RunnerTeam';
|
||||||
import { CreateRunnerGroup } from './CreateRunnerGroup';
|
import { CreateRunnerGroup } from './CreateRunnerGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to update a RunnerTeam entity (via put request).
|
||||||
|
*/
|
||||||
export class UpdateRunnerTeam extends CreateRunnerGroup {
|
export class UpdateRunnerTeam extends CreateRunnerGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The updated team's id.
|
* 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()
|
@IsInt()
|
||||||
id: number;
|
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()
|
@IsObject()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
parentGroup: RunnerOrganisation;
|
parentGroup: RunnerOrganisation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the updated teams's parentGroup based on it's id.
|
||||||
|
*/
|
||||||
public async getParent(): Promise<RunnerOrganisation> {
|
public async getParent(): Promise<RunnerOrganisation> {
|
||||||
if (this.parentGroup === undefined) {
|
if (this.parentGroup === undefined || this.parentGroup === null) {
|
||||||
throw new RunnerTeamNeedsParentError();
|
throw new RunnerTeamNeedsParentError();
|
||||||
}
|
}
|
||||||
if (!isNaN(this.parentGroup.id)) {
|
if (!isNaN(this.parentGroup.id)) {
|
||||||
@ -35,16 +43,14 @@ export class UpdateRunnerTeam extends CreateRunnerGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a RunnerTeam entity from this.
|
* Updates a provided RunnerTeam entity based on this.
|
||||||
*/
|
*/
|
||||||
public async toRunnerTeam(): Promise<RunnerTeam> {
|
public async updateRunnerTeam(team: RunnerTeam): Promise<RunnerTeam> {
|
||||||
let newRunnerTeam: RunnerTeam = new RunnerTeam();
|
|
||||||
|
|
||||||
newRunnerTeam.id = this.id;
|
team.name = this.name;
|
||||||
newRunnerTeam.name = this.name;
|
team.parentGroup = await this.getParent();
|
||||||
newRunnerTeam.parentGroup = await this.getParent();
|
team.contact = await this.getContact()
|
||||||
newRunnerTeam.contact = await this.getContact()
|
|
||||||
|
|
||||||
return newRunnerTeam;
|
return team;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,14 +3,18 @@ import { IsBoolean, IsEmail, IsInt, IsOptional, IsPhoneNumber, IsString } from '
|
|||||||
import { getConnectionManager } from 'typeorm';
|
import { getConnectionManager } from 'typeorm';
|
||||||
import { config } from '../../config';
|
import { config } from '../../config';
|
||||||
import { UsernameOrEmailNeededError } from '../../errors/AuthError';
|
import { UsernameOrEmailNeededError } from '../../errors/AuthError';
|
||||||
import { RunnerGroupNotFoundError } from '../../errors/RunnerGroupErrors';
|
import { UserGroupNotFoundError } from '../../errors/UserGroupErrors';
|
||||||
import { User } from '../entities/User';
|
import { User } from '../entities/User';
|
||||||
import { UserGroup } from '../entities/UserGroup';
|
import { UserGroup } from '../entities/UserGroup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to update a User entity (via put request).
|
||||||
|
*/
|
||||||
export class UpdateUser {
|
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()
|
@IsInt()
|
||||||
id: number;
|
id: number;
|
||||||
@ -23,7 +27,6 @@ export class UpdateUser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The updated user's middle name.
|
* The updated user's middle name.
|
||||||
* Optinal.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -54,14 +57,16 @@ export class UpdateUser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The updated user's phone number.
|
* 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)
|
@IsPhoneNumber(config.phone_validation_countrycode)
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
phone?: string;
|
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 :)
|
* This will of course not be saved in plaintext :)
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -75,20 +80,19 @@ export class UpdateUser {
|
|||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The new user's groups' id(s).
|
* The updated user's groups.
|
||||||
* You can provide either one groupId or an array of groupIDs.
|
* This just has to contain the group's id - everything else won't be changed.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
groups?: UserGroup[]
|
groups?: UserGroup[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a User entity from this.
|
* Updates a provided User entity based on this.
|
||||||
*/
|
*/
|
||||||
public async toUser(user: User): Promise<User> {
|
public async updateUser(user: User): Promise<User> {
|
||||||
user.email = this.email;
|
user.email = this.email;
|
||||||
user.username = this.username;
|
user.username = this.username;
|
||||||
if (user.email === undefined && user.username === undefined) {
|
if ((user.email === undefined || user.email === null) && (user.username === undefined || user.username === null)) {
|
||||||
throw new UsernameOrEmailNeededError();
|
throw new UsernameOrEmailNeededError();
|
||||||
}
|
}
|
||||||
if (this.password) {
|
if (this.password) {
|
||||||
@ -107,6 +111,9 @@ export class UpdateUser {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the updated user's groups based on their ids.
|
||||||
|
*/
|
||||||
public async getGroups() {
|
public async getGroups() {
|
||||||
if (!this.groups) { return null; }
|
if (!this.groups) { return null; }
|
||||||
let groups = new Array<UserGroup>();
|
let groups = new Array<UserGroup>();
|
||||||
@ -115,7 +122,7 @@ export class UpdateUser {
|
|||||||
}
|
}
|
||||||
for (let group of this.groups) {
|
for (let group of this.groups) {
|
||||||
let found = await getConnectionManager().get().getRepository(UserGroup).findOne({ id: group.id });
|
let found = await getConnectionManager().get().getRepository(UserGroup).findOne({ id: group.id });
|
||||||
if (!found) { throw new RunnerGroupNotFoundError(); }
|
if (!found) { throw new UserGroupNotFoundError(); }
|
||||||
groups.push(found);
|
groups.push(found);
|
||||||
}
|
}
|
||||||
return groups;
|
return groups;
|
||||||
|
@ -10,7 +10,8 @@ import { Participant } from "./Participant";
|
|||||||
import { RunnerOrganisation } from "./RunnerOrganisation";
|
import { RunnerOrganisation } from "./RunnerOrganisation";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a address (to be used for contact information).
|
* Defines the Address entity.
|
||||||
|
* Implemented this way to prevent any formatting differences.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Address {
|
export class Address {
|
||||||
@ -23,6 +24,7 @@ export class Address {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's description.
|
* The address's description.
|
||||||
|
* Optional and mostly for UX.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -49,6 +51,8 @@ export class Address {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The address's postal code.
|
* The address's postal code.
|
||||||
|
* This will get checked against the postal code syntax for the configured country.
|
||||||
|
* TODO: Implement the config option.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -4,19 +4,21 @@ import { Donation } from "./Donation";
|
|||||||
import { Runner } from "./Runner";
|
import { Runner } from "./Runner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a distance based donation.
|
* Defines the DistanceDonation entity.
|
||||||
* Here people donate a certain amout per kilometer
|
* For distanceDonations a donor pledges to donate a certain amount for each kilometer ran by a runner.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class DistanceDonation extends Donation {
|
export class DistanceDonation extends Donation {
|
||||||
/**
|
/**
|
||||||
* The runner associated.
|
* The donation's associated runner.
|
||||||
|
* Used as the source of the donation's distance.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => Runner, runner => runner.distanceDonations)
|
@ManyToOne(() => Runner, runner => runner.distanceDonations)
|
||||||
runner: Runner;
|
runner: Runner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The donation's amount donated per distance.
|
||||||
* The amount the donor set to be donated per kilometer that the runner ran.
|
* The amount the donor set to be donated per kilometer that the runner ran.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@ -26,12 +28,12 @@ export class DistanceDonation extends Donation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The donation's amount in cents (or whatever your currency's smallest unit is.).
|
* The donation's amount in cents (or whatever your currency's smallest unit is.).
|
||||||
* The exact implementation may differ for each type of donation.
|
* Get's calculated from the runner's distance ran and the amount donated per kilometer.
|
||||||
*/
|
*/
|
||||||
public get amount(): number {
|
public get amount(): number {
|
||||||
let calculatedAmount = -1;
|
let calculatedAmount = -1;
|
||||||
try {
|
try {
|
||||||
calculatedAmount = this.amountPerDistance * this.runner.distance;
|
calculatedAmount = this.amountPerDistance * (this.runner.distance / 1000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,9 @@ import { Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typ
|
|||||||
import { Participant } from "./Participant";
|
import { Participant } from "./Participant";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the donation interface.
|
* Defines the Donation entity.
|
||||||
|
* A donation just associates a donor with a donation amount.
|
||||||
|
* The specifics of the amoun's determination has to be implemented in child classes.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||||
|
@ -3,13 +3,13 @@ import { ChildEntity, Column } from "typeorm";
|
|||||||
import { Participant } from "./Participant";
|
import { Participant } from "./Participant";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a donor.
|
* Defines the Donor entity.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class Donor extends Participant {
|
export class Donor extends Participant {
|
||||||
/**
|
/**
|
||||||
* Does this donor need a receipt?.
|
* Does this donor need a receipt?
|
||||||
* Default: false
|
* Will later be used to automaticly generate donation receipts.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
|
@ -3,7 +3,8 @@ import { ChildEntity, Column } from "typeorm";
|
|||||||
import { Donation } from "./Donation";
|
import { Donation } from "./Donation";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a fixed donation.
|
* Defines the FixedDonation entity.
|
||||||
|
* In the past there was no easy way to track fixed donations (eg. for creating donation receipts).
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class FixedDonation extends Donation {
|
export class FixedDonation extends Donation {
|
||||||
|
@ -13,13 +13,14 @@ import { Address } from "./Address";
|
|||||||
import { RunnerGroup } from "./RunnerGroup";
|
import { RunnerGroup } from "./RunnerGroup";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a group's contact.
|
* Defines the GroupContact entity.
|
||||||
|
* Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class GroupContact {
|
export class GroupContact {
|
||||||
/**
|
/**
|
||||||
* Autogenerated unique id (primary key).
|
* Autogenerated unique id (primary key).
|
||||||
*/
|
*/
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
@IsInt()
|
@IsInt()
|
||||||
id: number;
|
id: number;
|
||||||
@ -34,7 +35,6 @@ export class GroupContact {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's middle name.
|
* The contact's middle name.
|
||||||
* Optional
|
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -51,7 +51,7 @@ export class GroupContact {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's address.
|
* The contact's address.
|
||||||
* Optional
|
* This is a address object to prevent any formatting differences.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ManyToOne(() => Address, address => address.participants, { nullable: true })
|
@ManyToOne(() => Address, address => address.participants, { nullable: true })
|
||||||
@ -59,7 +59,7 @@ export class GroupContact {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's phone number.
|
* The contact's phone number.
|
||||||
* Optional
|
* This will be validated against the configured country phone numer syntax (default: international).
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -68,7 +68,7 @@ export class GroupContact {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The contact's email address.
|
* The contact's email address.
|
||||||
* Optional
|
* Could later be used to automaticly send mails concerning the contact's associated groups.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
@ -13,7 +13,8 @@ import { Address } from "./Address";
|
|||||||
import { Donation } from "./Donation";
|
import { Donation } from "./Donation";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the participant interface.
|
* Defines the Participant entity.
|
||||||
|
* Participans can donate and therefor be associated with donation entities.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||||
@ -35,7 +36,6 @@ export abstract class Participant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's middle name.
|
* The participant's middle name.
|
||||||
* Optional
|
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -52,14 +52,14 @@ export abstract class Participant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's address.
|
* The participant's address.
|
||||||
* Optional
|
* This is a address object to prevent any formatting differences.
|
||||||
*/
|
*/
|
||||||
@ManyToOne(() => Address, address => address.participants, { nullable: true })
|
@ManyToOne(() => Address, address => address.participants, { nullable: true })
|
||||||
address?: Address;
|
address?: Address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's phone number.
|
* The participant's phone number.
|
||||||
* Optional
|
* This will be validated against the configured country phone numer syntax (default: international).
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -68,7 +68,7 @@ export abstract class Participant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's email address.
|
* The participant's email address.
|
||||||
* Optional
|
* Can be used to contact the participant.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -77,6 +77,7 @@ export abstract class Participant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link the participant as the donor of a donation.
|
* Used to link the participant as the donor of a donation.
|
||||||
|
* Attention: Only runner's can be associated as a distanceDonations distance source.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => Donation, donation => donation.donor, { nullable: true })
|
@OneToMany(() => Donation, donation => donation.donor, { nullable: true })
|
||||||
donations: Donation[];
|
donations: Donation[];
|
||||||
|
@ -8,7 +8,9 @@ import { PermissionAction } from '../enums/PermissionAction';
|
|||||||
import { PermissionTarget } from '../enums/PermissionTargets';
|
import { PermissionTarget } from '../enums/PermissionTargets';
|
||||||
import { Principal } from './Principal';
|
import { Principal } from './Principal';
|
||||||
/**
|
/**
|
||||||
* Defines the Permission interface.
|
* Defines the Permission entity.
|
||||||
|
* Permissions can be granted to principals.
|
||||||
|
* The permissions possible targets and actions are defined in enums.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Permission {
|
export class Permission {
|
||||||
@ -20,13 +22,14 @@ export class Permission {
|
|||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The permissions principal
|
* The permission's principal.
|
||||||
*/
|
*/
|
||||||
@ManyToOne(() => Principal, principal => principal.permissions)
|
@ManyToOne(() => Principal, principal => principal.permissions)
|
||||||
principal: Principal;
|
principal: Principal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The target
|
* The permission's target.
|
||||||
|
* This get's stored as the enum value's string representation for compatability reasons.
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'varchar' })
|
@Column({ type: 'varchar' })
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -34,14 +37,16 @@ export class Permission {
|
|||||||
target: PermissionTarget;
|
target: PermissionTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action type
|
* The permission's action.
|
||||||
|
* This get's stored as the enum value's string representation for compatability reasons.
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'varchar' })
|
@Column({ type: 'varchar' })
|
||||||
@IsEnum(PermissionAction)
|
@IsEnum(PermissionAction)
|
||||||
action: PermissionAction;
|
action: PermissionAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn this into a string for exporting (and jwts).
|
* Turn this into a string for exporting and jwts.
|
||||||
|
* Mainly used to shrink the size of jwts (otherwise the would contain entire objects).
|
||||||
*/
|
*/
|
||||||
public toString(): string {
|
public toString(): string {
|
||||||
return this.target + ":" + this.action;
|
return this.target + ":" + this.action;
|
||||||
|
@ -4,23 +4,27 @@ import { ResponsePrincipal } from '../responses/ResponsePrincipal';
|
|||||||
import { Permission } from './Permission';
|
import { Permission } from './Permission';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a admin user.
|
* Defines the principal entity.
|
||||||
|
* A principal basicly is any entity that can receive permissions for the api (users and their groups).
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||||
export abstract class Principal {
|
export abstract class Principal {
|
||||||
/**
|
/**
|
||||||
* autogenerated unique id (primary key).
|
* Autogenerated unique id (primary key).
|
||||||
*/
|
*/
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
@IsInt()
|
@IsInt()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* permissions
|
* The participant's permissions.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => Permission, permission => permission.principal, { nullable: true })
|
@OneToMany(() => Permission, permission => permission.principal, { nullable: true })
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns this entity into it's response class.
|
||||||
|
*/
|
||||||
public abstract toResponse(): ResponsePrincipal;
|
public abstract toResponse(): ResponsePrincipal;
|
||||||
}
|
}
|
@ -7,44 +7,52 @@ import { RunnerGroup } from "./RunnerGroup";
|
|||||||
import { Scan } from "./Scan";
|
import { Scan } from "./Scan";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a runner.
|
* Defines the runner entity.
|
||||||
|
* Runners differ from participants in being able to actually accumulate a ran distance through scans.
|
||||||
|
* Runner's get organized in groups.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class Runner extends Participant {
|
export class Runner extends Participant {
|
||||||
/**
|
/**
|
||||||
* The runner's associated group.
|
* The runner's associated group.
|
||||||
|
* Can be a runner team or organisation.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => RunnerGroup, group => group.runners, { nullable: false })
|
@ManyToOne(() => RunnerGroup, group => group.runners, { nullable: false })
|
||||||
group: RunnerGroup;
|
group: RunnerGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link runners to donations.
|
* The runner's associated distanceDonations.
|
||||||
|
* Used to link runners to distanceDonations in order to calculate the donation's amount based on the distance the runner ran.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => DistanceDonation, distanceDonation => distanceDonation.runner, { nullable: true })
|
@OneToMany(() => DistanceDonation, distanceDonation => distanceDonation.runner, { nullable: true })
|
||||||
distanceDonations: DistanceDonation[];
|
distanceDonations: DistanceDonation[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link runners to cards.
|
* The runner's associated cards.
|
||||||
|
* Used to link runners to cards - yes a runner be associated with multiple cards this came in handy in the past.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => RunnerCard, card => card.runner, { nullable: true })
|
@OneToMany(() => RunnerCard, card => card.runner, { nullable: true })
|
||||||
cards: RunnerCard[];
|
cards: RunnerCard[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link runners to a scans
|
* The runner's associated scans.
|
||||||
|
* Used to link runners to scans (valid and fraudulant).
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => Scan, scan => scan.runner, { nullable: true })
|
@OneToMany(() => Scan, scan => scan.runner, { nullable: true })
|
||||||
scans: Scan[];
|
scans: Scan[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all valid scans associated with this runner.
|
* Returns all valid scans associated with this runner.
|
||||||
|
* This is implemented here to avoid duplicate code in other files.
|
||||||
*/
|
*/
|
||||||
public get validScans(): Scan[] {
|
public get validScans(): Scan[] {
|
||||||
return this.scans.filter(scan => { scan.valid === true });
|
return this.scans.filter(scan => { scan.valid === true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total distance ran by this runner.
|
* Returns the total distance ran by this runner based on all his valid scans.
|
||||||
|
* This is implemented here to avoid duplicate code in other files.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
public get distance(): number {
|
public get distance(): number {
|
||||||
|
@ -11,7 +11,9 @@ import { Runner } from "./Runner";
|
|||||||
import { TrackScan } from "./TrackScan";
|
import { TrackScan } from "./TrackScan";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a card that can be scanned via a scanner station.
|
* Defines the RunnerCard entity.
|
||||||
|
* A runnerCard is a physical representation for a runner.
|
||||||
|
* It can be associated with a runner to create scans via the scan station's.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class RunnerCard {
|
export class RunnerCard {
|
||||||
@ -23,7 +25,8 @@ export class RunnerCard {
|
|||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The runner that is currently associated with this card.
|
* The card's currently associated runner.
|
||||||
|
* To increase reusability a card can be reassigned.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ManyToOne(() => Runner, runner => runner.cards, { nullable: true })
|
@ManyToOne(() => Runner, runner => runner.cards, { nullable: true })
|
||||||
@ -32,7 +35,7 @@ export class RunnerCard {
|
|||||||
/**
|
/**
|
||||||
* The card's code.
|
* The card's code.
|
||||||
* This has to be able to being converted to something barcode compatible.
|
* This has to be able to being converted to something barcode compatible.
|
||||||
* could theoretically be autogenerated
|
* Will get automaticlly generated (not implemented yet).
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsEAN()
|
@IsEAN()
|
||||||
@ -49,7 +52,8 @@ export class RunnerCard {
|
|||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link cards to a track scans.
|
* The card's associated scans.
|
||||||
|
* Used to link cards to track scans.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => TrackScan, scan => scan.track, { nullable: true })
|
@OneToMany(() => TrackScan, scan => scan.track, { nullable: true })
|
||||||
scans: TrackScan[];
|
scans: TrackScan[];
|
||||||
|
@ -9,7 +9,8 @@ import { GroupContact } from "./GroupContact";
|
|||||||
import { Runner } from "./Runner";
|
import { Runner } from "./Runner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the runnerGroup interface.
|
* Defines the RunnerGroup entity.
|
||||||
|
* This is used to group runners together (as the name suggests).
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||||
@ -31,13 +32,14 @@ export abstract class RunnerGroup {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The group's contact.
|
* The group's contact.
|
||||||
* Optional
|
* This is mostly a feature for the group managers and public relations.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ManyToOne(() => GroupContact, contact => contact.groups, { nullable: true })
|
@ManyToOne(() => GroupContact, contact => contact.groups, { nullable: true })
|
||||||
contact?: GroupContact;
|
contact?: GroupContact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The group's associated runners.
|
||||||
* Used to link runners to a runner group.
|
* Used to link runners to a runner group.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => Runner, runner => runner.group, { nullable: true })
|
@OneToMany(() => Runner, runner => runner.group, { nullable: true })
|
||||||
|
@ -5,22 +5,23 @@ import { RunnerGroup } from "./RunnerGroup";
|
|||||||
import { RunnerTeam } from "./RunnerTeam";
|
import { RunnerTeam } from "./RunnerTeam";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a runner organisation (business or school for example).
|
* Defines the RunnerOrganisation entity.
|
||||||
|
* This usually is a school, club or company.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class RunnerOrganisation extends RunnerGroup {
|
export class RunnerOrganisation extends RunnerGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The organisations's address.
|
* The organisations's address.
|
||||||
* Optional
|
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ManyToOne(() => Address, address => address.groups, { nullable: true })
|
@ManyToOne(() => Address, address => address.groups, { nullable: true })
|
||||||
address?: Address;
|
address?: Address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link teams to runner groups.
|
* The organisation's teams.
|
||||||
*/
|
* Used to link teams to a organisation.
|
||||||
|
*/
|
||||||
@OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true })
|
@OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true })
|
||||||
teams: RunnerTeam[];
|
teams: RunnerTeam[];
|
||||||
}
|
}
|
@ -4,14 +4,15 @@ import { RunnerGroup } from "./RunnerGroup";
|
|||||||
import { RunnerOrganisation } from "./RunnerOrganisation";
|
import { RunnerOrganisation } from "./RunnerOrganisation";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a runner team (class or deparment for example).
|
* Defines the RunnerTeam entity.
|
||||||
|
* This usually is a school class or department in a company.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class RunnerTeam extends RunnerGroup {
|
export class RunnerTeam extends RunnerGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The team's parent group.
|
* The team's parent group.
|
||||||
* Optional
|
* Every team has to be part of a runnerOrganisation - this get's checked on creation and update.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => RunnerOrganisation, org => org.teams, { nullable: true })
|
@ManyToOne(() => RunnerOrganisation, org => org.teams, { nullable: true })
|
||||||
|
@ -9,7 +9,8 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } f
|
|||||||
import { Runner } from "./Runner";
|
import { Runner } from "./Runner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the scan interface.
|
* Defines the Scan entity.
|
||||||
|
* A scan basicly adds a certain distance to a runner's total ran distance.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||||
@ -22,7 +23,8 @@ export abstract class Scan {
|
|||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated runner.
|
* The scan's associated runner.
|
||||||
|
* This is important to link ran distances to runners.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => Runner, runner => runner.scans, { nullable: false })
|
@ManyToOne(() => Runner, runner => runner.scans, { nullable: false })
|
||||||
@ -30,15 +32,17 @@ export abstract class Scan {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The scan's distance in meters.
|
* The scan's distance in meters.
|
||||||
|
* Can be set manually or derived from another object.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
abstract distance: number;
|
abstract distance: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the scan valid (for fraud reasons).
|
* Is the scan valid (for fraud reasons).
|
||||||
* Default: true
|
* The determination of validity will work differently for every child class.
|
||||||
*/
|
* Default: true
|
||||||
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
valid: boolean = true;
|
valid: boolean = true;
|
||||||
|
@ -10,7 +10,8 @@ import { Track } from "./Track";
|
|||||||
import { TrackScan } from "./TrackScan";
|
import { TrackScan } from "./TrackScan";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ScannerStations have the ability to create scans for specific tracks.
|
* Defines the ScanStation entity.
|
||||||
|
* ScanStations get used to create TrackScans for runners based on a scan of their runnerCard.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ScanStation {
|
export class ScanStation {
|
||||||
@ -23,6 +24,7 @@ export class ScanStation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The station's description.
|
* The station's description.
|
||||||
|
* Mostly for better UX when traceing back stuff.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -31,6 +33,7 @@ export class ScanStation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The track this station is associated with.
|
* The track this station is associated with.
|
||||||
|
* All scans created by this station will also be associated with this track.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => Track, track => track.stations, { nullable: false })
|
@ManyToOne(() => Track, track => track.stations, { nullable: false })
|
||||||
@ -38,6 +41,7 @@ export class ScanStation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The station's api key.
|
* The station's api key.
|
||||||
|
* This is used to authorize a station against the api (not implemented yet).
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -45,7 +49,7 @@ export class ScanStation {
|
|||||||
key: string;
|
key: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the station enabled (for fraud reasons)?
|
* Is the station enabled (for fraud and setup reasons)?
|
||||||
* Default: true
|
* Default: true
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
IsInt,
|
IsInt,
|
||||||
IsNotEmpty,
|
IsNotEmpty,
|
||||||
|
|
||||||
IsPositive,
|
IsPositive,
|
||||||
IsString
|
IsString
|
||||||
} from "class-validator";
|
} from "class-validator";
|
||||||
@ -10,7 +9,7 @@ import { ScanStation } from "./ScanStation";
|
|||||||
import { TrackScan } from "./TrackScan";
|
import { TrackScan } from "./TrackScan";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a track of given length.
|
* Defines the Track entity.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Track {
|
export class Track {
|
||||||
@ -23,6 +22,7 @@ export class Track {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The track's name.
|
* The track's name.
|
||||||
|
* Mainly here for UX.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -31,6 +31,7 @@ export class Track {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The track's length/distance in meters.
|
* The track's length/distance in meters.
|
||||||
|
* Will be used to calculate runner's ran distances.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@ -38,13 +39,15 @@ export class Track {
|
|||||||
distance: number;
|
distance: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link scan stations to track.
|
* Used to link scan stations to a certain track.
|
||||||
|
* This makes the configuration of the scan stations easier.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => ScanStation, station => station.track, { nullable: true })
|
@OneToMany(() => ScanStation, station => station.track, { nullable: true })
|
||||||
stations: ScanStation[];
|
stations: ScanStation[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to link track scans to a track.
|
* Used to link track scans to a track.
|
||||||
|
* The scan will derive it's distance from the track's distance.
|
||||||
*/
|
*/
|
||||||
@OneToMany(() => TrackScan, scan => scan.track, { nullable: true })
|
@OneToMany(() => TrackScan, scan => scan.track, { nullable: true })
|
||||||
scans: TrackScan[];
|
scans: TrackScan[];
|
||||||
|
@ -12,26 +12,30 @@ import { ScanStation } from "./ScanStation";
|
|||||||
import { Track } from "./Track";
|
import { Track } from "./Track";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the scan interface.
|
* Defines the TrackScan entity.
|
||||||
|
* A track scan usaually get's generated by a scan station.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class TrackScan extends Scan {
|
export class TrackScan extends Scan {
|
||||||
/**
|
/**
|
||||||
* The associated track.
|
* The scan's associated track.
|
||||||
|
* This is used to determine the scan's distance.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => Track, track => track.scans, { nullable: true })
|
@ManyToOne(() => Track, track => track.scans, { nullable: true })
|
||||||
track: Track;
|
track: Track;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated card.
|
* The runnerCard associated with the scan.
|
||||||
|
* This get's saved for documentation and management purposes.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => RunnerCard, card => card.scans, { nullable: true })
|
@ManyToOne(() => RunnerCard, card => card.scans, { nullable: true })
|
||||||
card: RunnerCard;
|
card: RunnerCard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scanning station.
|
* The scanning station that created the scan.
|
||||||
|
* Mainly used for logging and traceing back scans (or errors)
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ManyToOne(() => ScanStation, station => station.scans, { nullable: true })
|
@ManyToOne(() => ScanStation, station => station.scans, { nullable: true })
|
||||||
@ -39,6 +43,7 @@ export class TrackScan extends Scan {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The scan's distance in meters.
|
* The scan's distance in meters.
|
||||||
|
* This just get's loaded from it's track.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
@ -48,6 +53,7 @@ export class TrackScan extends Scan {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The scan's creation timestamp.
|
* The scan's creation timestamp.
|
||||||
|
* Will be used to implement fraud detection.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
|
@ -8,26 +8,29 @@ import { UserAction } from './UserAction';
|
|||||||
import { UserGroup } from './UserGroup';
|
import { UserGroup } from './UserGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a admin user.
|
* Defines the User entity.
|
||||||
|
* Users are the ones that can use the "admin" webui and do stuff in the backend.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class User extends Principal {
|
export class User extends Principal {
|
||||||
/**
|
/**
|
||||||
* uuid
|
* The user's uuid.
|
||||||
|
* Mainly gets used as a per-user salt for the password hash.
|
||||||
*/
|
*/
|
||||||
@Column({ unique: true })
|
@Column({ unique: true })
|
||||||
@IsUUID(4)
|
@IsUUID(4)
|
||||||
uuid: string;
|
uuid: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user email
|
* The user's e-mail address.
|
||||||
|
* Either username or email has to be set (otherwise the user couldn't log in).
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true, unique: true })
|
@Column({ nullable: true, unique: true })
|
||||||
@IsEmail()
|
@IsEmail()
|
||||||
email?: string;
|
email?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user phone
|
* The user's phone number.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -35,14 +38,15 @@ export class User extends Principal {
|
|||||||
phone?: string;
|
phone?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* username
|
* The user's username.
|
||||||
|
* Either username or email has to be set (otherwise the user couldn't log in).
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true, unique: true })
|
@Column({ nullable: true, unique: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
username?: string;
|
username?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* firstname
|
* The user's first name.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -50,7 +54,7 @@ export class User extends Principal {
|
|||||||
firstname: string;
|
firstname: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* middlename
|
* The user's middle name.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -58,7 +62,7 @@ export class User extends Principal {
|
|||||||
middlename?: string;
|
middlename?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lastname
|
* The user's last name.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -66,7 +70,8 @@ export class User extends Principal {
|
|||||||
lastname: string;
|
lastname: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* password
|
* The user's password.
|
||||||
|
* This is a argon2 hash salted with the user's uuid.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -74,7 +79,8 @@ export class User extends Principal {
|
|||||||
password: string;
|
password: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* groups
|
* The groups this user is a part of.
|
||||||
|
* The user will inherit the groups permissions (without overwriting his own).
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ManyToMany(() => UserGroup, { nullable: true })
|
@ManyToMany(() => UserGroup, { nullable: true })
|
||||||
@ -82,21 +88,23 @@ export class User extends Principal {
|
|||||||
groups: UserGroup[];
|
groups: UserGroup[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is user enabled?
|
* Is this user enabled?
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* jwt refresh count
|
* The user's jwt refresh token count.
|
||||||
|
* Used to invalidate jwts.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@Column({ default: 1 })
|
@Column({ default: 1 })
|
||||||
refreshTokenCount?: number;
|
refreshTokenCount?: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* profilepic
|
* 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: true })
|
@Column({ nullable: true, unique: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -104,14 +112,15 @@ export class User extends Principal {
|
|||||||
profilePic?: string;
|
profilePic?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* actions
|
* The actions performed by this user.
|
||||||
|
* For documentation purposes only, will be implemented later.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@OneToMany(() => UserAction, action => action.user, { nullable: true })
|
@OneToMany(() => UserAction, action => action.user, { nullable: true })
|
||||||
actions: UserAction[]
|
actions: UserAction[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn this into a response.
|
* Turns this entity into it's response class.
|
||||||
*/
|
*/
|
||||||
public toResponse(): ResponsePrincipal {
|
public toResponse(): ResponsePrincipal {
|
||||||
return new ResponseUser(this);
|
return new ResponseUser(this);
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
|
IsEnum,
|
||||||
IsInt,
|
IsInt,
|
||||||
IsNotEmpty,
|
IsNotEmpty,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
IsString
|
IsString
|
||||||
} from "class-validator";
|
} from "class-validator";
|
||||||
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import { PermissionAction } from '../enums/PermissionAction';
|
||||||
import { User } from './User';
|
import { User } from './User';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the UserAction interface.
|
* Defines the UserAction entity.
|
||||||
|
* Will later be used to document a user's actions.
|
||||||
*/
|
*/
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserAction {
|
export class UserAction {
|
||||||
@ -20,7 +23,7 @@ export class UserAction {
|
|||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user
|
* The user that performed the action.
|
||||||
*/
|
*/
|
||||||
@ManyToOne(() => User, user => user.actions)
|
@ManyToOne(() => User, user => user.actions)
|
||||||
user: User
|
user: User
|
||||||
@ -34,15 +37,16 @@ export class UserAction {
|
|||||||
target: string;
|
target: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actions's action (e.g. UPDATE)
|
* The actions's action (e.g. UPDATE).
|
||||||
|
* Directly pulled from the PermissionAction Enum.
|
||||||
*/
|
*/
|
||||||
@Column()
|
@Column({ type: 'varchar' })
|
||||||
@IsNotEmpty()
|
@IsEnum(PermissionAction)
|
||||||
@IsString()
|
action: PermissionAction;
|
||||||
action: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The description of change (before-> after; e.g. distance:15->17)
|
* The description of the change (before-> after; e.g. distance:15->17).
|
||||||
|
* Will later be defined in more detail.
|
||||||
*/
|
*/
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
@ -9,7 +9,8 @@ import { ResponseUserGroup } from '../responses/ResponseUserGroup';
|
|||||||
import { Principal } from './Principal';
|
import { Principal } from './Principal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the UserGroup interface.
|
* Defines the UserGroup entity.
|
||||||
|
* This entity describes a group of users with a set of permissions.
|
||||||
*/
|
*/
|
||||||
@ChildEntity()
|
@ChildEntity()
|
||||||
export class UserGroup extends Principal {
|
export class UserGroup extends Principal {
|
||||||
@ -30,6 +31,9 @@ export class UserGroup extends Principal {
|
|||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns this entity into it's response class.
|
||||||
|
*/
|
||||||
public toResponse(): ResponsePrincipal {
|
public toResponse(): ResponsePrincipal {
|
||||||
return new ResponseUserGroup(this);
|
return new ResponseUserGroup(this);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* This enum contains all posible actions for permissions.
|
||||||
|
*/
|
||||||
export enum PermissionAction {
|
export enum PermissionAction {
|
||||||
GET = 'GET',
|
GET = 'GET',
|
||||||
CREATE = 'CREATE',
|
CREATE = 'CREATE',
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* This enum contains all posible targets for permissions.
|
||||||
|
*/
|
||||||
export enum PermissionTarget {
|
export enum PermissionTarget {
|
||||||
RUNNER = 'RUNNER',
|
RUNNER = 'RUNNER',
|
||||||
ORGANISATION = 'ORGANISATION',
|
ORGANISATION = 'ORGANISATION',
|
||||||
TEAM = 'TEAM',
|
TEAM = 'TEAM',
|
||||||
TRACK = 'TRACK',
|
TRACK = 'TRACK',
|
||||||
USER = 'USER',
|
USER = 'USER',
|
||||||
GROUP = 'USERGROUP',
|
USERGROUP = 'USERGROUP',
|
||||||
PERMISSION = 'PERMISSION'
|
PERMISSION = 'PERMISSION'
|
||||||
}
|
}
|
@ -1,26 +1,29 @@
|
|||||||
import { IsInt, IsString } from 'class-validator';
|
import { IsInt, IsString } from 'class-validator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a auth object
|
* Defines the repsonse auth.
|
||||||
*/
|
*/
|
||||||
export class Auth {
|
export class Auth {
|
||||||
/**
|
/**
|
||||||
* access_token - JWT shortterm access token
|
* The access_token - JWT shortterm access token.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
access_token: string;
|
access_token: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh_token - longterm refresh token (used for requesting new access tokens)
|
* The refresh_token - longterm refresh token (used for requesting new access tokens).
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
refresh_token: string;
|
refresh_token: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* access_token_expires_at - unix timestamp of access token expiry
|
* The unix timestamp for access the token's expiry.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
access_token_expires_at: number;
|
access_token_expires_at: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh_token_expires_at - unix timestamp of access token expiry
|
* The unix unix timestamp for the access token's expiry.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
refresh_token_expires_at: number;
|
refresh_token_expires_at: number;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { IsString } from 'class-validator';
|
import { IsString } from 'class-validator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a empty response object
|
* Defines a empty response object.
|
||||||
*/
|
*/
|
||||||
export class ResponseEmpty {
|
export class ResponseEmpty {
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { IsString } from 'class-validator';
|
import { IsString } from 'class-validator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a Logout object
|
* Defines the logout response.
|
||||||
*/
|
*/
|
||||||
export class Logout {
|
export class Logout {
|
||||||
/**
|
/**
|
||||||
* timestamp of logout
|
* The logout's timestamp.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
import {
|
import { IsInt, IsString } from "class-validator";
|
||||||
IsInt,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IsString
|
|
||||||
} from "class-validator";
|
|
||||||
import { Participant } from '../entities/Participant';
|
import { Participant } from '../entities/Participant';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a participant response.
|
* Defines the participant response.
|
||||||
*/
|
*/
|
||||||
export abstract class ResponseParticipant {
|
export abstract class ResponseParticipant {
|
||||||
/**
|
/**
|
||||||
* Autogenerated unique id (primary key).
|
* The participant's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
id: number;
|
id: number;
|
||||||
@ -25,7 +19,6 @@ export abstract class ResponseParticipant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's middle name.
|
* The participant's middle name.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
middlename?: string;
|
middlename?: string;
|
||||||
@ -38,18 +31,20 @@ export abstract class ResponseParticipant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's phone number.
|
* The participant's phone number.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
phone?: string;
|
phone?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant's e-mail address.
|
* The participant's e-mail address.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
email?: string;
|
email?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseParticipant object from a participant.
|
||||||
|
* @param participant The participant the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(participant: Participant) {
|
public constructor(participant: Participant) {
|
||||||
this.id = participant.id;
|
this.id = participant.id;
|
||||||
this.firstname = participant.firstname;
|
this.firstname = participant.firstname;
|
||||||
|
@ -10,11 +10,11 @@ import { PermissionTarget } from '../enums/PermissionTargets';
|
|||||||
import { ResponsePrincipal } from './ResponsePrincipal';
|
import { ResponsePrincipal } from './ResponsePrincipal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a track of given length.
|
* Defines the permission response.
|
||||||
*/
|
*/
|
||||||
export class ResponsePermission {
|
export class ResponsePermission {
|
||||||
/**
|
/**
|
||||||
* Autogenerated unique id (primary key).
|
* The permission's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
id: number;;
|
id: number;;
|
||||||
@ -40,6 +40,10 @@ export class ResponsePermission {
|
|||||||
@IsEnum(PermissionAction)
|
@IsEnum(PermissionAction)
|
||||||
action: PermissionAction;
|
action: PermissionAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponsePermission object from a permission.
|
||||||
|
* @param permission The permission the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(permission: Permission) {
|
public constructor(permission: Permission) {
|
||||||
this.id = permission.id;
|
this.id = permission.id;
|
||||||
this.principal = permission.principal.toResponse();
|
this.principal = permission.principal.toResponse();
|
||||||
|
@ -4,16 +4,20 @@ import {
|
|||||||
import { Principal } from '../entities/Principal';
|
import { Principal } from '../entities/Principal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines Principal's response class.
|
* Defines the principal response.
|
||||||
*/
|
*/
|
||||||
export abstract class ResponsePrincipal {
|
export abstract class ResponsePrincipal {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Autogenerated unique id (primary key).
|
* The principal's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponsePrincipal object from a principal.
|
||||||
|
* @param principal The principal the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(principal: Principal) {
|
public constructor(principal: Principal) {
|
||||||
this.id = principal.id;
|
this.id = principal.id;
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,12 @@ import { RunnerGroup } from '../entities/RunnerGroup';
|
|||||||
import { ResponseParticipant } from './ResponseParticipant';
|
import { ResponseParticipant } from './ResponseParticipant';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines RunnerTeam's response class.
|
* Defines the runner response.
|
||||||
*/
|
*/
|
||||||
export class ResponseRunner extends ResponseParticipant {
|
export class ResponseRunner extends ResponseParticipant {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The runner's currently ran distance in meters.
|
* The runner's currently ran distance in meters.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
distance: number;
|
distance: number;
|
||||||
@ -24,6 +23,10 @@ export class ResponseRunner extends ResponseParticipant {
|
|||||||
@IsObject()
|
@IsObject()
|
||||||
group: RunnerGroup;
|
group: RunnerGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseRunner object from a runner.
|
||||||
|
* @param runner The user the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(runner: Runner) {
|
public constructor(runner: Runner) {
|
||||||
super(runner);
|
super(runner);
|
||||||
this.distance = runner.scans.filter(scan => { scan.valid === true }).reduce((sum, current) => sum + current.distance, 0);
|
this.distance = runner.scans.filter(scan => { scan.valid === true }).reduce((sum, current) => sum + current.distance, 0);
|
||||||
|
@ -1,38 +1,20 @@
|
|||||||
import {
|
import { IsInt, IsNotEmpty, IsObject, IsOptional, IsString } from "class-validator";
|
||||||
IsInt,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IsNotEmpty,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IsObject,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IsOptional,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IsString
|
|
||||||
} from "class-validator";
|
|
||||||
import { GroupContact } from '../entities/GroupContact';
|
import { GroupContact } from '../entities/GroupContact';
|
||||||
import { RunnerGroup } from '../entities/RunnerGroup';
|
import { RunnerGroup } from '../entities/RunnerGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a track of given length.
|
* Defines the runnerGroup response.
|
||||||
*/
|
*/
|
||||||
export abstract class ResponseRunnerGroup {
|
export abstract class ResponseRunnerGroup {
|
||||||
/**
|
/**
|
||||||
* Autogenerated unique id (primary key).
|
* The runnerGroup's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
id: number;;
|
id: number;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The groups's name.
|
* The runnerGroup's name.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -40,13 +22,16 @@ export abstract class ResponseRunnerGroup {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The group's contact.
|
* The runnerGroup's contact.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
contact?: GroupContact;
|
contact?: GroupContact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseRunnerGroup object from a runnerGroup.
|
||||||
|
* @param group The runnerGroup the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(group: RunnerGroup) {
|
public constructor(group: RunnerGroup) {
|
||||||
this.id = group.id;
|
this.id = group.id;
|
||||||
this.name = group.name;
|
this.name = group.name;
|
||||||
|
@ -9,25 +9,27 @@ import { RunnerTeam } from '../entities/RunnerTeam';
|
|||||||
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
|
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines RunnerOrgs's response class.
|
* Defines the runnerOrganisation response.
|
||||||
*/
|
*/
|
||||||
export class ResponseRunnerOrganisation extends ResponseRunnerGroup {
|
export class ResponseRunnerOrganisation extends ResponseRunnerGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The orgs's address.
|
* The runnerOrganisation's address.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
address?: Address;
|
address?: Address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The orgs associated teams.
|
* The runnerOrganisation associated teams.
|
||||||
*/
|
*/
|
||||||
@IsArray()
|
@IsArray()
|
||||||
teams: RunnerTeam[];
|
teams: RunnerTeam[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseRunnerOrganisation object from a runnerOrganisation.
|
||||||
|
* @param org The runnerOrganisation the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(org: RunnerOrganisation) {
|
public constructor(org: RunnerOrganisation) {
|
||||||
super(org);
|
super(org);
|
||||||
this.address = org.address;
|
this.address = org.address;
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import {
|
import { IsNotEmpty, IsObject } from "class-validator";
|
||||||
IsNotEmpty,
|
|
||||||
IsObject
|
|
||||||
} from "class-validator";
|
|
||||||
import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
import { RunnerOrganisation } from '../entities/RunnerOrganisation';
|
||||||
import { RunnerTeam } from '../entities/RunnerTeam';
|
import { RunnerTeam } from '../entities/RunnerTeam';
|
||||||
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
|
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines RunnerTeam's response class.
|
* Defines the runnerTeam response.
|
||||||
*/
|
*/
|
||||||
export class ResponseRunnerTeam extends ResponseRunnerGroup {
|
export class ResponseRunnerTeam extends ResponseRunnerGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The team's parent group (organisation).
|
* The runnerTeam's parent group (organisation).
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
parentGroup: RunnerOrganisation;
|
parentGroup: RunnerOrganisation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseRunnerTeam object from a runnerTeam.
|
||||||
|
* @param team The team the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(team: RunnerTeam) {
|
public constructor(team: RunnerTeam) {
|
||||||
super(team);
|
super(team);
|
||||||
this.parentGroup = team.parentGroup;
|
this.parentGroup = team.parentGroup;
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
import {
|
import { IsInt, IsString } from "class-validator";
|
||||||
IsInt,
|
|
||||||
|
|
||||||
IsString
|
|
||||||
} from "class-validator";
|
|
||||||
import { Track } from '../entities/Track';
|
import { Track } from '../entities/Track';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a track of given length.
|
* Defines the track response.
|
||||||
*/
|
*/
|
||||||
export class ResponseTrack {
|
export class ResponseTrack {
|
||||||
/**
|
/**
|
||||||
* Autogenerated unique id (primary key).
|
* The track's id.
|
||||||
*/
|
*/
|
||||||
@IsInt()
|
@IsInt()
|
||||||
id: number;;
|
id: number;;
|
||||||
@ -27,6 +23,10 @@ export class ResponseTrack {
|
|||||||
@IsInt()
|
@IsInt()
|
||||||
distance: number;
|
distance: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseTrack object from a track.
|
||||||
|
* @param track The track the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(track: Track) {
|
public constructor(track: Track) {
|
||||||
this.id = track.id;
|
this.id = track.id;
|
||||||
this.name = track.name;
|
this.name = track.name;
|
||||||
|
@ -11,7 +11,7 @@ import { UserGroup } from '../entities/UserGroup';
|
|||||||
import { ResponsePrincipal } from './ResponsePrincipal';
|
import { ResponsePrincipal } from './ResponsePrincipal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a user response.
|
* Defines the user response.
|
||||||
*/
|
*/
|
||||||
export class ResponseUser extends ResponsePrincipal {
|
export class ResponseUser extends ResponsePrincipal {
|
||||||
/**
|
/**
|
||||||
@ -22,7 +22,6 @@ export class ResponseUser extends ResponsePrincipal {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The user's middle name.
|
* The user's middle name.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
middlename?: string;
|
middlename?: string;
|
||||||
@ -35,45 +34,53 @@ export class ResponseUser extends ResponsePrincipal {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The user's phone number.
|
* The user's phone number.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
phone?: string;
|
phone?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user's e-mail address.
|
* The user's e-mail address.
|
||||||
* Optional.
|
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
email?: string;
|
email?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is user enabled?
|
* The user's username.
|
||||||
|
*/
|
||||||
|
@IsString()
|
||||||
|
username?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is user enabled?
|
||||||
*/
|
*/
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* profilepic
|
* The user's profile pic.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
profilePic?: string;
|
profilePic?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups
|
* The groups that the user is a part of.
|
||||||
*/
|
*/
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
groups: UserGroup[];
|
groups: UserGroup[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* permissions
|
* The user's permissions.
|
||||||
*/
|
*/
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseUser object from a user.
|
||||||
|
* @param user The user the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(user: User) {
|
public constructor(user: User) {
|
||||||
super(user);
|
super(user);
|
||||||
this.firstname = user.firstname;
|
this.firstname = user.firstname;
|
||||||
@ -81,6 +88,7 @@ export class ResponseUser extends ResponsePrincipal {
|
|||||||
this.lastname = user.lastname;
|
this.lastname = user.lastname;
|
||||||
this.phone = user.phone;
|
this.phone = user.phone;
|
||||||
this.email = user.email;
|
this.email = user.email;
|
||||||
|
this.username = user.username;
|
||||||
this.enabled = user.enabled;
|
this.enabled = user.enabled;
|
||||||
this.profilePic = user.profilePic;
|
this.profilePic = user.profilePic;
|
||||||
this.groups = user.groups;
|
this.groups = user.groups;
|
||||||
|
@ -1,41 +1,37 @@
|
|||||||
import {
|
import { IsArray, IsNotEmpty, IsOptional, IsString } from "class-validator";
|
||||||
IsArray,
|
|
||||||
|
|
||||||
|
|
||||||
IsNotEmpty,
|
|
||||||
|
|
||||||
IsOptional,
|
|
||||||
IsString
|
|
||||||
} from "class-validator";
|
|
||||||
import { Permission } from '../entities/Permission';
|
import { Permission } from '../entities/Permission';
|
||||||
import { UserGroup } from '../entities/UserGroup';
|
import { UserGroup } from '../entities/UserGroup';
|
||||||
import { ResponsePrincipal } from './ResponsePrincipal';
|
import { ResponsePrincipal } from './ResponsePrincipal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a user response.
|
* Defines the userGroup response.
|
||||||
*/
|
*/
|
||||||
export class ResponseUserGroup extends ResponsePrincipal {
|
export class ResponseUserGroup extends ResponsePrincipal {
|
||||||
/**
|
/**
|
||||||
* The group's name
|
* The userGroup's name.
|
||||||
*/
|
*/
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The group's description
|
* The userGroup's description.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* permissions
|
* The userGroup's permissions.
|
||||||
*/
|
*/
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ResponseUserGroup object from a userGroup.
|
||||||
|
* @param group The userGroup the response shall be build for.
|
||||||
|
*/
|
||||||
public constructor(group: UserGroup) {
|
public constructor(group: UserGroup) {
|
||||||
super(group);
|
super(group);
|
||||||
this.name = group.name;
|
this.name = group.name;
|
||||||
|
@ -9,6 +9,10 @@ import { UserGroup } from '../models/entities/UserGroup';
|
|||||||
import { PermissionAction } from '../models/enums/PermissionAction';
|
import { PermissionAction } from '../models/enums/PermissionAction';
|
||||||
import { PermissionTarget } from '../models/enums/PermissionTargets';
|
import { PermissionTarget } from '../models/enums/PermissionTargets';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seeds a admin group with a demo user into the database for initial setup and auto recovery.
|
||||||
|
* We know that the nameing isn't perfectly fitting. Feel free to change it.
|
||||||
|
*/
|
||||||
export default class SeedUsers implements Seeder {
|
export default class SeedUsers implements Seeder {
|
||||||
public async run(factory: Factory, connection: Connection): Promise<any> {
|
public async run(factory: Factory, connection: Connection): Promise<any> {
|
||||||
let adminGroup: UserGroup = await this.createAdminGroup(connection);
|
let adminGroup: UserGroup = await this.createAdminGroup(connection);
|
||||||
@ -19,7 +23,7 @@ export default class SeedUsers implements Seeder {
|
|||||||
public async createAdminGroup(connection: Connection) {
|
public async createAdminGroup(connection: Connection) {
|
||||||
let adminGroup = new CreateUserGroup();
|
let adminGroup = new CreateUserGroup();
|
||||||
adminGroup.name = "ADMINS";
|
adminGroup.name = "ADMINS";
|
||||||
adminGroup.description = "Has all possible permissions";
|
adminGroup.description = "Have all possible permissions";
|
||||||
return await connection.getRepository(UserGroup).save(await adminGroup.toUserGroup());
|
return await connection.getRepository(UserGroup).save(await adminGroup.toUserGroup());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user