diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index 98a9f85..cddb677 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -1,4 +1,4 @@ -import { Body, CookieParam, JsonController, Param, Post, Res } from 'routing-controllers'; +import { Body, CookieParam, JsonController, Param, Post, Req, Res } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError'; import { UserNotFoundError } from '../errors/UserErrors'; @@ -22,7 +22,7 @@ export class AuthController { @ResponseSchema(UsernameOrEmailNeededError) @ResponseSchema(PasswordNeededError) @ResponseSchema(InvalidCredentialsError) - @OpenAPI({ description: 'Create a new access token object' }) + @OpenAPI({ description: 'Login with your username/email and password.
You will receive: \n * access token (use it as a bearer token) \n * refresh token (will also be sent as a cookie)' }) async login(@Body({ validate: true }) createAuth: CreateAuth, @Res() response: any) { let auth; try { @@ -42,7 +42,7 @@ export class AuthController { @ResponseSchema(UsernameOrEmailNeededError) @ResponseSchema(PasswordNeededError) @ResponseSchema(InvalidCredentialsError) - @OpenAPI({ description: 'Create a new access token object' }) + @OpenAPI({ description: 'Logout using your refresh token.
This instantly invalidates all your access and refresh tokens.', security: [{ "RefreshTokenCookie": [] }] }) async logout(@Body({ validate: true }) handleLogout: HandleLogout, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any) { if (refresh_token && refresh_token.length != 0 && handleLogout.token == undefined) { handleLogout.token = refresh_token; @@ -65,11 +65,12 @@ export class AuthController { @ResponseSchema(IllegalJWTError) @ResponseSchema(UserNotFoundError) @ResponseSchema(RefreshTokenCountInvalidError) - @OpenAPI({ description: 'refresh a access token' }) - async refresh(@Body({ validate: true }) refreshAuth: RefreshAuth, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any) { + @OpenAPI({ description: 'Refresh your access and refresh tokens using a valid refresh token.
You will receive: \n * access token (use it as a bearer token) \n * refresh token (will also be sent as a cookie)', security: [{ "RefreshTokenCookie": [] }] }) + async refresh(@Body({ validate: true }) refreshAuth: RefreshAuth, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any, @Req() req: any) { if (refresh_token && refresh_token.length != 0 && refreshAuth.token == undefined) { refreshAuth.token = refresh_token; } + console.log(req.headers) let auth; try { auth = await refreshAuth.toAuth(); @@ -85,7 +86,7 @@ export class AuthController { @ResponseSchema(Auth) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) - @OpenAPI({ description: "Request a password reset token" }) + @OpenAPI({ description: "Request a password reset token.
This will provide you with a reset token that you can use by posting to /api/auth/reset/{token}." }) async getResetToken(@Body({ validate: true }) passwordReset: CreateResetToken) { //This really shouldn't just get returned, but sent via mail or sth like that. But for dev only this is fine. return { "resetToken": await passwordReset.toResetToken() }; @@ -95,7 +96,7 @@ export class AuthController { @ResponseSchema(Auth) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) - @OpenAPI({ description: "Reset a user's password" }) + @OpenAPI({ description: "Reset a user's utilising a valid password reset token.
This will set the user's password to the one you provided in the body.
To get a reset token post to /api/auth/reset with your username." }) async resetPassword(@Param("token") token: string, @Body({ validate: true }) passwordReset: ResetPassword) { passwordReset.resetToken = token; return await passwordReset.resetPassword(); diff --git a/src/controllers/ImportController.ts b/src/controllers/ImportController.ts index bccdfb3..3390e46 100644 --- a/src/controllers/ImportController.ts +++ b/src/controllers/ImportController.ts @@ -10,7 +10,7 @@ import { RunnerController } from './RunnerController'; @Controller() @Authorized(["RUNNER:IMPORT", "TEAM:IMPORT"]) -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class ImportController { private runnerController: RunnerController; @@ -26,7 +26,7 @@ export class ImportController { @ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 }) @ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerGroupNeededError, { statusCode: 406 }) - @OpenAPI({ description: "Create new runners from json and insert them (or their teams) into the provided group" }) + @OpenAPI({ description: "Create new runners from json and insert them into the provided group.
If teams/classes are provided alongside the runner's name they'll automaticly be created under the provided org and the runners will be inserted into the teams instead." }) async postJSON(@Body({ validate: true, type: ImportRunner }) importRunners: ImportRunner[], @QueryParam("group") groupID: number) { if (!groupID) { throw new RunnerGroupNeededError(); } let responseRunners: ResponseRunner[] = new Array(); @@ -41,7 +41,7 @@ export class ImportController { @ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 }) @ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerGroupNeededError, { statusCode: 406 }) - @OpenAPI({ description: "Create new runners from json and insert them (or their teams) into the provided org" }) + @OpenAPI({ description: "Create new runners from json and insert them into the provided org.
If teams/classes are provided alongside the runner's name they'll automaticly be created under the provided org and the runners will be inserted into the teams instead." }) async postOrgsJSON(@Body({ validate: true, type: ImportRunner }) importRunners: ImportRunner[], @Param('id') id: number) { return await this.postJSON(importRunners, id) } @@ -62,7 +62,7 @@ export class ImportController { @ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 }) @ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerGroupNeededError, { statusCode: 406 }) - @OpenAPI({ description: "Create new runners from csv and insert them (or their teams) into the provided group" }) + @OpenAPI({ description: "Create new runners from csv and insert them into the provided group.
If teams/classes are provided alongside the runner's name they'll automaticly be created under the provided org and the runners will be inserted into the teams instead." }) async postCSV(@Req() request: any, @QueryParam("group") groupID: number) { let csvParse = await csv({ delimiter: [",", ";"], trim: true }).fromString(request.rawBody.toString()); let importRunners: ImportRunner[] = new Array(); @@ -84,7 +84,7 @@ export class ImportController { @ResponseSchema(ResponseRunner, { isArray: true, statusCode: 200 }) @ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerGroupNeededError, { statusCode: 406 }) - @OpenAPI({ description: "Create new runners from csv and insert them (or their teams) into the provided org" }) + @OpenAPI({ description: "Create new runners from csv and insert them into the provided org.
If teams/classes are provided alongside the runner's name they'll automaticly be created under the provided org and the runners will be inserted into the teams instead." }) async postOrgsCSV(@Req() request: any, @Param("id") id: number) { return await this.postCSV(request, id); } diff --git a/src/controllers/PermissionController.ts b/src/controllers/PermissionController.ts index 208fe6f..15ad301 100644 --- a/src/controllers/PermissionController.ts +++ b/src/controllers/PermissionController.ts @@ -12,7 +12,7 @@ import { ResponsePrincipal } from '../models/responses/ResponsePrincipal'; @JsonController('/permissions') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class PermissionController { private permissionRepository: Repository; @@ -26,7 +26,7 @@ export class PermissionController { @Get() @Authorized("PERMISSION:GET") @ResponseSchema(ResponsePermission, { isArray: true }) - @OpenAPI({ description: 'Lists all permissions.' }) + @OpenAPI({ description: 'Lists all permissions for all users and groups.' }) async getAll() { let responsePermissions: ResponsePermission[] = new Array(); const permissions = await this.permissionRepository.find({ relations: ['principal'] }); @@ -42,7 +42,7 @@ export class PermissionController { @ResponseSchema(ResponsePermission) @ResponseSchema(PermissionNotFoundError, { statusCode: 404 }) @OnUndefined(PermissionNotFoundError) - @OpenAPI({ description: 'Returns a permissions of a specified id (if it exists)' }) + @OpenAPI({ description: 'Lists all information about the permission whose id got provided.' }) async getOne(@Param('id') id: number) { let permission = await this.permissionRepository.findOne({ id: id }, { relations: ['principal'] }); if (!permission) { throw new PermissionNotFoundError(); } @@ -54,7 +54,7 @@ export class PermissionController { @Authorized("PERMISSION:CREATE") @ResponseSchema(ResponsePermission) @ResponseSchema(PrincipalNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Create a new runnerTeam object (id will be generated automagicly).' }) + @OpenAPI({ description: 'Create a new permission for a existing principal(user/group).
If a permission with this target, action and prinicpal already exists that permission will be returned instead of creating a new one.' }) async post(@Body({ validate: true }) createPermission: CreatePermission) { let permission; try { @@ -79,7 +79,7 @@ export class PermissionController { @ResponseSchema(PrincipalNotFoundError, { statusCode: 404 }) @ResponseSchema(PermissionIdsNotMatchingError, { statusCode: 406 }) @ResponseSchema(PermissionNeedsPrincipalError, { statusCode: 406 }) - @OpenAPI({ description: "Update a permission object (id can't be changed)." }) + @OpenAPI({ description: "Update a permission object.
If updateing the permission object would result in duplicate permission (same target, action and principal) this permission will get deleted and the existing permission will be returned.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) permission: UpdatePermission) { let oldPermission = await this.permissionRepository.findOne({ id: id }, { relations: ['principal'] }); @@ -106,7 +106,7 @@ export class PermissionController { @ResponseSchema(ResponsePermission) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete a specified permission (if it exists).' }) + @OpenAPI({ description: 'Deletes the permission whose id you provide.
If no permission with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let permission = await this.permissionRepository.findOne({ id: id }, { relations: ['principal'] }); if (!permission) { return null; } diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 12569d0..9eeb916 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -10,7 +10,7 @@ import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunner } from '../models/responses/ResponseRunner'; @JsonController('/runners') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class RunnerController { private runnerRepository: Repository; @@ -24,7 +24,7 @@ export class RunnerController { @Get() @Authorized("RUNNER:GET") @ResponseSchema(ResponseRunner, { isArray: true }) - @OpenAPI({ description: 'Lists all runners.' }) + @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) async getAll() { let responseRunners: ResponseRunner[] = new Array(); const runners = await this.runnerRepository.find({ relations: ['scans', 'group'] }); @@ -39,7 +39,7 @@ export class RunnerController { @ResponseSchema(ResponseRunner) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(RunnerNotFoundError) - @OpenAPI({ description: 'Returns a runner of a specified id (if it exists)' }) + @OpenAPI({ description: 'Lists all information about the runner whose id got provided.' }) async getOne(@Param('id') id: number) { let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] }) if (!runner) { throw new RunnerNotFoundError(); } @@ -51,7 +51,7 @@ export class RunnerController { @ResponseSchema(ResponseRunner) @ResponseSchema(RunnerGroupNeededError) @ResponseSchema(RunnerGroupNotFoundError) - @OpenAPI({ description: 'Create a new runner object (id will be generated automagicly).' }) + @OpenAPI({ description: 'Create a new runner.
Please remeber to provide the runner\'s group\'s id.' }) async post(@Body({ validate: true }) createRunner: CreateRunner) { let runner; try { @@ -69,7 +69,7 @@ export class RunnerController { @ResponseSchema(ResponseRunner) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update a runner object (id can't be changed)." }) + @OpenAPI({ description: "Update the runner whose id you provided.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) runner: UpdateRunner) { let oldRunner = await this.runnerRepository.findOne({ id: id }, { relations: ['group'] }); @@ -90,7 +90,7 @@ export class RunnerController { @ResponseSchema(ResponseRunner) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete a specified runner (if it exists).' }) + @OpenAPI({ description: 'Delete the runner whose id you provided.
If no runner with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let runner = await this.runnerRepository.findOne({ id: id }); if (!runner) { return null; } diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index fb86cf2..e10d415 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -12,7 +12,7 @@ import { RunnerTeamController } from './RunnerTeamController'; @JsonController('/organisations') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class RunnerOrganisationController { private runnerOrganisationRepository: Repository; @@ -26,7 +26,7 @@ export class RunnerOrganisationController { @Get() @Authorized("ORGANISATION:GET") @ResponseSchema(ResponseRunnerOrganisation, { isArray: true }) - @OpenAPI({ description: 'Lists all runnerOrganisations.' }) + @OpenAPI({ description: 'Lists all organisations.
This includes their address, contact and teams (if existing/associated).' }) async getAll() { let responseTeams: ResponseRunnerOrganisation[] = new Array(); const runners = await this.runnerOrganisationRepository.find({ relations: ['address', 'contact', 'teams'] }); @@ -41,7 +41,7 @@ export class RunnerOrganisationController { @ResponseSchema(ResponseRunnerOrganisation) @ResponseSchema(RunnerOrganisationNotFoundError, { statusCode: 404 }) @OnUndefined(RunnerOrganisationNotFoundError) - @OpenAPI({ description: 'Returns a runnerOrganisation of a specified id (if it exists)' }) + @OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' }) async getOne(@Param('id') id: number) { let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['address', 'contact', 'teams'] }); if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); } @@ -51,7 +51,7 @@ export class RunnerOrganisationController { @Post() @Authorized("ORGANISATION:CREATE") @ResponseSchema(ResponseRunnerOrganisation) - @OpenAPI({ description: 'Create a new runnerOrganisation object (id will be generated automagicly).' }) + @OpenAPI({ description: 'Create a new organsisation.' }) async post(@Body({ validate: true }) createRunnerOrganisation: CreateRunnerOrganisation) { let runnerOrganisation; try { @@ -70,7 +70,7 @@ export class RunnerOrganisationController { @ResponseSchema(ResponseRunnerOrganisation) @ResponseSchema(RunnerOrganisationNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerOrganisationIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update a runnerOrganisation object (id can't be changed)." }) + @OpenAPI({ description: "Update the organisation whose id you provided.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) updateOrganisation: UpdateRunnerOrganisation) { let oldRunnerOrganisation = await this.runnerOrganisationRepository.findOne({ id: id }); @@ -94,7 +94,7 @@ export class RunnerOrganisationController { @ResponseSchema(RunnerOrganisationHasTeamsError, { statusCode: 406 }) @ResponseSchema(RunnerOrganisationHasRunnersError, { statusCode: 406 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete a specified runnerOrganisation (if it exists).' }) + @OpenAPI({ description: 'Delete the organsisation whose id you provided.
If the organisation still has runners and/or teams associated this will fail.
To delete the organisation with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while).
If no organisation with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let organisation = await this.runnerOrganisationRepository.findOne({ id: id }); if (!organisation) { return null; } diff --git a/src/controllers/RunnerTeamController.ts b/src/controllers/RunnerTeamController.ts index 5040e8c..bc99d79 100644 --- a/src/controllers/RunnerTeamController.ts +++ b/src/controllers/RunnerTeamController.ts @@ -11,7 +11,7 @@ import { RunnerController } from './RunnerController'; @JsonController('/teams') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class RunnerTeamController { private runnerTeamRepository: Repository; @@ -25,7 +25,7 @@ export class RunnerTeamController { @Get() @Authorized("TEAM:GET") @ResponseSchema(ResponseRunnerTeam, { isArray: true }) - @OpenAPI({ description: 'Lists all runnerTeams.' }) + @OpenAPI({ description: 'Lists all teams.
This includes their parent organisation and contact (if existing/associated).' }) async getAll() { let responseTeams: ResponseRunnerTeam[] = new Array(); const runners = await this.runnerTeamRepository.find({ relations: ['parentGroup', 'contact'] }); @@ -40,7 +40,7 @@ export class RunnerTeamController { @ResponseSchema(ResponseRunnerTeam) @ResponseSchema(RunnerTeamNotFoundError, { statusCode: 404 }) @OnUndefined(RunnerTeamNotFoundError) - @OpenAPI({ description: 'Returns a runnerTeam of a specified id (if it exists)' }) + @OpenAPI({ description: 'Lists all information about the team whose id got provided.' }) async getOne(@Param('id') id: number) { let runnerTeam = await this.runnerTeamRepository.findOne({ id: id }, { relations: ['parentGroup', 'contact'] }); if (!runnerTeam) { throw new RunnerTeamNotFoundError(); } @@ -50,7 +50,7 @@ export class RunnerTeamController { @Post() @Authorized("TEAM:CREATE") @ResponseSchema(ResponseRunnerTeam) - @OpenAPI({ description: 'Create a new runnerTeam object (id will be generated automagicly).' }) + @OpenAPI({ description: 'Create a new organsisation.
Please remember to provide it\'s parent group\'s id.' }) async post(@Body({ validate: true }) createRunnerTeam: CreateRunnerTeam) { let runnerTeam; try { @@ -70,7 +70,7 @@ export class RunnerTeamController { @ResponseSchema(ResponseRunnerTeam) @ResponseSchema(RunnerTeamNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerTeamIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update a runnerTeam object (id can't be changed)." }) + @OpenAPI({ description: "Update the team whose id you provided.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) runnerTeam: UpdateRunnerTeam) { let oldRunnerTeam = await this.runnerTeamRepository.findOne({ id: id }, { relations: ['parentGroup', 'contact'] }); @@ -93,7 +93,7 @@ export class RunnerTeamController { @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @ResponseSchema(RunnerTeamHasRunnersError, { statusCode: 406 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete a specified runnerTeam (if it exists).' }) + @OpenAPI({ description: 'Delete the team whose id you provided.
If the team still has runners associated this will fail.
To delete the team with all associated runners set the force QueryParam to true (cascading deletion might take a while).
If no team with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let team = await this.runnerTeamRepository.findOne({ id: id }); if (!team) { return null; } diff --git a/src/controllers/StatusController.ts b/src/controllers/StatusController.ts index 9f83c50..b867429 100644 --- a/src/controllers/StatusController.ts +++ b/src/controllers/StatusController.ts @@ -6,7 +6,7 @@ import { getConnection } from 'typeorm'; export class StatusController { @Get() - @OpenAPI({ description: "Lists all tracks." }) + @OpenAPI({ description: "A very basic status/health endpoint that just checks if the database connection is available.
The available information depth will be expanded later." }) get() { let connection; try { diff --git a/src/controllers/TrackController.ts b/src/controllers/TrackController.ts index d5746ff..1f74193 100644 --- a/src/controllers/TrackController.ts +++ b/src/controllers/TrackController.ts @@ -9,7 +9,7 @@ import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseTrack } from '../models/responses/ResponseTrack'; @JsonController('/tracks') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class TrackController { private trackRepository: Repository; @@ -23,6 +23,7 @@ export class TrackController { @Get() @Authorized("TRACK:GET") @ResponseSchema(ResponseTrack, { isArray: true }) + @OpenAPI({ description: 'Lists all tracks.' }) async getAll() { let responseTracks: ResponseTrack[] = new Array(); const tracks = await this.trackRepository.find(); @@ -37,7 +38,7 @@ export class TrackController { @ResponseSchema(ResponseTrack) @ResponseSchema(TrackNotFoundError, { statusCode: 404 }) @OnUndefined(TrackNotFoundError) - @OpenAPI({ description: "Returns a track of a specified id (if it exists)" }) + @OpenAPI({ description: "Lists all information about the track whose id got provided." }) async getOne(@Param('id') id: number) { let track = await this.trackRepository.findOne({ id: id }); if (!track) { throw new TrackNotFoundError(); } @@ -47,7 +48,7 @@ export class TrackController { @Post() @Authorized("TRACK:CREATE") @ResponseSchema(ResponseTrack) - @OpenAPI({ description: "Create a new track object (id will be generated automagicly)." }) + @OpenAPI({ description: "Create a new track.
Please remember that the track\'s distance must be greater than 0." }) async post( @Body({ validate: true }) track: CreateTrack @@ -60,7 +61,7 @@ export class TrackController { @ResponseSchema(ResponseTrack) @ResponseSchema(TrackNotFoundError, { statusCode: 404 }) @ResponseSchema(TrackIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update a track object (id can't be changed)." }) + @OpenAPI({ description: "Update the track whose id you provided.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @EntityFromBody() track: Track) { let oldTrack = await this.trackRepository.findOne({ id: id }); @@ -81,7 +82,7 @@ export class TrackController { @ResponseSchema(ResponseTrack) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) - @OpenAPI({ description: "Delete a specified track (if it exists)." }) + @OpenAPI({ description: "Delete the track whose id you provided.
If no track with this id exists it will just return 204(no content)." }) async remove(@Param("id") id: number) { let track = await this.trackRepository.findOne({ id: id }); if (!track) { return null; } diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 560f0c8..1b77743 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -12,7 +12,7 @@ import { PermissionController } from './PermissionController'; @JsonController('/users') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class UserController { private userRepository: Repository; @@ -26,7 +26,7 @@ export class UserController { @Get() @Authorized("USER:GET") @ResponseSchema(User, { isArray: true }) - @OpenAPI({ description: 'Lists all users.' }) + @OpenAPI({ description: 'Lists all users.
This includes their groups and permissions directly granted to them (if existing/associated).' }) async getAll() { let responseUsers: ResponseUser[] = new Array(); const users = await this.userRepository.find({ relations: ['permissions', 'groups'] }); @@ -41,7 +41,7 @@ export class UserController { @ResponseSchema(User) @ResponseSchema(UserNotFoundError, { statusCode: 404 }) @OnUndefined(UserNotFoundError) - @OpenAPI({ description: 'Returns a user of a specified id (if it exists)' }) + @OpenAPI({ description: 'Lists all information about the user whose id got provided.
Please remember that only permissions granted directly to the user will show up here, not permissions inherited from groups.' }) async getOne(@Param('id') id: number) { let user = await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups'] }) if (!user) { throw new UserNotFoundError(); } @@ -52,7 +52,7 @@ export class UserController { @Authorized("USER:CREATE") @ResponseSchema(User) @ResponseSchema(UserGroupNotFoundError) - @OpenAPI({ description: 'Create a new user object (id will be generated automagicly).' }) + @OpenAPI({ description: 'Create a new user.
If you want to grant permissions to the user you have to create them seperately by posting to /api/permissions after creating the user.' }) async post(@Body({ validate: true }) createUser: CreateUser) { let user; try { @@ -70,7 +70,7 @@ export class UserController { @ResponseSchema(User) @ResponseSchema(UserNotFoundError, { statusCode: 404 }) @ResponseSchema(UserIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update a user object (id can't be changed)." }) + @OpenAPI({ description: "Update the user whose id you provided.
To change the permissions directly granted to the user please use /api/permissions instead.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) updateUser: UpdateUser) { let oldUser = await this.userRepository.findOne({ id: id }); @@ -91,7 +91,7 @@ export class UserController { @ResponseSchema(User) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete a user runner (if it exists).' }) + @OpenAPI({ description: 'Delete the user whose id you provided.
If there are any permissions directly granted to the user they will get deleted as well.
If no user with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let user = await this.userRepository.findOne({ id: id }); if (!user) { return null; } diff --git a/src/controllers/UserGroupController.ts b/src/controllers/UserGroupController.ts index ea3ab16..4b484fc 100644 --- a/src/controllers/UserGroupController.ts +++ b/src/controllers/UserGroupController.ts @@ -11,7 +11,7 @@ import { PermissionController } from './PermissionController'; @JsonController('/usergroups') -@OpenAPI({ security: [{ "AuthToken": [] }] }) +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class UserGroupController { private userGroupsRepository: Repository; @@ -25,9 +25,9 @@ export class UserGroupController { @Get() @Authorized("USERGROUP:GET") @ResponseSchema(UserGroup, { isArray: true }) - @OpenAPI({ description: 'Lists all usergroups.' }) + @OpenAPI({ description: 'Lists all groups.
The information provided might change while the project continues to evolve.' }) getAll() { - return this.userGroupsRepository.find(); + return this.userGroupsRepository.find({ relations: ["permissions"] }); } @Get('/:id') @@ -35,16 +35,16 @@ export class UserGroupController { @ResponseSchema(UserGroup) @ResponseSchema(UserGroupNotFoundError, { statusCode: 404 }) @OnUndefined(UserGroupNotFoundError) - @OpenAPI({ description: 'Returns a usergroup of a specified id (if it exists)' }) + @OpenAPI({ description: 'Lists all information about the group whose id got provided.
The information provided might change while the project continues to evolve.' }) getOne(@Param('id') id: number) { - return this.userGroupsRepository.findOne({ id: id }); + return this.userGroupsRepository.findOne({ id: id }, { relations: ["permissions"] }); } @Post() @Authorized("USERGROUP:CREATE") @ResponseSchema(UserGroup) @ResponseSchema(UserGroupNotFoundError) - @OpenAPI({ description: 'Create a new usergroup object (id will be generated automagicly).' }) + @OpenAPI({ description: 'Create a new group.
If you want to grant permissions to the group you have to create them seperately by posting to /api/permissions after creating the group.' }) async post(@Body({ validate: true }) createUserGroup: CreateUserGroup) { let userGroup; try { @@ -61,9 +61,9 @@ export class UserGroupController { @ResponseSchema(UserGroup) @ResponseSchema(UserGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(UserGroupIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update a usergroup object (id can't be changed)." }) + @OpenAPI({ description: "Update the group whose id you provided.
To change the permissions granted to the group please use /api/permissions instead.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @EntityFromBody() userGroup: UserGroup) { - let oldUserGroup = await this.userGroupsRepository.findOne({ id: id }); + let oldUserGroup = await this.userGroupsRepository.findOne({ id: id }, { relations: ["permissions"] }); if (!oldUserGroup) { throw new UserGroupNotFoundError() @@ -82,11 +82,11 @@ export class UserGroupController { @ResponseSchema(ResponseUserGroup) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete a specified usergroup (if it exists).' }) + @OpenAPI({ description: 'Delete the group whose id you provided.
If there are any permissions directly granted to the group they will get deleted as well.
Users associated with this group won\'t get deleted - just deassociated.
If no group with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { - let group = await this.userGroupsRepository.findOne({ id: id }); + let group = await this.userGroupsRepository.findOne({ id: id }, { relations: ["permissions"] }); if (!group) { return null; } - const responseGroup = await this.userGroupsRepository.findOne({ id: id }, { relations: ['permissions'] });; + const responseGroup = await this.userGroupsRepository.findOne({ id: id }, { relations: ['permissions'] }); const permissionControler = new PermissionController(); for (let permission of responseGroup.permissions) { diff --git a/src/loaders/openapi.ts b/src/loaders/openapi.ts index 44c6f34..049259b 100644 --- a/src/loaders/openapi.ts +++ b/src/loaders/openapi.ts @@ -29,6 +29,12 @@ export default async (app: Application) => { "scheme": "bearer", "bearerFormat": "JWT", description: "A JWT based access token. Use /api/auth/login or /api/auth/refresh to get one." + }, + "RefreshTokenCookie": { + "type": "apiKey", + "in": "cookie", + "name": "lfk_backend__refresh_token", + description: "A cookie containing a JWT based refreh token. Attention: Doesn't work in swagger-ui. Use /api/auth/login or /api/auth/refresh to get one." } } },