chore: cache org guard and fix roles guard apiv2 (#15719)
This commit is contained in:
@@ -1,14 +1,24 @@
|
||||
import { OrganizationsRepository } from "@/modules/organizations/organizations.repository";
|
||||
import { RedisService } from "@/modules/redis/redis.service";
|
||||
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from "@nestjs/common";
|
||||
import { Request } from "express";
|
||||
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
type CachedData = {
|
||||
org?: Team;
|
||||
canAccess?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class IsOrgGuard implements CanActivate {
|
||||
constructor(private organizationsRepository: OrganizationsRepository) {}
|
||||
constructor(
|
||||
private organizationsRepository: OrganizationsRepository,
|
||||
private readonly redisService: RedisService
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
let canAccess = false;
|
||||
const request = context.switchToHttp().getRequest<Request & { organization: Team }>();
|
||||
const organizationId: string = request.params.orgId;
|
||||
|
||||
@@ -16,13 +26,33 @@ export class IsOrgGuard implements CanActivate {
|
||||
throw new ForbiddenException("No organization id found in request params.");
|
||||
}
|
||||
|
||||
const org = await this.organizationsRepository.findById(Number(organizationId));
|
||||
const REDIS_CACHE_KEY = `apiv2:org:${organizationId}:guard:isOrg`;
|
||||
const cachedData = await this.redisService.redis.get(REDIS_CACHE_KEY);
|
||||
|
||||
if (org && org.isOrganization) {
|
||||
request.organization = org;
|
||||
return true;
|
||||
if (cachedData) {
|
||||
const { org: cachedOrg, canAccess: cachedCanAccess } = JSON.parse(cachedData) as CachedData;
|
||||
if (cachedOrg?.id === Number(organizationId) && cachedCanAccess !== undefined) {
|
||||
request.organization = cachedOrg;
|
||||
return cachedCanAccess;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
const org = await this.organizationsRepository.findById(Number(organizationId));
|
||||
|
||||
if (org?.isOrganization) {
|
||||
request.organization = org;
|
||||
canAccess = true;
|
||||
}
|
||||
|
||||
if (org) {
|
||||
await this.redisService.redis.set(
|
||||
REDIS_CACHE_KEY,
|
||||
JSON.stringify({ org: org, canAccess } satisfies CachedData),
|
||||
"EX",
|
||||
300
|
||||
);
|
||||
}
|
||||
|
||||
return canAccess;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,23 +101,23 @@ export class RolesGuard implements CanActivate {
|
||||
// if the user is admin or owner of org, allow request because org > team
|
||||
if (`ORG_${orgMembership.role}` === "ORG_ADMIN" || `ORG_${orgMembership.role}` === "ORG_OWNER") {
|
||||
canAccess = true;
|
||||
}
|
||||
} else {
|
||||
if (!teamMembership) {
|
||||
this.logger.log(
|
||||
`User (${user.id}) is not part of the team (${teamId}) and/or, is not an admin nor an owner of the organization (${orgId}).`
|
||||
);
|
||||
throw new ForbiddenException(
|
||||
"User is not part of the team and/or, is not an admin nor an owner of the organization."
|
||||
);
|
||||
}
|
||||
|
||||
if (!teamMembership) {
|
||||
this.logger.log(
|
||||
`User (${user.id}) is not part of the team (${teamId}) and/or, is not an admin nor an owner of the organization (${orgId}).`
|
||||
);
|
||||
throw new ForbiddenException(
|
||||
"User is not part of the team and/or, is not an admin nor an owner of the organization."
|
||||
);
|
||||
// if user is not admin nor an owner of org, and is part of the team, then check user team membership role
|
||||
canAccess = hasMinimumRole({
|
||||
checkRole: `TEAM_${teamMembership.role}`,
|
||||
minimumRole: allowedRole,
|
||||
roles: TEAM_ROLES,
|
||||
});
|
||||
}
|
||||
|
||||
// if user is not admin nor an owner of org, and is part of the team, then check user team membership role
|
||||
canAccess = hasMinimumRole({
|
||||
checkRole: `TEAM_${teamMembership.role}`,
|
||||
minimumRole: allowedRole,
|
||||
roles: TEAM_ROLES,
|
||||
});
|
||||
}
|
||||
|
||||
// if allowed role is a ORG ROLE, check org membersip role
|
||||
@@ -129,7 +129,7 @@ export class RolesGuard implements CanActivate {
|
||||
});
|
||||
}
|
||||
}
|
||||
await this.redisService.redis.set(REDIS_CACHE_KEY, String(canAccess), "EX", 3600);
|
||||
await this.redisService.redis.set(REDIS_CACHE_KEY, String(canAccess), "EX", 300);
|
||||
return canAccess;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user