Skip to content

Commit 41dda1b

Browse files
committed
WIP auth system
1 parent 6d3327a commit 41dda1b

File tree

18 files changed

+233
-48
lines changed

18 files changed

+233
-48
lines changed

app/nuxt.config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ export default defineNuxtConfig({
3636
provider: {
3737
type: 'local',
3838
endpoints: {
39-
signIn: { path: '/login', method: 'post' },
39+
signIn: { path: '/local', method: 'post' },
4040
signOut: { path: '/logout', method: 'post' },
41-
signUp: { path: '/register', method: 'post' },
4241
getSession: { path: '/session', method: 'get' },
4342
},
4443
pages: {

app/src/pages/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ div
1111
<script lang='ts' setup>
1212
import { definePageMeta, useAuth } from '#imports'
1313
const { signIn, signOut, session, status, cookies, getProviders, user, sessionToken } = useAuth()
14+
1415
</script>

service/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
TK_SERVICE_MONGOOSE_URI=mongodb://localhost:27017/teaket
2+
TK_SERVICE_JWT_SECRET=kkns]ge^BC2m|O1HY!eIhvRx,w9%i.PkH-X.+K~E;2.@yXh4Q=h2y@jT5L+rtP*

service/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@nestjs/swagger": "^7.1.10",
3232
"@streamkits/nestjs_module_scrud": "^0.0.15",
3333
"@typegoose/auto-increment": "^3.4.0",
34+
"argon2": "^0.31.1",
3435
"cookie-parser": "^1.4.6",
3536
"dayjs": "^1.11.9",
3637
"deepmerge": "^4.3.1",
@@ -40,6 +41,7 @@
4041
"mongoose-unique-validator": "^4.0.0",
4142
"passport": "^0.6.0",
4243
"passport-jwt": "^4.0.1",
44+
"passport-local": "^1.0.0",
4345
"reflect-metadata": "^0.1.13",
4446
"rxjs": "^7.2.0",
4547
"swagger-themes": "^1.2.30",
@@ -57,6 +59,7 @@
5759
"@types/node": "18.15.11",
5860
"@types/passport": "^1.0.12",
5961
"@types/passport-jwt": "^3.0.9",
62+
"@types/passport-local": "^1.0.35",
6063
"@types/supertest": "^2.0.11",
6164
"@typescript-eslint/eslint-plugin": "^5.0.0",
6265
"@typescript-eslint/parser": "^5.0.0",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { createParamDecorator, ExecutionContext } from '@nestjs/common'
2+
import { IdentityType } from '~/_common/types/identity.type'
3+
4+
export const ReqIdentity = createParamDecorator((_data: unknown, ctx: ExecutionContext): IdentityType => {
5+
const request = ctx.switchToHttp().getRequest()
6+
return request.user
7+
})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ExecutionContext, Injectable } from '@nestjs/common'
2+
import { Reflector } from '@nestjs/core'
3+
import { AuthGuard as AuthGuardInternal } from '@nestjs/passport'
4+
import { Observable } from 'rxjs'
5+
import { META_UNPROTECTED } from '~/_common/decorators/public.decorator'
6+
7+
@Injectable()
8+
export class AuthGuard extends AuthGuardInternal(['jwt']) {
9+
public constructor(private readonly reflector: Reflector) {
10+
super()
11+
}
12+
13+
public canActivate(
14+
context: ExecutionContext,
15+
): boolean | Promise<boolean> | Observable<boolean> {
16+
const isUnprotected = this.reflector.getAllAndOverride<boolean>(
17+
META_UNPROTECTED,
18+
[context.getClass(), context.getHandler()],
19+
)
20+
return isUnprotected || super.canActivate(context)
21+
}
22+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Identities } from '~/core/identities/_schemas/identities.schema'
2+
3+
export const ExcludeIdentityType: (keyof Identities)[] = ['password']
4+
5+
export type IdentityType = Partial<Omit<Identities, 'password'>>

service/src/app.module.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { INestApplication, Module } from '@nestjs/common'
1+
import { Module } from '@nestjs/common'
22
import { AppController } from './app.controller'
33
import { AppService } from './app.service'
44
import { TicketsModule } from '~/tickets/tickets.module'
@@ -8,11 +8,12 @@ import { ConfigModule, ConfigService } from '@nestjs/config'
88
import config, { MongoosePlugin } from './config'
99
import { RedisModule } from '@nestjs-modules/ioredis'
1010
import { RedisOptions } from 'ioredis'
11-
import { APP_FILTER, APP_PIPE } from '@nestjs/core'
11+
import { APP_FILTER, APP_GUARD, APP_PIPE } from '@nestjs/core'
1212
import { MongooseValidationFilter } from './_common/filters/mongoose-validation.filter'
1313
import { DtoValidationPipe } from './_common/pipes/dto-validation.pipe'
1414
import { CoreModule } from '~/core/core.module'
1515
import { ShutdownService } from '~/shutdown.service'
16+
import { AuthGuard } from '~/_common/guards/auth.guard'
1617

1718
@Module({
1819
imports: [
@@ -55,6 +56,10 @@ import { ShutdownService } from '~/shutdown.service'
5556
providers: [
5657
AppService,
5758
ShutdownService,
59+
// {
60+
// provide: APP_GUARD,
61+
// useClass: AuthGuard,
62+
// },
5863
{
5964
provide: APP_FILTER,
6065
useClass: MongooseValidationFilter,

service/src/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export interface ConfigInstance {
2626
options: IAuthModuleOptions
2727
}
2828
jwt: {
29-
options: JwtModuleOptions & any
29+
options: JwtModuleOptions
3030
}
3131
// oidc: {
3232
// options: BuildOpenIdClientOptions
@@ -84,7 +84,7 @@ export default (): ConfigInstance => ({
8484
* @see https://randomkeygen.com/
8585
*/
8686
secret: process.env.TK_SERVICE_JWT_SECRET,
87-
jwksUri: 'http://127.0.0.1:2000/jwks',
87+
// jwksUri: 'http://127.0.0.1:2000/jwks',
8888
},
8989
},
9090
// oidc: {
Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,55 @@
1-
import { Controller, Get, Post, Res } from '@nestjs/common'
1+
import { Controller, Get, HttpStatus, Post, Res, UseGuards } from '@nestjs/common'
22
import { AuthService } from './auth.service'
33
import { AbstractController } from '~/_common/abstracts/abstract.controller'
44
import { Response } from 'express'
55
import { ApiTags } from '@nestjs/swagger'
6+
import { Public } from '~/_common/decorators/public.decorator'
7+
import { ModuleRef } from '@nestjs/core'
8+
import { AuthGuard } from '@nestjs/passport'
9+
import { IdentityType } from '~/_common/types/identity.type'
10+
import { ReqIdentity } from '~/_common/decorators/params/req-identity.decorator'
611

12+
@Public()
713
@ApiTags('core')
814
@Controller('auth')
915
export class AuthController extends AbstractController {
10-
constructor(private readonly service: AuthService) {
16+
constructor(
17+
protected moduleRef: ModuleRef,
18+
private readonly service: AuthService,
19+
) {
1120
super()
1221
}
1322

14-
@Post('login')
15-
public async login(@Res() res: Response): Promise<Response> {
16-
console.log('login')
17-
return res.json({
18-
token: '123',
23+
@Post('local')
24+
@UseGuards(AuthGuard('local'))
25+
public async authenticateWithLocal(@Res() res: Response, @ReqIdentity() identity: IdentityType): Promise<Response> {
26+
const tokens = await this.service.createToken(identity)
27+
return res.status(HttpStatus.CREATED).json({
28+
...tokens,
29+
token: '1234',
30+
identity,
1931
user: {
20-
id: "1",
32+
id: 1,
2133
}
2234
})
2335
}
2436

2537
@Get('session')
26-
public async session(@Res() res: Response): Promise<Response> {
27-
// console.log('session')
28-
return res.json({
38+
// @UseGuards(AuthGuard('jwt'))
39+
public async session(@Res() res: Response, @ReqIdentity() identity: IdentityType): Promise<Response> {
40+
// const tokens = await this.service.createToken(identity)
41+
return res.status(HttpStatus.OK).json({
42+
// ...tokens,
2943
token: '1234',
44+
identity,
3045
user: {
31-
id: "1",
46+
id: 1,
3247
}
3348
})
3449
}
3550

36-
@Get('credentials')
37-
public async credentials(@Res() res: Response): Promise<Response> {
38-
return res.json({
39-
token: '123',
40-
user: {
41-
id: "1",
42-
}
43-
})
51+
@Post('logout')
52+
public async logout(@Res() res: Response): Promise<Response> {
53+
return res.status(HttpStatus.NO_CONTENT).send()
4454
}
4555
}

0 commit comments

Comments
 (0)