mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
sample(new auth sample): matches new auth chapter
This commit is contained in:
34
sample/24-auth-jwt/.gitignore
vendored
Normal file
34
sample/24-auth-jwt/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# compiled output
|
||||
/dist
|
||||
/node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
# Tests
|
||||
/coverage
|
||||
/.nyc_output
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
5
sample/24-auth-jwt/nest-cli.json
Normal file
5
sample/24-auth-jwt/nest-cli.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"language": "ts",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src"
|
||||
}
|
||||
6
sample/24-auth-jwt/nodemon-debug.json
Normal file
6
sample/24-auth-jwt/nodemon-debug.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"watch": ["src"],
|
||||
"ext": "ts",
|
||||
"ignore": ["src/**/*.spec.ts"],
|
||||
"exec": "node --inspect-brk -r ts-node/register -r tsconfig-paths/register src/main.ts"
|
||||
}
|
||||
5
sample/24-auth-jwt/nodemon.json
Normal file
5
sample/24-auth-jwt/nodemon.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"watch": ["dist"],
|
||||
"ext": "js",
|
||||
"exec": "node dist/main"
|
||||
}
|
||||
67
sample/24-auth-jwt/package.json
Normal file
67
sample/24-auth-jwt/package.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "auth-sample",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"format": "prettier --write \"src/**/*.ts\"",
|
||||
"start": "ts-node -r tsconfig-paths/register src/main.ts",
|
||||
"start:dev": "concurrently --handle-input \"wait-on dist/main.js && nodemon\" \"tsc -w -p tsconfig.build.json\" ",
|
||||
"start:debug": "nodemon --config nodemon-debug.json",
|
||||
"prestart:prod": "rimraf dist && npm run build",
|
||||
"start:prod": "node dist/main.js",
|
||||
"lint": "tslint -p tsconfig.json -c tslint.json",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^6.0.0",
|
||||
"@nestjs/core": "^6.0.0",
|
||||
"@nestjs/jwt": "^6.1.1",
|
||||
"@nestjs/passport": "^6.1.0",
|
||||
"@nestjs/platform-express": "^6.0.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-jwt": "^4.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"rimraf": "^2.6.2",
|
||||
"rxjs": "^6.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/testing": "^6.0.0",
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/jest": "^23.3.13",
|
||||
"@types/node": "^10.12.18",
|
||||
"@types/supertest": "^2.0.7",
|
||||
"concurrently": "^4.1.0",
|
||||
"jest": "^23.6.0",
|
||||
"nodemon": "^1.18.9",
|
||||
"prettier": "^1.15.3",
|
||||
"supertest": "^3.4.1",
|
||||
"ts-jest": "24.0.2",
|
||||
"ts-node": "8.1.0",
|
||||
"tsconfig-paths": "3.8.0",
|
||||
"tslint": "5.16.0",
|
||||
"typescript": "3.4.3",
|
||||
"wait-on": "^3.2.0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".spec.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
||||
22
sample/24-auth-jwt/src/app.controller.spec.ts
Normal file
22
sample/24-auth-jwt/src/app.controller.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
describe('AppController', () => {
|
||||
let appController: AppController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const app: TestingModule = await Test.createTestingModule({
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
}).compile();
|
||||
|
||||
appController = app.get<AppController>(AppController);
|
||||
});
|
||||
|
||||
describe('root', () => {
|
||||
it('should return "Hello World!"', () => {
|
||||
expect(appController.getHello()).toBe('Hello World!');
|
||||
});
|
||||
});
|
||||
});
|
||||
20
sample/24-auth-jwt/src/app.controller.ts
Normal file
20
sample/24-auth-jwt/src/app.controller.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Controller, Get, Request, Post, UseGuards } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { AuthService } from './auth/auth.service';
|
||||
|
||||
@Controller('api')
|
||||
export class AppController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@UseGuards(AuthGuard('local'))
|
||||
@Post('/login')
|
||||
async login(@Request() req) {
|
||||
return this.authService.login(req.user);
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Get('/me')
|
||||
getProfile(@Request() req) {
|
||||
return req.user;
|
||||
}
|
||||
}
|
||||
12
sample/24-auth-jwt/src/app.module.ts
Normal file
12
sample/24-auth-jwt/src/app.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { UsersModule } from './users/users.module';
|
||||
|
||||
@Module({
|
||||
imports: [AuthModule, UsersModule],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
8
sample/24-auth-jwt/src/app.service.ts
Normal file
8
sample/24-auth-jwt/src/app.service.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getHello(): string {
|
||||
return 'Hello World!';
|
||||
}
|
||||
}
|
||||
22
sample/24-auth-jwt/src/auth/auth.module.ts
Normal file
22
sample/24-auth-jwt/src/auth/auth.module.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { LocalStrategy } from './local.strategy';
|
||||
import { JwtStrategy } from './jwt.strategy';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { jwtConstants } from './constants';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
UsersModule,
|
||||
PassportModule,
|
||||
JwtModule.register({
|
||||
secret: jwtConstants.secret,
|
||||
signOptions: { expiresIn: '60s' },
|
||||
}),
|
||||
],
|
||||
providers: [AuthService, LocalStrategy, JwtStrategy],
|
||||
exports: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
18
sample/24-auth-jwt/src/auth/auth.service.spec.ts
Normal file
18
sample/24-auth-jwt/src/auth/auth.service.spec.ts
Normal file
@@ -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();
|
||||
});
|
||||
});
|
||||
27
sample/24-auth-jwt/src/auth/auth.service.ts
Normal file
27
sample/24-auth-jwt/src/auth/auth.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private readonly usersService: UsersService,
|
||||
private readonly jwtService: JwtService,
|
||||
) {}
|
||||
|
||||
async validateUser(username: string, pass: string): Promise<any> {
|
||||
const user = await this.usersService.findOne(username);
|
||||
if (user && user.password === pass) {
|
||||
const { password, ...result } = user;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async login(user: any) {
|
||||
const payload = { username: user.username, sub: user.userId };
|
||||
return {
|
||||
access_token: this.jwtService.sign(payload),
|
||||
};
|
||||
}
|
||||
}
|
||||
3
sample/24-auth-jwt/src/auth/constants.ts
Normal file
3
sample/24-auth-jwt/src/auth/constants.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const jwtConstants = {
|
||||
secret: 'secretKey',
|
||||
};
|
||||
19
sample/24-auth-jwt/src/auth/jwt.strategy.ts
Normal file
19
sample/24-auth-jwt/src/auth/jwt.strategy.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
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 };
|
||||
}
|
||||
}
|
||||
19
sample/24-auth-jwt/src/auth/local.strategy.ts
Normal file
19
sample/24-auth-jwt/src/auth/local.strategy.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Strategy } from 'passport-local';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
@Injectable()
|
||||
export class LocalStrategy extends PassportStrategy(Strategy) {
|
||||
constructor(private readonly authService: AuthService) {
|
||||
super();
|
||||
}
|
||||
|
||||
async validate(username: string, password: string): Promise<any> {
|
||||
const user = await this.authService.validateUser(username, password);
|
||||
if (!user) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
8
sample/24-auth-jwt/src/main.ts
Normal file
8
sample/24-auth-jwt/src/main.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(3000);
|
||||
}
|
||||
bootstrap();
|
||||
8
sample/24-auth-jwt/src/users/users.module.ts
Normal file
8
sample/24-auth-jwt/src/users/users.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UsersService } from './users.service';
|
||||
|
||||
@Module({
|
||||
providers: [UsersService],
|
||||
exports: [UsersService],
|
||||
})
|
||||
export class UsersModule {}
|
||||
18
sample/24-auth-jwt/src/users/users.service.spec.ts
Normal file
18
sample/24-auth-jwt/src/users/users.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { UsersService } from './users.service';
|
||||
|
||||
describe('UsersService', () => {
|
||||
let service: UsersService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [UsersService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<UsersService>(UsersService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
30
sample/24-auth-jwt/src/users/users.service.ts
Normal file
30
sample/24-auth-jwt/src/users/users.service.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
private readonly users;
|
||||
|
||||
constructor() {
|
||||
this.users = [
|
||||
{
|
||||
userId: 1,
|
||||
username: 'john',
|
||||
password: 'changeme',
|
||||
},
|
||||
{
|
||||
userId: 2,
|
||||
username: 'chris',
|
||||
password: 'secret',
|
||||
},
|
||||
{
|
||||
userId: 3,
|
||||
username: 'maria',
|
||||
password: 'guess',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async findOne(username): Promise<any> {
|
||||
return this.users.filter(user => user.username === username)[0];
|
||||
}
|
||||
}
|
||||
4
sample/24-auth-jwt/tsconfig.build.json
Normal file
4
sample/24-auth-jwt/tsconfig.build.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
}
|
||||
15
sample/24-auth-jwt/tsconfig.json
Normal file
15
sample/24-auth-jwt/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "es6",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "./",
|
||||
"incremental": true
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
18
sample/24-auth-jwt/tslint.json
Normal file
18
sample/24-auth-jwt/tslint.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": ["tslint:recommended"],
|
||||
"jsRules": {
|
||||
"no-unused-expression": true
|
||||
},
|
||||
"rules": {
|
||||
"quotemark": [true, "single"],
|
||||
"member-access": [false],
|
||||
"ordered-imports": [false],
|
||||
"max-line-length": [true, 150],
|
||||
"member-ordering": [false],
|
||||
"interface-name": [false],
|
||||
"arrow-parens": false,
|
||||
"object-literal-sort-keys": false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
||||
0
scripts/test.sh
Executable file → Normal file
0
scripts/test.sh
Executable file → Normal file
Reference in New Issue
Block a user