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:
dwindown
2025-10-11 14:15:34 +07:00
parent c3bc181063
commit 9b789b333f
26 changed files with 117 additions and 15 deletions

View File

View 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;
}
}

View File

@@ -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',
});
}

View File

@@ -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'
};
}
}