first commit
This commit is contained in:
7
myteamwallet_backend/src/auth/auth-providers.enum.ts
Normal file
7
myteamwallet_backend/src/auth/auth-providers.enum.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export enum AuthProvidersEnum {
|
||||
email = 'email',
|
||||
facebook = 'facebook',
|
||||
google = 'google',
|
||||
twitter = 'twitter',
|
||||
apple = 'apple',
|
||||
}
|
||||
139
myteamwallet_backend/src/auth/auth.controller.ts
Normal file
139
myteamwallet_backend/src/auth/auth.controller.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Request,
|
||||
Post,
|
||||
UseGuards,
|
||||
Patch,
|
||||
Delete,
|
||||
UseInterceptors,
|
||||
ClassSerializerInterceptor,
|
||||
SerializeOptions,
|
||||
} from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthEmailLoginDto } from './dto/auth-email-login.dto';
|
||||
import { AuthForgotPasswordDto } from './dto/auth-forgot-password.dto';
|
||||
import { AuthConfirmEmailDto } from './dto/auth-confirm-email.dto';
|
||||
import { AuthResetPasswordDto } from './dto/auth-reset-password.dto';
|
||||
import { AuthUpdateDto } from './dto/auth-update.dto';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import {
|
||||
ApiTags,
|
||||
ApiBearerAuth,
|
||||
ApiOperation,
|
||||
ApiOkResponse,
|
||||
} from '@nestjs/swagger';
|
||||
import { CreateInviteDTO } from './dto/create-invite.dto';
|
||||
|
||||
@ApiTags('Auth')
|
||||
@Controller({
|
||||
path: 'auth',
|
||||
version: '1',
|
||||
})
|
||||
@UseInterceptors(ClassSerializerInterceptor)
|
||||
export class AuthController {
|
||||
constructor(public service: AuthService) {}
|
||||
|
||||
@Post('email/login')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
public async login(@Body() loginDto: AuthEmailLoginDto) {
|
||||
return this.service.validateLogin(loginDto);
|
||||
}
|
||||
|
||||
@Post('admin/email/login')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
public async adminLogin(@Body() loginDTO: AuthEmailLoginDto) {
|
||||
return this.service.validateLogin(loginDTO);
|
||||
}
|
||||
|
||||
@Post('email/register')
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
async register(@Body() createUserDto: any) {
|
||||
return this.service.register(createUserDto);
|
||||
}
|
||||
|
||||
@Post('email/confirm')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async confirmEmail(@Body() confirmEmailDto: AuthConfirmEmailDto) {
|
||||
return this.service.confirmEmail(confirmEmailDto.hash);
|
||||
}
|
||||
|
||||
@Post('forgot/password')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async forgotPassword(@Body() forgotPasswordDto: AuthForgotPasswordDto) {
|
||||
return this.service.forgotPassword(forgotPasswordDto.email);
|
||||
}
|
||||
|
||||
@Post('reset/password')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async resetPassword(@Body() resetPasswordDto: AuthResetPasswordDto) {
|
||||
return this.service.resetPassword(
|
||||
resetPasswordDto.hash,
|
||||
resetPasswordDto.password,
|
||||
);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@SerializeOptions({
|
||||
groups: ['exposeProvider'],
|
||||
})
|
||||
@Get('me')
|
||||
// @UseGuards(AuthGuard('jwt'))
|
||||
@HttpCode(HttpStatus.OK)
|
||||
public me(@Request() request: Request) {
|
||||
return this.service.me(request.headers['authorization']);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@Patch('me')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@HttpCode(HttpStatus.OK)
|
||||
public async update(@Request() request, @Body() userDto: AuthUpdateDto) {
|
||||
return this.service.update(request.user, userDto);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@Delete('me')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@HttpCode(HttpStatus.OK)
|
||||
public async delete(@Request() request) {
|
||||
return this.service.softDelete(request.user);
|
||||
}
|
||||
|
||||
@ApiOperation({
|
||||
summary: 'Erstellt Registrierungstoken',
|
||||
description:
|
||||
'Encoded den JWT Token für eine Einladung für eine neue Registrierung. Team- und Rollen-Infos müssen da sein. Der Token ist dann 30 Tage gültig.',
|
||||
})
|
||||
@ApiOkResponse({
|
||||
description: 'JWT Token',
|
||||
isArray: false,
|
||||
type: 'string',
|
||||
})
|
||||
@Post('invite')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
public getInvite(
|
||||
@Body()
|
||||
invite: any,
|
||||
) {
|
||||
return this.service.createTeamInvite(invite);
|
||||
}
|
||||
|
||||
@ApiOperation({
|
||||
summary: 'Verifiziert Registrierungstoken',
|
||||
description:
|
||||
'Decoded und prüft den JWT Token einer Einladung für die Registrierung',
|
||||
})
|
||||
@ApiOkResponse({
|
||||
description: 'Object mit teamName, teamId, roleName, roleId',
|
||||
isArray: false,
|
||||
type: CreateInviteDTO,
|
||||
})
|
||||
@Post('verify-invite')
|
||||
public verifyInvite(@Body() body: any) {
|
||||
return this.service.getTeamFromInvite(body.token);
|
||||
}
|
||||
}
|
||||
38
myteamwallet_backend/src/auth/auth.module.ts
Normal file
38
myteamwallet_backend/src/auth/auth.module.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtStrategy } from './strategies/jwt.strategy';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { AnonymousStrategy } from './strategies/anonymous.strategy';
|
||||
import { UsersModule } from 'src/users/users.module';
|
||||
import { ForgotModule } from 'src/forgot/forgot.module';
|
||||
import { MailModule } from 'src/mail/mail.module';
|
||||
import { IsExist } from 'src/utils/validators/is-exists.validator';
|
||||
import { IsNotExist } from 'src/utils/validators/is-not-exists.validator';
|
||||
import { LoggingModule } from 'src/database/logging/logging.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
UsersModule,
|
||||
ForgotModule,
|
||||
PassportModule,
|
||||
MailModule,
|
||||
JwtModule.registerAsync({
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
secret: configService.get('auth.secret'),
|
||||
signOptions: {
|
||||
expiresIn: configService.get('auth.expires'),
|
||||
},
|
||||
}),
|
||||
}),
|
||||
LoggingModule,
|
||||
],
|
||||
controllers: [AuthController],
|
||||
providers: [IsExist, IsNotExist, AuthService, JwtStrategy, AnonymousStrategy],
|
||||
exports: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
405
myteamwallet_backend/src/auth/auth.service.ts
Normal file
405
myteamwallet_backend/src/auth/auth.service.ts
Normal file
@@ -0,0 +1,405 @@
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { User } from '../users/entities/user.entity';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import { AuthEmailLoginDto } from './dto/auth-email-login.dto';
|
||||
import { AuthUpdateDto } from './dto/auth-update.dto';
|
||||
import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util';
|
||||
import { RoleEnum } from 'src/roles/roles.enum';
|
||||
import { StatusEnum } from 'src/statuses/statuses.enum';
|
||||
import * as crypto from 'crypto';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { Status } from 'src/statuses/entities/status.entity';
|
||||
import { Role } from 'src/roles/entities/role.entity';
|
||||
import { AuthProvidersEnum } from './auth-providers.enum';
|
||||
import { SocialInterface } from 'src/social/interfaces/social.interface';
|
||||
import { AuthRegisterLoginDto } from './dto/auth-register-login.dto';
|
||||
import { UsersService } from 'src/users/users.service';
|
||||
import { ForgotService } from 'src/forgot/forgot.service';
|
||||
import { MailService } from 'src/mail/mail.service';
|
||||
import { CreateInviteDTO } from './dto/create-invite.dto';
|
||||
import { LoggingService } from 'src/database/logging/logging.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private jwtService: JwtService,
|
||||
private usersService: UsersService,
|
||||
private forgotService: ForgotService,
|
||||
private mailService: MailService,
|
||||
private logger: LoggingService,
|
||||
) {}
|
||||
|
||||
async validateLogin(
|
||||
loginDto: AuthEmailLoginDto,
|
||||
): Promise<{ token: string; user: User }> {
|
||||
const user = await this.usersService.findOne({
|
||||
email: loginDto.email,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
await this.logger.info({
|
||||
event: 'user_login_fail',
|
||||
details: `mail not found: ${loginDto.email}`,
|
||||
userId: -1,
|
||||
});
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
email: 'notFound',
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
if (user.provider !== AuthProvidersEnum.email) {
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
email: `needLoginViaProvider:${user.provider}`,
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
const isValidPassword = await bcrypt.compare(
|
||||
loginDto.password,
|
||||
user.password,
|
||||
);
|
||||
|
||||
if (isValidPassword) {
|
||||
const token = await this.jwtService.sign({
|
||||
id: user.id,
|
||||
role: user.role,
|
||||
});
|
||||
|
||||
await this.logger.info({
|
||||
event: 'user_login_success',
|
||||
details: `logged in: ${loginDto.email}`,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
return { token, user: user };
|
||||
} else {
|
||||
await this.logger.info({
|
||||
event: 'user_login_fail',
|
||||
details: `incorrect password for user: ${loginDto.email}`,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
password: 'incorrectPassword',
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async validateSocialLogin(
|
||||
authProvider: string,
|
||||
socialData: SocialInterface,
|
||||
): Promise<{ token: string; user: User }> {
|
||||
let user: User;
|
||||
const socialEmail = socialData.email?.toLowerCase();
|
||||
|
||||
const userByEmail = await this.usersService.findOne({
|
||||
email: socialEmail,
|
||||
});
|
||||
|
||||
user = await this.usersService.findOne({
|
||||
socialId: socialData.id,
|
||||
provider: authProvider,
|
||||
});
|
||||
|
||||
if (user) {
|
||||
if (socialEmail && !userByEmail) {
|
||||
user.email = socialEmail;
|
||||
}
|
||||
await this.usersService.update(user.id, user);
|
||||
} else if (userByEmail) {
|
||||
user = userByEmail;
|
||||
} else {
|
||||
const role = plainToClass(Role, {
|
||||
id: RoleEnum.user,
|
||||
});
|
||||
const status = plainToClass(Status, {
|
||||
id: StatusEnum.active,
|
||||
});
|
||||
|
||||
user = await this.usersService.create({
|
||||
email: socialEmail,
|
||||
firstName: socialData.firstName,
|
||||
lastName: socialData.lastName,
|
||||
socialId: socialData.id,
|
||||
provider: authProvider,
|
||||
role,
|
||||
status,
|
||||
});
|
||||
|
||||
user = await this.usersService.findOne({
|
||||
id: user.id,
|
||||
});
|
||||
}
|
||||
|
||||
const jwtToken = await this.jwtService.sign({
|
||||
id: user.id,
|
||||
role: user.role,
|
||||
});
|
||||
|
||||
return {
|
||||
token: jwtToken,
|
||||
user,
|
||||
};
|
||||
}
|
||||
|
||||
async register(dto: AuthRegisterLoginDto): Promise<void> {
|
||||
const hash = crypto
|
||||
.createHash('sha256')
|
||||
.update(randomStringGenerator())
|
||||
.digest('hex');
|
||||
|
||||
const user = await this.usersService.create({
|
||||
...dto,
|
||||
email: dto.email,
|
||||
role: {
|
||||
id: RoleEnum.user,
|
||||
} as Role,
|
||||
status: {
|
||||
id: StatusEnum.inactive,
|
||||
} as Status,
|
||||
hash,
|
||||
});
|
||||
|
||||
if (user && dto.linkPlayerId != null) {
|
||||
await this.usersService.linkPlayerToUserId(user, dto.linkPlayerId);
|
||||
}
|
||||
|
||||
await this.logger.info({
|
||||
event: 'user_create',
|
||||
details: `user created with mail: ${dto.email}`,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
await this.mailService.userSignUp({
|
||||
to: user.email,
|
||||
data: {
|
||||
hash,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async confirmEmail(hash: string): Promise<void> {
|
||||
const user = await this.usersService.findOne({
|
||||
hash,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.NOT_FOUND,
|
||||
error: `notFound`,
|
||||
},
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
user.hash = null;
|
||||
user.status = plainToClass(Status, {
|
||||
id: StatusEnum.active,
|
||||
});
|
||||
await user.save();
|
||||
}
|
||||
|
||||
async forgotPassword(email: string): Promise<void> {
|
||||
const user = await this.usersService.findOne({
|
||||
email,
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
email: 'emailNotExists',
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
} else {
|
||||
const hash = crypto
|
||||
.createHash('sha256')
|
||||
.update(randomStringGenerator())
|
||||
.digest('hex');
|
||||
await this.forgotService.create({
|
||||
hash,
|
||||
user,
|
||||
});
|
||||
|
||||
await this.mailService.forgotPassword({
|
||||
to: email,
|
||||
data: {
|
||||
hash,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async resetPassword(hash: string, password: string): Promise<void> {
|
||||
const forgot = await this.forgotService.findOne({
|
||||
where: {
|
||||
hash,
|
||||
},
|
||||
});
|
||||
|
||||
if (!forgot) {
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
hash: `notFound`,
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
const user = forgot.user;
|
||||
user.password = password;
|
||||
await user.save();
|
||||
await this.forgotService.softDelete(forgot.id);
|
||||
}
|
||||
|
||||
async me(token: string): Promise<User> {
|
||||
token = token.replace('Bearer ', '');
|
||||
let role: any;
|
||||
try {
|
||||
role = this.jwtService.verify(token);
|
||||
|
||||
const u = await this.usersService.findOne({
|
||||
id: role.id,
|
||||
});
|
||||
|
||||
await this.logger.debug({
|
||||
event: 'user_token_verification_success',
|
||||
details: `Email: ${u.email}`,
|
||||
userId: u.id,
|
||||
});
|
||||
|
||||
return u;
|
||||
} catch (error) {
|
||||
const role = this.jwtService.decode(token);
|
||||
|
||||
const user = await this.usersService.findOne({
|
||||
id: (role as any).id,
|
||||
});
|
||||
const t = await this.jwtService.sign({
|
||||
id: user.id,
|
||||
role: user.role,
|
||||
});
|
||||
|
||||
user['token'] = t;
|
||||
await this.logger.debug({
|
||||
event: 'user_token_verification_success',
|
||||
details: `Email: ${user.email}`,
|
||||
userId: user.id,
|
||||
});
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
async update(user: User, userDto: AuthUpdateDto): Promise<User> {
|
||||
if (userDto.password) {
|
||||
if (userDto.oldPassword) {
|
||||
const currentUser = await this.usersService.findOne({
|
||||
id: user.id,
|
||||
});
|
||||
|
||||
const isValidOldPassword = await bcrypt.compare(
|
||||
userDto.oldPassword,
|
||||
currentUser.password,
|
||||
);
|
||||
|
||||
if (!isValidOldPassword) {
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
oldPassword: 'incorrectOldPassword',
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(
|
||||
{
|
||||
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
errors: {
|
||||
oldPassword: 'missingOldPassword',
|
||||
},
|
||||
},
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await this.usersService.update(user.id, userDto);
|
||||
|
||||
return this.usersService.findOne({
|
||||
id: user.id,
|
||||
});
|
||||
}
|
||||
|
||||
async softDelete(user: User): Promise<void> {
|
||||
await this.usersService.softDelete(user.id);
|
||||
}
|
||||
|
||||
async createTeamInvite(object: CreateInviteDTO) {
|
||||
const token = await this.jwtService.sign(object, {
|
||||
expiresIn: '30d',
|
||||
});
|
||||
|
||||
await this.logger.info({
|
||||
event: 'user_invite_link_create',
|
||||
details: `invitation created for team: ${object.teamName} , ${object.teamId}`,
|
||||
userId: 0,
|
||||
});
|
||||
|
||||
return { token };
|
||||
}
|
||||
|
||||
async getTeamFromInvite(token: string) {
|
||||
try {
|
||||
const teamInfo = this.jwtService.verify(token);
|
||||
delete teamInfo.iat;
|
||||
delete teamInfo.exp;
|
||||
|
||||
await this.logger.info({
|
||||
event: 'user_invite_link_validate',
|
||||
details: `invitation validated for team: ${teamInfo.teamName} , ${teamInfo.teamId}`,
|
||||
userId: 0,
|
||||
});
|
||||
|
||||
return teamInfo;
|
||||
} catch {
|
||||
await this.logger.info({
|
||||
event: 'user_invite_link_validate_fail',
|
||||
details: `validation failed for token ${token}`,
|
||||
userId: 0,
|
||||
});
|
||||
|
||||
throw new HttpException(
|
||||
'Token not valid',
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class AuthConfirmEmailDto {
|
||||
@ApiProperty()
|
||||
@IsNotEmpty()
|
||||
hash: string;
|
||||
}
|
||||
17
myteamwallet_backend/src/auth/dto/auth-email-login.dto.ts
Normal file
17
myteamwallet_backend/src/auth/dto/auth-email-login.dto.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, Validate } from 'class-validator';
|
||||
import { IsExist } from 'src/utils/validators/is-exists.validator';
|
||||
import { Transform } from 'class-transformer';
|
||||
|
||||
export class AuthEmailLoginDto {
|
||||
@ApiProperty({ example: 'test1@example.com' })
|
||||
@Transform(({ value }) => value.toLowerCase().trim())
|
||||
@Validate(IsExist, ['User'], {
|
||||
message: 'emailNotExists',
|
||||
})
|
||||
email: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNotEmpty()
|
||||
password: string;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEmail } from 'class-validator';
|
||||
import { Transform } from 'class-transformer';
|
||||
|
||||
export class AuthForgotPasswordDto {
|
||||
@ApiProperty()
|
||||
@Transform(({ value }) => value.toLowerCase().trim())
|
||||
@IsEmail()
|
||||
email: string;
|
||||
}
|
||||
29
myteamwallet_backend/src/auth/dto/auth-register-login.dto.ts
Normal file
29
myteamwallet_backend/src/auth/dto/auth-register-login.dto.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEmail, IsNotEmpty, MinLength, Validate } from 'class-validator';
|
||||
import { IsNotExist } from 'src/utils/validators/is-not-exists.validator';
|
||||
import { Transform } from 'class-transformer';
|
||||
|
||||
export class AuthRegisterLoginDto {
|
||||
@ApiProperty({ example: 'test1@example.com' })
|
||||
@Transform(({ value }) => value.toLowerCase().trim())
|
||||
@Validate(IsNotExist, ['User'], {
|
||||
message: 'emailAlreadyExists',
|
||||
})
|
||||
@IsEmail()
|
||||
email: string;
|
||||
|
||||
@ApiProperty()
|
||||
@MinLength(6)
|
||||
password: string;
|
||||
|
||||
@ApiProperty({ example: 'John' })
|
||||
@IsNotEmpty()
|
||||
firstName: string;
|
||||
|
||||
@ApiProperty({ example: 'Doe' })
|
||||
@IsNotEmpty()
|
||||
lastName: string;
|
||||
|
||||
@ApiProperty({ example: 27 })
|
||||
linkPlayerId: number | null;
|
||||
}
|
||||
12
myteamwallet_backend/src/auth/dto/auth-reset-password.dto.ts
Normal file
12
myteamwallet_backend/src/auth/dto/auth-reset-password.dto.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty } from 'class-validator';
|
||||
|
||||
export class AuthResetPasswordDto {
|
||||
@ApiProperty()
|
||||
@IsNotEmpty()
|
||||
password: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNotEmpty()
|
||||
hash: string;
|
||||
}
|
||||
22
myteamwallet_backend/src/auth/dto/auth-social-login.dto.ts
Normal file
22
myteamwallet_backend/src/auth/dto/auth-social-login.dto.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Allow, IsNotEmpty } from 'class-validator';
|
||||
import { Tokens } from 'src/social/tokens';
|
||||
import { AuthProvidersEnum } from '../auth-providers.enum';
|
||||
|
||||
export class AuthSocialLoginDto {
|
||||
@Allow()
|
||||
@ApiProperty({ type: () => Tokens })
|
||||
tokens: Tokens;
|
||||
|
||||
@ApiProperty({ enum: AuthProvidersEnum })
|
||||
@IsNotEmpty()
|
||||
socialType: AuthProvidersEnum;
|
||||
|
||||
@Allow()
|
||||
@ApiProperty({ required: false })
|
||||
firstName?: string;
|
||||
|
||||
@Allow()
|
||||
@ApiProperty({ required: false })
|
||||
lastName?: string;
|
||||
}
|
||||
34
myteamwallet_backend/src/auth/dto/auth-update.dto.ts
Normal file
34
myteamwallet_backend/src/auth/dto/auth-update.dto.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsOptional, MinLength, Validate } from 'class-validator';
|
||||
import { IsExist } from '../../utils/validators/is-exists.validator';
|
||||
import { FileEntity } from '../../files/entities/file.entity';
|
||||
|
||||
export class AuthUpdateDto {
|
||||
@ApiProperty({ type: () => FileEntity })
|
||||
@IsOptional()
|
||||
@Validate(IsExist, ['FileEntity', 'id'], {
|
||||
message: 'imageNotExists',
|
||||
})
|
||||
photo?: FileEntity;
|
||||
|
||||
@ApiProperty({ example: 'John' })
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: 'mustBeNotEmpty' })
|
||||
firstName?: string;
|
||||
|
||||
@ApiProperty({ example: 'Doe' })
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: 'mustBeNotEmpty' })
|
||||
lastName?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
@MinLength(6)
|
||||
password?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: 'mustBeNotEmpty' })
|
||||
oldPassword: string;
|
||||
}
|
||||
15
myteamwallet_backend/src/auth/dto/create-invite.dto.ts
Normal file
15
myteamwallet_backend/src/auth/dto/create-invite.dto.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class CreateInviteDTO {
|
||||
@ApiProperty()
|
||||
teamId: number;
|
||||
|
||||
@ApiProperty({ example: 'Development Team' })
|
||||
teamName: string;
|
||||
|
||||
@ApiProperty()
|
||||
playerId: number;
|
||||
|
||||
@ApiProperty({ example: 'Max Mustermann' })
|
||||
playerName: string;
|
||||
}
|
||||
6
myteamwallet_backend/src/auth/dto/verify-token.dto.ts
Normal file
6
myteamwallet_backend/src/auth/dto/verify-token.dto.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class VerifyTokenDTO {
|
||||
@ApiProperty({ example: 'JWT' })
|
||||
token: string;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Strategy } from 'passport-anonymous';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
|
||||
@Injectable()
|
||||
export class AnonymousStrategy extends PassportStrategy(Strategy) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public validate(payload: unknown, request: unknown): unknown {
|
||||
return request;
|
||||
}
|
||||
}
|
||||
28
myteamwallet_backend/src/auth/strategies/jwt.strategy.ts
Normal file
28
myteamwallet_backend/src/auth/strategies/jwt.strategy.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { User } from '../../users/entities/user.entity';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
type JwtPayload = Pick<User, 'id' | 'role'> & { iat: number; exp: number };
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(
|
||||
private jwtService: JwtService,
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: configService.get('auth.secret'),
|
||||
});
|
||||
}
|
||||
|
||||
public validate(payload: JwtPayload) {
|
||||
if (!payload.id) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user