'get Forbidden resource even when the requested user is admin
Middleware is used to protect the resolver. The middleware checks the role of user and despite the right role of the requested user I cannot access listUser
query. I get following response
"errors": [
{
"message": "Forbidden resource",
"extensions": {
"code": "FORBIDDEN",
"response": {
"statusCode": 403,
"message": "Forbidden resource",
"error": "Forbidden"
}
}
}
],
"data": null
}
Here is my code
model User {
id String @id @default(uuid())
firstName String
lastName String
email String @unique
username String @unique
password String
confirm Boolean @default(false)
isValid Boolean @default(false) @map("is_valid")
isSuperuser Boolean @default(false)
userRoles UserRole[]
@@unique([id, email])
}
model Role {
id String @id @default(uuid())
name String @unique
createdAt DateTime? @db.Timestamp()
updatedAt DateTime? @updatedAt @db.Timestamp()
userRoles UserRole[]
}
model UserRole {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id])
roleId String
role Role @relation(fields: [roleId], references: [id])
createdAt DateTime? @default(now())
updatedAt DateTime? @updatedAt @db.Timestamp()
}
@Injectable()
export class UserMiddleware implements NestMiddleware {
constructor(
private readonly prismaService: PrismaService,
private readonly validationService: ValidationService,
) {}
async use(req: any, res: any, next: () => void) {
if (req.headers.authorization) {
const { userId } = jwt.decode(
String(req.headers.authorization).split(/ /g)[1],
) as JWT;
const user = await this.prismaService.user.findFirst({
where: { id: userId },
include: { userRoles: true },
});
if (user && !user.confirm)
throw new ForbiddenException('User not confirmed');
if (user) {
delete user.password;
req.user = user;
req.user.isAdmin = await this.validationService.isAdmin(userId);
}
}
next();
}
}
@Injectable()
export class ValidationService {
constructor(private readonly prisma: PrismaService) {}
async isAdmin(userId: string): Promise<boolean> {
const u = await this.prisma.role.findUnique({
where: { name: Role.Admin },
});
return await this.prisma.userRole
.count({
// could not find a way to access directly through role name instead of id
where: { userId, roleId: u.id },
})
.then((count) => {
return count ? true : false;
});
}
}
@Query(() => UserPaginated)
@Roles(Role.Admin)
async listUsers(
@Args('paginate', { nullable: true, defaultValue: { skip: 0, take: 50 } })
paginate: PaginationArgs,
@Args('order', {
nullable: true,
defaultValue: { orderBy: 'username', direction: 'desc' },
})
order: OrderListUsers,
@Args('filter', { nullable: true })
filter: FilterListUsers,
) {
return await this.userService.list(paginate, order, filter);
}
Why am I not able to access listUser
with role as Admin ?
Solution 1:[1]
I think your ValidationService has some problems. Please try this. But i should say that, this is not the perfect solution. Your table structure and prisma requests needs some improvements.
@Injectable()
export class ValidationService {
constructor(private readonly prisma: PrismaService) {}
async isAdmin(userId: string): Promise<boolean> {
const u = await this.prisma.role.findUnique({
where: { name: Role.Admin },
});
const userRoleCount = await this.prisma.userRole
.count({
where: { userId, roleId: u.id },
});
return userRoleCount > 0;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dagistan |