Skip to content

Commit

Permalink
Added auth samples
Browse files Browse the repository at this point in the history
  • Loading branch information
jskonst committed Nov 22, 2024
1 parent 066fc95 commit 2af1d0e
Show file tree
Hide file tree
Showing 24 changed files with 614 additions and 32 deletions.
18 changes: 16 additions & 2 deletions client/src/components/User.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
import Button from '@mui/material/Button'
import { UserInfo } from './Users'
import React, { useEffect, useState } from 'react'
import TextField from '@mui/material/TextField';

interface IProps {
user: UserInfo
}

export default function User(props: IProps) {
const [count, setCount] = useState<number>(0);
const [count, setCount] = useState<number>(0);
const [description, setDescription] = useState<string>("");

const clickHandler = () => {
const clickHandler = () => {
console.log(count + 1);
setCount(count + 1);
}

const textChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
setDescription(event.target.value);
}

useEffect(() => {
let isMounted = true;
console.log("useEffect called when text changed");
return () => { isMounted = false }
}, [description, setDescription]);

return (
<>
<h3>Имя пользователя: {props.user.username}</h3>
<h3>ФИО: {props.user.fullname}</h3>
<h3>email: {props.user.email}</h3>
<h3>Count: {count}</h3>
<TextField id="outlined-basic" label="Description" variant="outlined" onChange={textChanged} />
<p>{description}</p>
<Button variant="contained" onClick={clickHandler}>Contained</Button>
</>
)
Expand Down
24 changes: 0 additions & 24 deletions client/src/components/Users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,6 @@ const getUsers = async ():Promise<UserInfo[]> => {
const resp = await fetch("/api/users");
const data = await resp.json();
return data;
// console.log(data);

// const users: UserInfo[] =
// [
// {
// id: "de1b01ad-c4aa-45d9-8147-c091ce89cd02",
// username: "testuser",
// fullname: "test",
// email: "test@test.ru"
// },
// {
// id: "de1b01ad-c4aa-45d9-8147-c091ce89cd01",
// username: "testuser2",
// fullname: "test2",
// email: "222@test2.ru"
// }
// ]
// const promise = new Promise<UserInfo[]>((res, rej) =>{
// setTimeout(()=>{
// res(users);
// }, 5000)
// });
// return promise;

}


Expand Down
2 changes: 1 addition & 1 deletion server/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"type": "node",
"request": "launch",
"name": "Launch Server",
"cwd": "${workspaceRoot}",
Expand Down
10 changes: 10 additions & 0 deletions server/migrations/.snapshot-webdev.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@
"nullable": false,
"length": 255,
"mappedType": "string"
},
"password": {
"name": "password",
"type": "varchar(255)",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"length": 255,
"mappedType": "string"
}
},
"name": "user",
Expand Down
13 changes: 13 additions & 0 deletions server/migrations/Migration20241116145833.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20241116145833 extends Migration {

override async up(): Promise<void> {
this.addSql(`alter table "user" add column "password" varchar(255) not null default 'changeme';`);
}

override async down(): Promise<void> {
this.addSql(`alter table "user" drop column "password";`);
}

}
9 changes: 9 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@
"@mikro-orm/postgresql": "^6.3.11",
"@nestjs/common": "^10.4.4",
"@nestjs/core": "^10.4.4",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "^2.0.5",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.4.4",
"@nestjs/typeorm": "^10.0.2",
"passport": "^0.7.0",
"passport-google-oauth": "^2.0.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pg": "^8.13.0",
"reflect-metadata": "^0.2.2",
"rimraf": "^6.0.1",
Expand All @@ -52,6 +58,9 @@
"@nestjs/testing": "^10.4.4",
"@types/jest": "29.5.13",
"@types/node": "^22.7.3",
"@types/passport-google-oauth": "^1.0.45",
"@types/passport-jwt": "^4.0.1",
"@types/passport-local": "^1.0.38",
"@types/supertest": "^6.0.2",
"@typescript-eslint/eslint-plugin": "8.7.0",
"@typescript-eslint/parser": "8.7.0",
Expand Down
40 changes: 38 additions & 2 deletions server/src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,48 @@
import { Controller, Get } from '@nestjs/common';
import { Controller, Get, Post, Request, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { LocalAuthGuard } from './auth/local-auth.guard';
import { AuthService } from './auth/auth.service';
import { GoogleStrategy } from './auth/google.strategy';
import { GoogleAuthGuard } from './auth/google-auth.guard';

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
constructor(
private readonly appService: AppService,
private authService: AuthService,
private googleStrategy: GoogleStrategy,
) {}

@Get()
getHello(): string {
return this.appService.getHello();
}

@UseGuards(LocalAuthGuard)
@Post('auth/login')
async login(@Request() req) {
return this.authService.login(req.user);
}

@UseGuards(LocalAuthGuard)
@Post('auth/logout')
async logout(@Request() req) {
return req.logout();
}

@UseGuards(GoogleAuthGuard)
@Get('auth/google-login')
async googleLogin(@Request() req) {
console.log('request', req);
return this.googleStrategy.authenticate(req);
}

@UseGuards(GoogleAuthGuard)
@Get('auth/google/google-redirect')
async googleLoginCallback(@Request() req) {
console.log(req);
console.log('REDIrect');
return req.user;
// return this.googleStrategy.validate(req);
}
}
2 changes: 2 additions & 0 deletions server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MikroOrmModule } from '@mikro-orm/nestjs';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
import { UsersModule } from './users/users.module';
import { User } from './users/entities/user.entity';
import { AuthModule } from './auth/auth.module';

