Initial commit: Prism messenger with Expo + NestJS + GraphQL + PostgreSQL
This commit is contained in:
21
backend/src/modules/auth/auth.module.ts
Normal file
21
backend/src/modules/auth/auth.module.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthResolver } from './auth.resolver';
|
||||
import { JwtStrategy } from './strategies/jwt.strategy';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
UsersModule,
|
||||
PassportModule,
|
||||
JwtModule.register({
|
||||
secret: process.env.JWT_SECRET || 'secret',
|
||||
signOptions: { expiresIn: process.env.JWT_EXPIRATION || '7d' },
|
||||
}),
|
||||
],
|
||||
providers: [AuthService, AuthResolver, JwtStrategy],
|
||||
exports: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
34
backend/src/modules/auth/auth.resolver.ts
Normal file
34
backend/src/modules/auth/auth.resolver.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { Resolver, Mutation, Args, ObjectType, Field } from '@nestjs/graphql';
|
||||
import { AuthService } from './auth.service';
|
||||
import { User } from '../users/entities/user.entity';
|
||||
|
||||
@ObjectType()
|
||||
class AuthResponse {
|
||||
@Field()
|
||||
access_token: string;
|
||||
|
||||
@Field(() => User)
|
||||
user: User;
|
||||
}
|
||||
|
||||
@Resolver()
|
||||
export class AuthResolver {
|
||||
constructor(private authService: AuthService) {}
|
||||
|
||||
@Mutation(() => AuthResponse)
|
||||
async login(
|
||||
@Args('username') username: string,
|
||||
@Args('password') password: string,
|
||||
) {
|
||||
return this.authService.login(username, password);
|
||||
}
|
||||
|
||||
@Mutation(() => AuthResponse)
|
||||
async register(
|
||||
@Args('username') username: string,
|
||||
@Args('email') email: string,
|
||||
@Args('password') password: string,
|
||||
) {
|
||||
return this.authService.register(username, email, password);
|
||||
}
|
||||
}
|
43
backend/src/modules/auth/auth.service.ts
Normal file
43
backend/src/modules/auth/auth.service.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { User } from '../users/entities/user.entity';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private usersService: UsersService,
|
||||
private jwtService: JwtService,
|
||||
) {}
|
||||
|
||||
async validateUser(username: string, password: string): Promise<User | null> {
|
||||
const user = await this.usersService.findByUsername(username);
|
||||
if (user && await bcrypt.compare(password, user.password)) {
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async login(username: string, password: string) {
|
||||
const user = await this.validateUser(username, password);
|
||||
if (!user) {
|
||||
throw new UnauthorizedException('Неверный логин или пароль');
|
||||
}
|
||||
|
||||
const payload = { username: user.username, sub: user.id };
|
||||
return {
|
||||
access_token: this.jwtService.sign(payload),
|
||||
user,
|
||||
};
|
||||
}
|
||||
|
||||
async register(username: string, email: string, password: string) {
|
||||
const user = await this.usersService.create(username, email, password);
|
||||
const payload = { username: user.username, sub: user.id };
|
||||
return {
|
||||
access_token: this.jwtService.sign(payload),
|
||||
user,
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
import { GqlExecutionContext } from '@nestjs/graphql';
|
||||
|
||||
export const CurrentUser = createParamDecorator(
|
||||
(data: unknown, context: ExecutionContext) => {
|
||||
const ctx = GqlExecutionContext.create(context);
|
||||
return ctx.getContext().req.user;
|
||||
},
|
||||
);
|
11
backend/src/modules/auth/guards/gql-auth.guard.ts
Normal file
11
backend/src/modules/auth/guards/gql-auth.guard.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Injectable, ExecutionContext } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { GqlExecutionContext } from '@nestjs/graphql';
|
||||
|
||||
@Injectable()
|
||||
export class GqlAuthGuard extends AuthGuard('jwt') {
|
||||
getRequest(context: ExecutionContext) {
|
||||
const ctx = GqlExecutionContext.create(context);
|
||||
return ctx.getContext().req;
|
||||
}
|
||||
}
|
20
backend/src/modules/auth/strategies/jwt.strategy.ts
Normal file
20
backend/src/modules/auth/strategies/jwt.strategy.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { UsersService } from '../../users/users.service';
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(private usersService: UsersService) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: false,
|
||||
secretOrKey: process.env.JWT_SECRET || 'secret',
|
||||
});
|
||||
}
|
||||
|
||||
async validate(payload: any) {
|
||||
const user = await this.usersService.findOne(payload.sub);
|
||||
return user;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user