feat: add comprehensive permission tests and enhance permission checks in components

- Introduced new test files for permission checks, including `check-permission.test.ts`, `enterprise-only-resources.test.ts`, `resolve-permissions.test.ts`, and `service-access.test.ts`.
- Implemented permission checks in various components to ensure actions are gated by user permissions, including `ShowTraefikConfig`, `UpdateTraefikConfig`, `ShowVolumes`, `ShowDomains`, and others.
- Enhanced the logic for displaying UI elements based on user permissions, ensuring that only authorized users can access or modify resources.
This commit is contained in:
Mauricio Siu
2026-03-15 16:42:48 -06:00
parent 8eace173b9
commit 8127dc4536
118 changed files with 25020 additions and 5430 deletions
+59 -1
View File
@@ -1,10 +1,10 @@
import type { IncomingMessage } from "node:http";
import { apiKey } from "@better-auth/api-key";
import { sso } from "@better-auth/sso";
import * as bcrypt from "bcrypt";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { APIError } from "better-auth/api";
import { apiKey } from "@better-auth/api-key";
import { admin, organization, twoFactor } from "better-auth/plugins";
import { and, desc, eq } from "drizzle-orm";
import { BETTER_AUTH_SECRET, IS_CLOUD } from "../constants";
@@ -15,6 +15,7 @@ import {
getTrustedProviders,
getUserByToken,
} from "../services/admin";
import { createAuditLog } from "../services/proprietary/audit-log";
import {
getWebServerSettings,
updateWebServerSettings,
@@ -22,6 +23,7 @@ import {
import { getHubSpotUTK, submitToHubSpot } from "../utils/tracking/hubspot";
import { sendEmail } from "../verification/send-verification-email";
import { getPublicIpWithFallback } from "../wss/utils";
import { ac, adminRole, memberRole, ownerRole } from "./access-control";
const { handler, api } = betterAuth({
database: drizzleAdapter(db, {
@@ -270,6 +272,52 @@ const { handler, api } = betterAuth({
},
};
},
after: async (session) => {
const orgId = (
session as typeof session & { activeOrganizationId?: string }
).activeOrganizationId;
if (!orgId) return;
const memberRecord = await db.query.member.findFirst({
where: and(
eq(schema.member.userId, session.userId),
eq(schema.member.organizationId, orgId),
),
with: { user: true },
});
if (!memberRecord) return;
await createAuditLog({
organizationId: orgId,
userId: session.userId,
userEmail: memberRecord.user.email,
userRole: memberRecord.role,
action: "login",
resourceType: "session",
});
},
},
delete: {
after: async (session) => {
const orgId = (
session as typeof session & { activeOrganizationId?: string }
).activeOrganizationId;
if (!orgId) return;
const memberRecord = await db.query.member.findFirst({
where: and(
eq(schema.member.userId, session.userId),
eq(schema.member.organizationId, orgId),
),
with: { user: true },
});
if (!memberRecord) return;
await createAuditLog({
organizationId: orgId,
userId: session.userId,
userEmail: memberRecord.user.email,
userRole: memberRecord.role,
action: "logout",
resourceType: "session",
});
},
},
},
},
@@ -323,6 +371,16 @@ const { handler, api } = betterAuth({
sso(),
twoFactor(),
organization({
ac,
roles: {
owner: ownerRole,
admin: adminRole,
member: memberRole,
},
dynamicAccessControl: {
enabled: true,
maximumRolesPerOrganization: 10,
},
async sendInvitationEmail(data, _request) {
if (IS_CLOUD) {
const host =