@Module({
imports: [
Expand All @@ -28,6 +29,7 @@ import { User } from './users/entities/user.entity';
},
}),
UsersModule,
AuthModule,
],
controllers: [AppController, DemoController],
providers: [AppService],
Expand Down
24 changes: 24 additions & 0 deletions server/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { LocalStrategy } from './local.strategy';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { JwtStrategy } from './jwt.strategy';
import { GoogleStrategy } from './google.strategy';


@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
],
providers: [AuthService, LocalStrategy, JwtStrategy, GoogleStrategy],
exports: [AuthService, GoogleStrategy],
})
export class AuthModule {}
18 changes: 18 additions & 0 deletions server/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AuthService } from './auth.service';

describe('AuthService', () => {
let service: AuthService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
}).compile();

service = module.get<AuthService>(AuthService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
54 changes: 54 additions & 0 deletions server/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Injectable } from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}

async validateUser(username: string, pass: string): Promise<any> {
const user = await this.usersService.findByName(username);
if (user && user.password === pass) {
const { password, ...result } = user;
return result;
}
return null;
}
//Реализация авторизации через google
async validateGoogleUser(accessToken: string, refreshToken: string, profile: any) {
const { name, emails, id, photos } = profile;
const user = await this.usersService.findByName(emails[0].value);
if (user) {
return user;
}

const user_tmp = {
email: emails[0].value,
firstName: name.givenName,
lastName: name.familyName,
picture: photos[0].value,
tmp: 'user authenticated',
accessToken,
refreshToken,
};

const newUser = await this.usersService.create({
username: name,
email: emails[0].value,
password: id,
});

return user_tmp;
}


async login(user: any) {
const payload = { username: user.username, sub: user.userId };
return {
access_token: this.jwtService.sign(payload),
};
}
}
4 changes: 4 additions & 0 deletions server/src/auth/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

export const jwtConstants = {
secret:
};
6 changes: 6 additions & 0 deletions server/src/auth/google-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class GoogleAuthGuard extends AuthGuard('google') {}
7 changes: 7 additions & 0 deletions server/src/auth/google-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export const googleAuthConfig = {
callbackURL: 'http://localhost:4000/api/auth/google/google-redirect',
passReqToCallback: true,
scope: ['email', 'profile']
};

22 changes: 22 additions & 0 deletions server/src/auth/google.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { OAuth2Strategy } from 'passport-google-oauth';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { AuthService } from './auth.service';
import { googleAuthConfig } from './google-auth';

@Injectable()
export class GoogleStrategy extends PassportStrategy(OAuth2Strategy) {
constructor(private authService: AuthService) {
super(
googleAuthConfig
);
}

async validate(req: any, accessToken: string, refreshToken: string, profile: any, done: Function) {
const user = await this.authService.validateGoogleUser(accessToken, refreshToken, profile);


done(null, user);
}
}

6 changes: 6 additions & 0 deletions server/src/auth/jwt-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
20 changes: 20 additions & 0 deletions server/src/auth/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { jwtConstants } from './constants';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jwtConstants.secret,
});
}

async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
6 changes: 6 additions & 0 deletions server/src/auth/local-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}
Loading

0 comments on commit 2af1d0e

Please sign in to comment.