diff --git a/src/app/projects/project-page.tsx b/src/app/projects/project-page.tsx
index 9f3abd4..85690b3 100644
--- a/src/app/projects/project-page.tsx
+++ b/src/app/projects/project-page.tsx
@@ -25,15 +25,15 @@ export default async function ProjectPage() {
const session = await getAuthUserSession();
const data = await projectService.getAllProjects();
const relevantProjectsForUser = data.filter((project) =>
- project.apps.some((app) => RoleUtils.sessionHasReadAccessForApp(session, app.id)));
+ RoleUtils.sessionHasReadAccessToProject(session, project));
return (
Projects
-
+ {RoleUtils.isAdmin(session) &&
-
+ }
diff --git a/src/app/settings/users/page.tsx b/src/app/settings/users/page.tsx
index 2d22c33..838db65 100644
--- a/src/app/settings/users/page.tsx
+++ b/src/app/settings/users/page.tsx
@@ -20,7 +20,7 @@ import appService from "@/server/services/app.service";
export default async function UsersAndRolesPage() {
- await getAdminUserSession();
+ const session = await getAdminUserSession();
const users = await userService.getAllUsers();
const roles = await roleService.getAll();
const allApps = await appService.getAll();
@@ -36,10 +36,10 @@ export default async function UsersAndRolesPage() {
Users
- Roles
+ Roles
-
+
diff --git a/src/app/settings/users/role-edit-overlay.tsx b/src/app/settings/users/role-edit-overlay.tsx
index 3c5f2a9..057e841 100644
--- a/src/app/settings/users/role-edit-overlay.tsx
+++ b/src/app/settings/users/role-edit-overlay.tsx
@@ -4,6 +4,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/u
import {
Form,
FormControl,
+ FormDescription,
FormField,
FormItem,
FormLabel,
@@ -158,14 +159,21 @@ export default function RoleEditOverlay({ children, role, apps }: {
control={form.control}
name="canCreateNewApps"
render={({ field }) => (
-
- Can create new apps
+
+
+
+ Can create new apps
+
+
+ If enabled, users with this role can create new apps. Projects can only be created by admins.
+
+
)}
/>
@@ -174,14 +182,21 @@ export default function RoleEditOverlay({ children, role, apps }: {
control={form.control}
name="canAccessBackups"
render={({ field }) => (
-
- Can access backups
+
+
+
+ Can access backups
+
+
+ If enabled, users can access the backups page and download backups from all apps.
+
+
)}
/>
@@ -234,7 +249,7 @@ export default function RoleEditOverlay({ children, role, apps }: {
-
+
>
)
}
\ No newline at end of file
diff --git a/src/app/settings/users/users-table.tsx b/src/app/settings/users/users-table.tsx
index c0d1074..f09b0dc 100644
--- a/src/app/settings/users/users-table.tsx
+++ b/src/app/settings/users/users-table.tsx
@@ -12,10 +12,12 @@ import { UserExtended } from "@/shared/model/user-extended.model";
import UserEditOverlay from "./user-edit-overlay";
import { deleteUser } from "./actions";
import { RoleExtended } from "@/shared/model/role-extended.model.ts";
+import { UserSession } from "@/shared/model/sim-session.model";
-export default function UsersTable({ users, roles }: {
+export default function UsersTable({ users, roles, session }: {
users: UserExtended[];
roles: RoleExtended[];
+ session: UserSession;
}) {
const { openConfirmDialog: openDialog } = useConfirmDialog();
@@ -44,12 +46,13 @@ export default function UsersTable({ users, roles }: {
<>
-
+ {session.email !== item.email && <>
-
+
+ >}
>}
/>
diff --git a/src/app/sidebar-client.tsx b/src/app/sidebar-client.tsx
index d7fd4ea..b7a2c2f 100644
--- a/src/app/sidebar-client.tsx
+++ b/src/app/sidebar-client.tsx
@@ -165,11 +165,11 @@ export function SidebarCient({
Projects
-
+ {RoleUtils.isAdmin(session) &&
-
+ }
{projects.map((item) => (
diff --git a/src/app/sidebar.tsx b/src/app/sidebar.tsx
index b974897..f24d4de 100644
--- a/src/app/sidebar.tsx
+++ b/src/app/sidebar.tsx
@@ -14,7 +14,7 @@ export async function AppSidebar() {
const projects = await projectService.getAllProjects();
const relevantProjectsForUser = projects.filter((project) =>
- project.apps.some((app) => RoleUtils.sessionHasReadAccessForApp(session, app.id)));
+ RoleUtils.sessionHasReadAccessToProject(session, project));
for (const project of relevantProjectsForUser) {
project.apps = project.apps.filter((app) => RoleUtils.sessionHasReadAccessForApp(session, app.id));
}
diff --git a/src/server/services/app.service.ts b/src/server/services/app.service.ts
index 351dad9..750cd79 100644
--- a/src/server/services/app.service.ts
+++ b/src/server/services/app.service.ts
@@ -63,6 +63,8 @@ class AppService {
revalidateTag(Tags.apps(existingApp.projectId));
revalidateTag(Tags.app(existingApp.id));
revalidateTag(Tags.projects());
+ revalidateTag(Tags.roles());
+ revalidateTag(Tags.users());
}
}
diff --git a/src/server/services/project.service.ts b/src/server/services/project.service.ts
index 238de6e..d7267e0 100644
--- a/src/server/services/project.service.ts
+++ b/src/server/services/project.service.ts
@@ -25,6 +25,8 @@ class ProjectService {
});
} finally {
revalidateTag(Tags.projects());
+ revalidateTag(Tags.roles());
+ revalidateTag(Tags.users());
}
}
diff --git a/src/server/utils/role.utils.ts b/src/server/utils/role.utils.ts
index 819bd96..188da38 100644
--- a/src/server/utils/role.utils.ts
+++ b/src/server/utils/role.utils.ts
@@ -2,7 +2,18 @@ import { adminRoleName, RolePermissionEnum } from "@/shared/model/role-extended.
import { UserSession } from "@/shared/model/sim-session.model";
export class RoleUtils {
+
+ static sessionHasReadAccessToProject(session: UserSession, project: { apps: { id: string; }[] }) {
+ if (project.apps.length === 0 && RoleUtils.sessionCanCreateNewApps(session)) {
+ return true;
+ }
+ return project.apps.some((app) => RoleUtils.sessionHasReadAccessForApp(session, app.id))
+ }
+
static getRolePermissionForApp(session: UserSession, appId: string) {
+ if (this.isAdmin(session)) {
+ return RolePermissionEnum.READWRITE;
+ }
return (session.permissions?.find(app => app.appId === appId)?.permission ?? null) as RolePermissionEnum | null;
}