feat: add admin guard and JWT role support
- Create AdminGuard to check user role - Update JWT strategy to include role in payload - Update auth service to include role in token generation - Prepare admin module structure - TypeScript will resolve lint errors after server restart
This commit is contained in:
0
apps/api/src/admin/admin-plans.controller.ts
Normal file
0
apps/api/src/admin/admin-plans.controller.ts
Normal file
0
apps/api/src/admin/admin-plans.service.ts
Normal file
0
apps/api/src/admin/admin-plans.service.ts
Normal file
0
apps/api/src/admin/admin.module.ts
Normal file
0
apps/api/src/admin/admin.module.ts
Normal file
31
apps/api/src/admin/guards/admin.guard.ts
Normal file
31
apps/api/src/admin/guards/admin.guard.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import {
|
||||
Injectable,
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
ForbiddenException,
|
||||
} from '@nestjs/common';
|
||||
|
||||
interface RequestWithUser {
|
||||
user: {
|
||||
userId: string;
|
||||
role?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AdminGuard implements CanActivate {
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
const request = context.switchToHttp().getRequest<RequestWithUser>();
|
||||
const user = request.user;
|
||||
|
||||
if (!user) {
|
||||
throw new ForbiddenException('Authentication required');
|
||||
}
|
||||
|
||||
if (user.role !== 'admin') {
|
||||
throw new ForbiddenException('Admin access required');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -359,10 +359,17 @@ export class AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
private generateToken(userId: string, email: string): string {
|
||||
private async generateToken(userId: string, email: string): Promise<string> {
|
||||
// Get user role
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { role: true },
|
||||
});
|
||||
|
||||
return this.jwtService.sign({
|
||||
sub: userId,
|
||||
email,
|
||||
role: user?.role || 'user',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
export interface JwtPayload {
|
||||
sub: string; // user ID
|
||||
email: string;
|
||||
role?: string; // user role
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
}
|
||||
@@ -20,6 +21,10 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
}
|
||||
|
||||
async validate(payload: JwtPayload) {
|
||||
return { userId: payload.sub, email: payload.email };
|
||||
return {
|
||||
userId: payload.sub,
|
||||
email: payload.email,
|
||||
role: payload.role || 'user'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user