Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { redirect } from "next/navigation";

import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { hasInsightsPermission } from "@calcom/features/insights/server/hasInsightsPermission";
import { prisma } from "@calcom/prisma";

import { buildLegacyRequest } from "@lib/buildLegacyCtx";
Expand All @@ -21,14 +20,5 @@ export async function checkInsightsPagePermission() {
redirect("/auth/login");
}

const hasPermission = await hasInsightsPermission({
userId: session.user.id,
organizationId: session.user.org?.id,
});

if (!hasPermission) {
redirect("/");
}

return session;
}
77 changes: 76 additions & 1 deletion apps/web/playwright/insights.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { expect } from "@playwright/test";

import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service";
import { randomString } from "@calcom/lib/random";
import prisma from "@calcom/prisma";
import { prisma } from "@calcom/prisma";

import { clearFilters, applySelectFilter } from "./filter-helpers";
import { test } from "./lib/fixtures";
import { createAllPermissionsArray, enablePBACForTeam } from "./lib/test-helpers/pbac";

test.describe.configure({ mode: "parallel" });

Expand Down Expand Up @@ -272,4 +275,76 @@ test.describe("Insights", async () => {
await expect(chartCard).toBeVisible();
}
});

test("should be able to access insights page with custom role lacking insights.read permission", async ({
page,
users,
}) => {
const owner = await users.create(undefined, {
hasTeam: true,
isUnpublished: true,
isOrg: true,
});

const userOne = await users.create();
const userTwo = await users.create();

const { teamOne } = await createTeamsAndMembership(userOne.id, userTwo.id);

const orgMembership = await owner.getOrgMembership();
const orgId = orgMembership.team.id;

await enablePBACForTeam(orgId);
await enablePBACForTeam(teamOne.id);

const permissions = createAllPermissionsArray().filter(
({ resource, action }) => !(resource === "insights" && action === "read")
);

const customRole = await prisma.role.create({
data: {
id: `e2e_no_insights_${orgId}_${Date.now()}`,
name: "E2E Role Without Insights",
description: "E2E role for testing - has all permissions except insights.read",
color: "#dc2626",
teamId: orgId,
type: "CUSTOM",
permissions: {
create: permissions,
},
},
});

await prisma.membership.update({
where: {
userId_teamId: {
userId: userOne.id,
teamId: teamOne.id,
},
},
data: {
customRoleId: customRole.id,
},
});

const featuresRepository = new FeaturesRepository(prisma);
const isPBACEnabled = await featuresRepository.checkIfTeamHasFeature(orgId, "pbac");
expect(isPBACEnabled).toBe(true);

const permissionService = new PermissionCheckService();
const hasPermission = await permissionService.checkPermission({
userId: userOne.id,
teamId: teamOne.id,
permission: "insights.read",
fallbackRoles: [],
});
expect(hasPermission).toBe(false);

await userOne.apiLogin();
await page.goto("/insights");

// Verify the user can access the insights page
await page.locator('[data-testid^="insights-filters-"]').waitFor();
expect(page.url()).toContain("/insights");
});
});
29 changes: 29 additions & 0 deletions apps/web/playwright/lib/test-helpers/pbac.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { PERMISSION_REGISTRY } from "@calcom/features/pbac/domain/types/permission-registry";
import { prisma } from "@calcom/prisma";

// Create array of all permissions from PERMISSION_REGISTRY
export const createAllPermissionsArray = () => {
const allPermissions: { resource: string; action: string }[] = [];

Object.entries(PERMISSION_REGISTRY).forEach(([resource, resourceConfig]) => {
if (resource === "*") {
return;
}
Object.entries(resourceConfig).forEach(([action, _details]) => {
allPermissions.push({ resource, action });
});
});

return allPermissions;
};

export const enablePBACForTeam = async (teamId: number) => {
await prisma.teamFeatures.create({
data: {
featureId: "pbac",
teamId: teamId,
assignedBy: "e2e",
assignedAt: new Date(),
},
});
};
39 changes: 0 additions & 39 deletions packages/features/insights/server/hasInsightsPermission.ts

This file was deleted.

Loading
Loading