create license management
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
createParamDecorator,
|
||||
ExecutionContext,
|
||||
ForbiddenException,
|
||||
} from '@nestjs/common'
|
||||
import { Request } from 'express'
|
||||
import { IConsumerPayload } from '../models'
|
||||
|
||||
export const ConsumerInfoInfo = createParamDecorator(
|
||||
(data: keyof IConsumerPayload | undefined, ctx: ExecutionContext) => {
|
||||
try {
|
||||
const request = ctx.switchToHttp().getRequest<Request>()
|
||||
const info = request.consumerData
|
||||
|
||||
if (!info) {
|
||||
throw new ForbiddenException('شما به این بخش دسترسی ندارید')
|
||||
}
|
||||
|
||||
if (data) {
|
||||
return info[data]
|
||||
}
|
||||
|
||||
return info
|
||||
} catch (err) {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
|
||||
throw new BadRequestException('مشکلی در ساختار درخواست شما وجود دارد.')
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -14,7 +14,7 @@ export const TokenAccount = createParamDecorator(
|
||||
const account = request.decodedToken
|
||||
|
||||
// ✅ if middleware didn't populate req.account, return undefined or throw
|
||||
if (!account.user?.id) {
|
||||
if (!account || !account.user?.id) {
|
||||
throw new UnauthorizedException('شما به این بخش دسترسی ندارید')
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// src/common/guards/permissions.guard.ts
|
||||
import { ITokenPayload } from '@/modules/auth/auth.utils'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common'
|
||||
import { Request as ExpressRequest } from 'express'
|
||||
|
||||
@Injectable()
|
||||
export class ConsumerGuard {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async canActivate(
|
||||
tokenPayload: ITokenPayload,
|
||||
context: ExecutionContext,
|
||||
): Promise<boolean> {
|
||||
if (!tokenPayload || tokenPayload.type !== 'CONSUMER')
|
||||
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
||||
|
||||
const consumer = await this.prisma.consumer.findFirst({
|
||||
where: {
|
||||
accounts: {
|
||||
some: {
|
||||
id: tokenPayload.account_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
license: {
|
||||
select: {
|
||||
expires_at: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if (!consumer) {
|
||||
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
||||
}
|
||||
|
||||
const req = context.switchToHttp().getRequest<ExpressRequest>()
|
||||
|
||||
if (req.method !== 'GET') {
|
||||
if (!consumer.license?.expires_at) {
|
||||
throw new ForbiddenException('برای کاربر شما لایسنس ایجاد نشده است.')
|
||||
}
|
||||
if (
|
||||
new Date().toUTCString() > new Date(consumer.license?.expires_at).toUTCString()
|
||||
) {
|
||||
throw new ForbiddenException('لایسنس شما منقضی شده است.')
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,26 @@
|
||||
// src/common/guards/permissions.guard.ts
|
||||
import { ITokenPayload } from '@/modules/auth/auth.utils'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
ForbiddenException,
|
||||
Injectable,
|
||||
} from '@nestjs/common'
|
||||
import { Reflector } from '@nestjs/core'
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import { ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common'
|
||||
import { Request as ExpressRequest } from 'express'
|
||||
import { IS_PUBLIC_KEY } from '../decorators/public.decorator'
|
||||
import { checkAndDecodeJwtToken } from '../utils/jwt-user.util'
|
||||
|
||||
@Injectable()
|
||||
export class PosGuard implements CanActivate {
|
||||
constructor(
|
||||
private jwt: JwtService,
|
||||
private reflector: Reflector,
|
||||
private prisma: PrismaService,
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
])
|
||||
if (isPublic) return true
|
||||
|
||||
// const requiredPermissions = this.reflector.get<string[]>(
|
||||
// 'permissions',
|
||||
// context.getHandler(),
|
||||
// )
|
||||
// if (!requiredPermissions || requiredPermissions.length === 0) return true
|
||||
export class PosGuard {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async canActivate(
|
||||
tokenPayload: ITokenPayload,
|
||||
context: ExecutionContext,
|
||||
): Promise<boolean> {
|
||||
const req = context.switchToHttp().getRequest<ExpressRequest>()
|
||||
|
||||
const account = checkAndDecodeJwtToken(req, this.jwt)
|
||||
// const account = req.decodedToken
|
||||
|
||||
if (!req.url.startsWith('/api/v1/pos/')) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!account || account.type !== 'CONSUMER')
|
||||
if (!tokenPayload || tokenPayload.type !== 'CONSUMER')
|
||||
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
||||
|
||||
const cookie = req.cookies
|
||||
const { posId, accessToken } = cookie
|
||||
const { posId } = cookie
|
||||
|
||||
if (!posId || !accessToken) {
|
||||
if (!posId) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -60,7 +32,7 @@ export class PosGuard implements CanActivate {
|
||||
user: {
|
||||
accounts: {
|
||||
some: {
|
||||
id: account.account_id,
|
||||
id: tokenPayload.account_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -83,7 +55,7 @@ export class PosGuard implements CanActivate {
|
||||
|
||||
const foundedAccount = await this.prisma.consumerAccount.findUnique({
|
||||
where: {
|
||||
id: account.account_id,
|
||||
id: tokenPayload.account_id,
|
||||
},
|
||||
select: {
|
||||
role: true,
|
||||
@@ -96,7 +68,7 @@ export class PosGuard implements CanActivate {
|
||||
|
||||
const accountPermissions = await this.prisma.permissionConsumer.findUnique({
|
||||
where: {
|
||||
account_id: account.account_id,
|
||||
account_id: tokenPayload.account_id,
|
||||
},
|
||||
select: {
|
||||
posPermissions: true,
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ITokenPayload } from '@/modules/auth/auth.utils'
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
ForbiddenException,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common'
|
||||
@@ -8,12 +10,16 @@ import { Reflector } from '@nestjs/core'
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import { Request as ExpressRequest } from 'express'
|
||||
import { IS_PUBLIC_KEY } from '../decorators/public.decorator'
|
||||
import { ConsumerGuard } from './auth-consumer.guard'
|
||||
import { PosGuard } from './auth-pos.guard'
|
||||
|
||||
@Injectable()
|
||||
export class JwtAuthGuard implements CanActivate {
|
||||
constructor(
|
||||
private jwt: JwtService,
|
||||
private reflector: Reflector,
|
||||
private consumerGuard: ConsumerGuard,
|
||||
private posGuard: PosGuard,
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
@@ -42,15 +48,19 @@ export class JwtAuthGuard implements CanActivate {
|
||||
secret: process.env.JWT_SECRET,
|
||||
})
|
||||
|
||||
// if (payload.type !== 'POS')
|
||||
// throw new UnauthorizedException('Invalid or expired token')
|
||||
|
||||
// Set the typed dataPayload to the request
|
||||
// req.dataPayload = payload
|
||||
const tokenPayload = this.jwt.decode(token) as ITokenPayload
|
||||
|
||||
if (req.url.startsWith('/api/v1/consumer')) {
|
||||
await this.consumerGuard.canActivate(tokenPayload, context)
|
||||
} else if (req.url.startsWith('/api/v1/pos')) {
|
||||
await this.consumerGuard.canActivate(tokenPayload, context)
|
||||
await this.posGuard.canActivate(tokenPayload, context)
|
||||
} else if (tokenPayload.type != 'ADMIN') {
|
||||
throw new ForbiddenException('شما دسترسی لازم را ندارید')
|
||||
}
|
||||
return true
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
if (err) throw err
|
||||
throw new UnauthorizedException('Invalid or expired token')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface IConsumerPayload {
|
||||
user_id: string
|
||||
account_id: string
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './consumerPayload.model'
|
||||
export * from './posPayload.model'
|
||||
export * from './tokenPayload.model'
|
||||
Reference in New Issue
Block a user