Listory/src/auth/auth.controller.ts

108 lines
3.2 KiB
TypeScript
Raw Normal View History

2020-09-05 23:35:53 +02:00
import {
Body as NestBody,
2020-09-05 23:35:53 +02:00
Controller,
Delete,
2020-09-05 23:35:53 +02:00
Get,
Param,
2020-09-05 23:35:53 +02:00
Post,
Res,
UseFilters,
UseGuards,
} from "@nestjs/common";
import { ApiBody, ApiTags } from "@nestjs/swagger";
import type { Response as ExpressResponse } from "express";
2020-02-01 16:11:48 +01:00
import { User } from "../users/user.entity";
2020-09-05 23:35:53 +02:00
import { AuthSession } from "./auth-session.entity";
2020-02-01 16:11:48 +01:00
import { AuthService } from "./auth.service";
2020-09-05 23:35:53 +02:00
import { COOKIE_REFRESH_TOKEN } from "./constants";
import { AuthAccessToken } from "./decorators/auth-access-token.decorator";
import { ReqUser } from "./decorators/req-user.decorator";
import { ApiTokenDto } from "./dto/api-token.dto";
import { CreateApiTokenRequestDto } from "./dto/create-api-token-request.dto";
import { NewApiTokenDto } from "./dto/new-api-token.dto";
2020-09-05 23:35:53 +02:00
import { RefreshAccessTokenResponseDto } from "./dto/refresh-access-token-response.dto";
import { RevokeApiTokenRequestDto } from "./dto/revoke-api-token-request.dto";
2020-09-05 23:35:53 +02:00
import {
RefreshTokenAuthGuard,
SpotifyAuthGuard,
} from "./guards/auth-strategies.guard";
import { SpotifyAuthFilter } from "./spotify.filter";
2020-02-01 16:11:48 +01:00
2022-07-12 20:32:55 +02:00
@ApiTags("auth")
2020-02-01 16:11:48 +01:00
@Controller("api/v1/auth")
export class AuthController {
2021-06-20 00:49:17 +02:00
constructor(private readonly authService: AuthService) {}
2020-02-01 16:11:48 +01:00
@Get("spotify")
2020-09-05 23:35:53 +02:00
@UseGuards(SpotifyAuthGuard)
2020-02-01 16:11:48 +01:00
spotifyRedirect() {
// User is redirected by AuthGuard
}
@Get("spotify/callback")
@UseFilters(SpotifyAuthFilter)
2020-09-05 23:35:53 +02:00
@UseGuards(SpotifyAuthGuard)
async spotifyCallback(@ReqUser() user: User, @Res() res: ExpressResponse) {
2020-09-05 23:35:53 +02:00
const { refreshToken } = await this.authService.createSession(user);
2020-02-01 16:11:48 +01:00
2020-09-05 23:35:53 +02:00
// Refresh token should not be accessible to frontend to reduce risk
// of XSS attacks.
res.cookie(COOKIE_REFRESH_TOKEN, refreshToken, { httpOnly: true });
2020-02-01 16:11:48 +01:00
// Redirect User to SPA
res.redirect("/login/success?source=spotify");
2020-02-01 16:11:48 +01:00
}
2020-09-05 23:35:53 +02:00
@Post("token/refresh")
@UseGuards(RefreshTokenAuthGuard)
async refreshAccessToken(
// With RefreshTokenAuthGuard the session is available instead of user
2023-09-16 13:02:19 +02:00
@ReqUser() session: AuthSession,
2020-09-05 23:35:53 +02:00
): Promise<RefreshAccessTokenResponseDto> {
const { accessToken } = await this.authService.createAccessToken(session);
return { accessToken };
}
@Post("api-tokens")
@ApiBody({ type: CreateApiTokenRequestDto })
@AuthAccessToken()
async createApiToken(
@ReqUser() user: User,
@NestBody("description") description: string,
): Promise<NewApiTokenDto> {
const apiToken = await this.authService.createApiToken(user, description);
return {
id: apiToken.id,
description: apiToken.description,
token: apiToken.token,
createdAt: apiToken.createdAt,
};
}
@Get("api-tokens")
@AuthAccessToken()
async listApiTokens(@ReqUser() user: User): Promise<ApiTokenDto[]> {
const apiTokens = await this.authService.listApiTokens(user);
return apiTokens.map((apiToken) => ({
id: apiToken.id,
description: apiToken.description,
prefix: apiToken.token.slice(0, 12),
createdAt: apiToken.createdAt,
revokedAt: apiToken.revokedAt,
}));
}
@Delete("api-tokens/:id")
@ApiBody({ type: RevokeApiTokenRequestDto })
@AuthAccessToken()
async revokeApiToken(
@ReqUser() user: User,
2023-09-16 13:02:19 +02:00
@Param("id") id: string,
): Promise<void> {
return this.authService.revokeApiToken(user, id);
}
2020-02-01 16:11:48 +01:00
}