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
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:
parent
7a6c872948
commit
31f5b42962
48 changed files with 389 additions and 198 deletions
|
@ -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]
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue