diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index d0a810a..2ee181c 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -1,13 +1,25 @@ -import { Controller, Get, UseGuards, Req, Res, Logger } from '@nestjs/common'; +import { + Controller, + Get, + Post, + UseGuards, + Req, + Res, + Body, + Logger, +} from '@nestjs/common'; import { Request, Response } from 'express'; import { AuthService } from './auth.service'; import { GoogleAuthGuard } from './google/google.guard'; import { User as AuthUser } from 'passport'; -import { User } from 'src/user/entity/user.entity'; +import { UserEntity } from 'src/user/entity/user.entity'; +import { CreateUserDto } from 'src/user/dto/create-user.dto'; +import { SignUpUserDto } from 'src/user/dto/signup-user.dto'; @Controller('auth') export class AuthController { private readonly logger = new Logger(AuthController.name); + constructor(private readonly authService: AuthService) {} @Get('google') @@ -20,29 +32,67 @@ export class AuthController { @Req() req: Request & { user: AuthUser }, @Res() res: Response, ): Promise { + this.logger.debug(`googleAuthRedirect`); try { - const user = req.user; - this.logger.debug(`googleAuthRedirect [user: ${JSON.stringify(user)}]`); - const userEntity: { isNew: boolean; user: Partial } = - await this.authService.findOrCreateUser(user); - const accessToken: string = await this.authService.generateToken(userEntity.user); - const refreshToken: string = await this.authService.generateRefreshToken(userEntity.user); - // res.cookie('access_token', accessToken, { - // httpOnly: true, - // secure: true, - // sameSite: 'none', - // // expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7), - // }); - res.cookie('refresh_token', refreshToken, { - httpOnly: true, - secure: true, - sameSite: 'none', - expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7), - }); - res.redirect(`${process.env.FRONT_URL}/auth/callback/?token=${accessToken}`); + const user: AuthUser = req.user; + const findUser: Partial = + await this.authService.findOneByEmail(user.email); + if (typeof findUser === 'undefined' || findUser === null) { + this.logger.debug(`new user [user: ${JSON.stringify(user)}]`); + res.cookie('google_token', user.accessToken, { + httpOnly: true, + secure: true, + sameSite: 'none', + }); + res.redirect(`${process.env.FRONT_URL}/auth/signup`); + } else { + this.logger.debug(`existing user [user: ${JSON.stringify(user)}]`); + const accessToken: string = + await this.authService.generateToken(findUser); + const refreshToken: string = + await this.authService.generateRefreshToken(findUser); + this.setCookie(res, accessToken, refreshToken); + res.redirect(`${process.env.FRONT_URL}/auth/callback/`); + } } catch (error) { this.logger.error(`googleAuthRedirect [error: ${error.message}]`); res.status(500).json({ message: error.message }); } } + + @Post('signup') + async signup( + @Req() req: Request, + @Res() res: Response, + @Body() body: SignUpUserDto, + ) { + const user = req['user']; + const userInfo: CreateUserDto = { + email: user.email, + googleId: user.sub, + nickname: body.nickname, + slackId: body.slackId, + }; + console.log('userInfo', userInfo); + const newUser = await this.authService.createUser(userInfo); + const accessToken = await this.authService.generateToken(newUser); + const refreshToken = await this.authService.generateRefreshToken(newUser); + this.setCookie(res, accessToken, refreshToken); + res.redirect(`${process.env.FRONT_URL}/auth/callback/`); + } + + private setCookie(res: Response, accessToken: string, refreshToken: string) { + res.cookie('refresh_token', refreshToken, { + httpOnly: true, + secure: true, + sameSite: 'none', + expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7), + }); + res.cookie('access_token', accessToken, { + httpOnly: true, + secure: true, + sameSite: 'none', + expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 1), + }); + } } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index b7382f9..92dc6fd 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; @@ -8,6 +8,7 @@ import { JwtStrategy } from './jwt/jwt.strategy'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { UserModule } from 'src/user/user.module'; import { UserService } from 'src/user/user.service'; +import { GoogleMiddleware } from './google/google.middleware'; @Module({ imports: [ @@ -32,4 +33,8 @@ import { UserService } from 'src/user/user.service'; controllers: [AuthController], providers: [UserService, AuthService, GoogleStrategy, JwtStrategy], }) -export class AuthModule {} +export class AuthModule implements NestModule { + configure(consumer: MiddlewareConsumer): any { + consumer.apply(GoogleMiddleware).forRoutes('/auth/signup'); + } +} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 385d78a..d5085e4 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -2,7 +2,8 @@ import { Injectable, Logger } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { ConfigService } from '@nestjs/config'; import { UserService } from 'src/user/user.service'; -import { User } from 'src/user/entity/user.entity'; +import { UserEntity } from 'src/user/entity/user.entity'; +import { CreateUserDto } from 'src/user/dto/create-user.dto'; @Injectable() export class AuthService { @@ -13,38 +14,24 @@ export class AuthService { private readonly userService: UserService, ) {} - async googleLogin(user: any): Promise { - this.logger.debug(`googleLogin [user: ${JSON.stringify(user)}]`); - // const userId = user.sub; - const userEntity = await this.userService.findOneByEmail(user.email); - if (typeof userEntity === 'undefined' || userEntity === null) { - await this.userService.createUser(user); - return false; - } - return true; + async findOneByEmail(email: string): Promise { + return this.userService.findOneByEmail(email); } - async generateToken(user: Partial): Promise { + + async generateToken(user: Partial): Promise { const payload = { username: user.nickname, uid: user.id, role: user.role }; return this.jwtService.signAsync(payload); } - async generateRefreshToken(user: Partial): Promise { + async generateRefreshToken(user: Partial): Promise { const payload = { uid: user.id }; return this.jwtService.signAsync(payload, { secret: this.configService.get('jwt.refreshSecret'), expiresIn: this.configService.get('jwt.refreshExpiresIn'), }); } - async findOrCreateUser( - user: any, - ): Promise<{ isNew: boolean; user: Partial }> { - let userEntity: Partial = await this.userService.findOneByEmail( - user.email, - ); - if (typeof userEntity === 'undefined' || userEntity === null) { - userEntity = await this.userService.createUser(user); - return { isNew: true, user: userEntity }; - } - return { isNew: false, user: userEntity }; + + async createUser(user: CreateUserDto): Promise | null> { + return this.userService.createUser(user); } } diff --git a/src/auth/google/google.guard.ts b/src/auth/google/google.guard.ts index 4ed939b..ce56c68 100644 --- a/src/auth/google/google.guard.ts +++ b/src/auth/google/google.guard.ts @@ -8,7 +8,9 @@ export class GoogleAuthGuard extends AuthGuard('google') { constructor() { super({}); } + async canActivate(context: ExecutionContext): Promise { + let result: boolean = false; if (context.getType() === 'http') { this.logger.debug( `canActivate [http, ${context.getArgs()[0].method} ${ @@ -16,16 +18,7 @@ export class GoogleAuthGuard extends AuthGuard('google') { }]`, ); } - // const token = context - // .switchToHttp() - // .getRequest() - // .headers?.authorization?.split('Bearer ')[1]; - const result: boolean = (await super.canActivate(context)) as boolean; - const request = context.switchToHttp().getRequest(); - // await super.logIn(request); - this.logger.debug( - `canActivate success [request.user: ${JSON.stringify(request.user)}]`, - ); + result = (await super.canActivate(context)) as boolean; return result; } }