1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 08:19:40 +02:00

feat(auth): add useIsEdgeAdmin hook [EE-6627] (#11057)
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run

This commit is contained in:
Chaim Lev-Ari 2024-02-15 00:50:20 +02:00 committed by GitHub
parent 7a6c872948
commit 31f5b42962
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 389 additions and 198 deletions

View file

@ -7,11 +7,14 @@ import {
PropsWithChildren,
} from 'react';
import { isAdmin } from '@/portainer/users/user.helpers';
import { isEdgeAdmin, isPureAdmin } from '@/portainer/users/user.helpers';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { User } from '@/portainer/users/types';
import { useLoadCurrentUser } from '@/portainer/users/queries/useLoadCurrentUser';
import { useEnvironment } from '../portainer/environments/queries';
import { isBE } from '../portainer/feature-flags/feature-flags.service';
interface State {
user?: User;
}
@ -39,32 +42,84 @@ export function useCurrentUser() {
return useMemo(
() => ({
user,
isAdmin: isAdmin(user),
isPureAdmin: isPureAdmin(user),
}),
[user]
);
}
export function useIsPureAdmin() {
const { isPureAdmin } = useCurrentUser();
return isPureAdmin;
}
/**
* Load the admin status of the user, (admin >= edge admin)
* @param forceEnvironmentId to force the environment id, used where the environment id can't be loaded from the router, like sidebar
* @returns query result with isLoading and isAdmin - isAdmin is true if the user edge admin or admin.
*/
export function useIsEdgeAdmin({
forceEnvironmentId,
noEnvScope,
}: {
forceEnvironmentId?: EnvironmentId;
noEnvScope?: boolean;
} = {}) {
const { user } = useCurrentUser();
const {
params: { endpointId },
} = useCurrentStateAndParams();
const envId = forceEnvironmentId || endpointId;
const envScope = typeof noEnvScope === 'boolean' ? !noEnvScope : !!envId;
const envQuery = useEnvironment(envScope ? envId : undefined);
if (!envScope) {
return { isLoading: false, isAdmin: isEdgeAdmin(user) };
}
if (envQuery.isLoading) {
return { isLoading: true, isAdmin: false };
}
return {
isLoading: false,
isAdmin: isEdgeAdmin(user, envQuery.data),
};
}
export function useAuthorizations(
authorizations: string | string[],
forceEnvironmentId?: EnvironmentId,
adminOnlyCE = false
) {
const { user } = useUser();
const { user } = useCurrentUser();
const {
params: { endpointId },
} = useCurrentStateAndParams();
const envQuery = useEnvironment(forceEnvironmentId || endpointId);
const isAdmin = useIsEdgeAdmin({ forceEnvironmentId });
if (!user) {
return false;
return { authorized: false, isLoading: false };
}
return hasAuthorizations(
user,
authorizations,
forceEnvironmentId || endpointId,
adminOnlyCE
);
if (envQuery.isLoading) {
return { authorized: false, isLoading: true };
}
if (isAdmin) {
return { authorized: true, isLoading: false };
}
if (!isBE && adminOnlyCE) {
return { authorized: false, isLoading: false };
}
return {
authorized: hasAuthorizations(user, authorizations, envQuery.data?.Id),
isLoading: false,
};
}
export function useIsEnvironmentAdmin({
@ -81,24 +136,18 @@ export function useIsEnvironmentAdmin({
);
}
export function isEnvironmentAdmin(
user: User,
environmentId: EnvironmentId,
adminOnlyCE = true
) {
return hasAuthorizations(
user,
['EndpointResourcesAccess'],
environmentId,
adminOnlyCE
);
}
export function hasAuthorizations(
/**
* will return true if the user has the authorizations. assumes the user is authenticated and not an admin
* @param user
* @param authorizations
* @param environmentId
* @param adminOnlyCE
* @returns
*/
function hasAuthorizations(
user: User,
authorizations: string | string[],
environmentId?: EnvironmentId,
adminOnlyCE = false
environmentId?: EnvironmentId
) {
const authorizationsArray =
typeof authorizations === 'string' ? [authorizations] : authorizations;
@ -107,26 +156,13 @@ export function hasAuthorizations(
return true;
}
if (process.env.PORTAINER_EDITION === 'CE') {
return !adminOnlyCE || isAdmin(user);
}
if (!environmentId) {
return false;
}
if (isAdmin(user)) {
return true;
}
const userEndpointAuthorizations =
user.EndpointAuthorizations?.[environmentId] || [];
if (
!user.EndpointAuthorizations ||
!user.EndpointAuthorizations[environmentId]
) {
return false;
}
const userEndpointAuthorizations = user.EndpointAuthorizations[environmentId];
return authorizationsArray.some(
(authorization) => userEndpointAuthorizations[authorization]
);