Skip to content

Commit c5dc051

Browse files
authored
Knowledge Table: Display admin permission & Enable actions for admin (#18)
Admin users have write access to all knowledge. Previously, the knowledge table displayed all knowledge, but displayed "No permission" for administrators. It also did not provide the knowledge actions (set tags, permissions etc.) to administrators, even though they are allowed to modify knowledge. This change also refactors the user role "calculation" into the UserContextService, so that the role is globally available.
1 parent 92415c5 commit c5dc051

6 files changed

Lines changed: 44 additions & 25 deletions

File tree

src/locales/de/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"pending": "Läuft"
9797
},
9898
"permission": {
99+
"administrator": "Administrator",
99100
"owner": "Besitzer",
100101
"readwrite": "Lesen/Schreiben",
101102
"readonly": "Lesen",

src/locales/en/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"unknown": "Unknown"
9797
},
9898
"permission": {
99+
"administrator": "Administrator",
99100
"owner": "Owner",
100101
"readwrite": "Read/Write",
101102
"readonly": "Read",

src/services/UserContextService.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ export interface UserContext {
1818

1919
user: UserInfoDto | null;
2020
setUser: (info: UserInfoDto | null) => void;
21+
role: UserRole | null;
22+
setRole: (role: UserRole | null) => void;
2123
}
2224

25+
export type UserRole = "admin" | "user";
26+
2327
const UserContext = createContext<UserContext | undefined>(undefined);
2428

2529
export const UserContextProvider: FC<{ children: ReactNode }> = ({
@@ -28,10 +32,20 @@ export const UserContextProvider: FC<{ children: ReactNode }> = ({
2832
const [ready, setReady] = useState(false);
2933
const [loading, setLoading] = useState(false);
3034
const [user, setUser] = useState<UserInfoDto | null>(null);
35+
const [role, setRole] = useState<UserRole | null>(null);
3136

3237
const value = useMemo(
33-
() => ({ loading, setLoading, ready, setReady, user, setUser }),
34-
[loading, setLoading, ready, setReady, user, setUser],
38+
() => ({
39+
loading,
40+
setLoading,
41+
ready,
42+
setReady,
43+
user,
44+
setUser,
45+
role,
46+
setRole,
47+
}),
48+
[loading, setLoading, ready, setReady, user, setUser, role, setRole],
3549
);
3650

3751
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
@@ -47,7 +61,7 @@ export const useUserContext = () => {
4761

4862
export const useSetupUserContext = () => {
4963
const { token, loginInProgress } = useContext(AuthContext);
50-
const { setReady, setUser } = useUserContext();
64+
const { setReady, setUser, setRole } = useUserContext();
5165
const [loading, setLoading] = useState<boolean>(false);
5266

5367
useEffect(() => {
@@ -81,6 +95,7 @@ export const useSetupUserContext = () => {
8195
throw new Error("Failed to get user info");
8296
}
8397
setUser(response.data);
98+
setRole(getUserRole(response.data.roles));
8499
setReady(true);
85100
setLoading(false);
86101
})
@@ -95,3 +110,13 @@ export const useSetupUserContext = () => {
95110
});
96111
}, [token, loginInProgress]);
97112
};
113+
114+
function getUserRole(roles: string[] | undefined): UserRole | null {
115+
if (!roles) {
116+
return null;
117+
}
118+
if (roles.includes("admin")) {
119+
return "admin";
120+
}
121+
return "user";
122+
}

src/views/knowledge/KnowledgeOptions.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function KnowledgeOptions({
4040
knowledge,
4141
}: Readonly<KnowledgeOptionsProps>) {
4242
const { t } = useTranslation();
43-
const { user } = useUserContext();
43+
const { user, role } = useUserContext();
4444
const { handleDeleteKnowledge } = useDeleteKnowledgeApi();
4545
const { deleteLocalKnowledge } = useGetKnowledgeList();
4646
const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -60,12 +60,13 @@ export default function KnowledgeOptions({
6060
await registerFiles([knowledge.id]);
6161
}
6262

63-
const hasUserPermission = () => {
63+
const hasUserWritePermissions = () => {
64+
if (role === "admin") return true;
6465
if (!knowledge.permissions) return false;
6566
if (knowledge.permissions[USER_ANY] === "READWRITE") return true;
6667
if (!user?.username) return false;
6768
return (
68-
knowledge.permissions[user.username] === "READONLY" ||
69+
knowledge.permissions[user.username] === "READWRITE" ||
6970
knowledge.permissions[user.username] === "OWNER"
7071
);
7172
};
@@ -81,7 +82,7 @@ export default function KnowledgeOptions({
8182
<DropdownMenuLabel>
8283
{t("knowledgePage.options.actions")}
8384
</DropdownMenuLabel>
84-
{hasUserPermission() ? (
85+
{hasUserWritePermissions() ? (
8586
<>
8687
<DropdownMenuItem
8788
onClick={() => {

src/views/knowledge/KnowledgePermissions.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default function KnowledgePermissions({
1313
knowledge,
1414
}: Readonly<KnowledgePermissionsProps>) {
1515
const { t } = useTranslation();
16-
const { user } = useUserContext();
16+
const { user, role } = useUserContext();
1717

1818
if (!knowledge?.permissions || !user?.username) {
1919
return (
@@ -25,9 +25,11 @@ export default function KnowledgePermissions({
2525

2626
return (
2727
<div className="ml-4">
28-
{translatePermissions(
29-
compareWithAnyPermission(knowledge.permissions, user.username),
30-
)}
28+
{role === "admin"
29+
? t("knowledgePage.table.permission.administrator")
30+
: translatePermissions(
31+
compareWithAnyPermission(knowledge.permissions, user.username),
32+
)}
3133
</div>
3234
);
3335
}

src/views/overlays/sidebar/SidebarUser.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,14 @@ export function SidebarUser() {
4545
const [isDeleteUserDialogOpen, setIsDeleteUserDialogOpen] =
4646
useState<boolean>(false);
4747
const { toast } = useToast();
48-
const { user } = useUserContext();
48+
const { user, role } = useUserContext();
4949
const navigate = useNavigate();
5050
const { token, logOut } = useContext(AuthContext);
5151

5252
const loggedIn = token.length > 0;
5353

5454
const username = user?.name ?? user?.username ?? t("user.anonymous");
5555
const name = user?.name ?? username;
56-
const userRole = getUserRole(user?.roles);
5756
const changeLanguageHandler = (lang: string) => {
5857
void i18n.changeLanguage(lang);
5958
};
@@ -113,9 +112,9 @@ export function SidebarUser() {
113112
</Avatar>
114113
<div className="grid flex-1 text-left text-sm leading-tight">
115114
<span className="truncate font-semibold">{name}</span>
116-
{userRole !== null && (
115+
{role !== null && (
117116
<span className="truncate text-xs">
118-
{t(`role.${userRole}`)}
117+
{t(`role.${role}`)}
119118
</span>
120119
)}
121120
</div>
@@ -224,13 +223,3 @@ export function SidebarUser() {
224223
</SidebarMenu>
225224
);
226225
}
227-
228-
const getUserRole = (roles: string[] | undefined): string | null => {
229-
if (!roles) {
230-
return null;
231-
}
232-
if (roles.includes("admin")) {
233-
return "admin";
234-
}
235-
return "user";
236-
};

0 commit comments

Comments
 (0)