mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-18 00:19:49 +01:00
feat(cjux-278): maintenance root roles (#8875)
Custom root roles for changing maintenance mode state and banners. Internal ticket: CJUX-278
This commit is contained in:
parent
c860d8e434
commit
5cc0e589e8
@ -3,6 +3,7 @@ import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuar
|
|||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
|
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
|
||||||
import { BannersTable } from './BannersTable/BannersTable';
|
import { BannersTable } from './BannersTable/BannersTable';
|
||||||
|
import { UPDATE_INSTANCE_BANNERS } from '@server/types/permissions';
|
||||||
|
|
||||||
export const Banners = () => {
|
export const Banners = () => {
|
||||||
const { isEnterprise } = useUiConfig();
|
const { isEnterprise } = useUiConfig();
|
||||||
@ -13,7 +14,7 @@ export const Banners = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<PermissionGuard permissions={ADMIN}>
|
<PermissionGuard permissions={[ADMIN, UPDATE_INSTANCE_BANNERS]}>
|
||||||
<BannersTable />
|
<BannersTable />
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,10 +6,11 @@ import { Box, styled } from '@mui/material';
|
|||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { MaintenanceTooltip } from './MaintenanceTooltip';
|
import { MaintenanceTooltip } from './MaintenanceTooltip';
|
||||||
import { MaintenanceToggle } from './MaintenanceToggle';
|
import { MaintenanceToggle } from './MaintenanceToggle';
|
||||||
|
import { UPDATE_MAINTENANCE_MODE } from '@server/types/permissions';
|
||||||
|
|
||||||
export const MaintenanceAdmin = () => (
|
export const MaintenanceAdmin = () => (
|
||||||
<div>
|
<div>
|
||||||
<PermissionGuard permissions={ADMIN}>
|
<PermissionGuard permissions={[ADMIN, UPDATE_MAINTENANCE_MODE]}>
|
||||||
<MaintenancePage />
|
<MaintenancePage />
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,6 +42,9 @@ export const RolePermissionCategories = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||||
|
const granularAdminPermissionsEnabled = useUiFlag(
|
||||||
|
'granularAdminPermissions',
|
||||||
|
);
|
||||||
|
|
||||||
const isProjectRole = PROJECT_ROLE_TYPES.includes(type);
|
const isProjectRole = PROJECT_ROLE_TYPES.includes(type);
|
||||||
|
|
||||||
@ -85,10 +88,15 @@ export const RolePermissionCategories = ({
|
|||||||
releasePlansEnabled ||
|
releasePlansEnabled ||
|
||||||
label !== 'Release plan templates',
|
label !== 'Release plan templates',
|
||||||
)
|
)
|
||||||
|
.filter(
|
||||||
|
({ label }) =>
|
||||||
|
granularAdminPermissionsEnabled ||
|
||||||
|
label !== 'Instance maintenance',
|
||||||
|
)
|
||||||
.map(({ label, type, permissions }) => (
|
.map(({ label, type, permissions }) => (
|
||||||
<RolePermissionCategory
|
<RolePermissionCategory
|
||||||
key={label}
|
key={label}
|
||||||
title={`${label} permissions`}
|
title={label}
|
||||||
context={label.toLowerCase()}
|
context={label.toLowerCase()}
|
||||||
Icon={
|
Icon={
|
||||||
type === PROJECT_PERMISSION_TYPE ? (
|
type === PROJECT_PERMISSION_TYPE ? (
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
} from './useAuthEndpoint';
|
} from './useAuthEndpoint';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import type { IUiConfig } from 'interfaces/uiConfig';
|
import type { IUiConfig } from 'interfaces/uiConfig';
|
||||||
|
import { MAINTENANCE_MODE_PERMISSIONS } from '@server/types/permissions';
|
||||||
|
|
||||||
interface IUseAuthPermissionsOutput {
|
interface IUseAuthPermissionsOutput {
|
||||||
permissions?: IPermission[];
|
permissions?: IPermission[];
|
||||||
@ -22,8 +23,8 @@ const getPermissions = (
|
|||||||
? auth.data.permissions
|
? auth.data.permissions
|
||||||
: undefined;
|
: undefined;
|
||||||
if (permissions && uiConfig?.maintenanceMode) {
|
if (permissions && uiConfig?.maintenanceMode) {
|
||||||
permissions = permissions.filter(
|
permissions = permissions.filter((permission) =>
|
||||||
(permission) => permission.permission === 'ADMIN',
|
MAINTENANCE_MODE_PERMISSIONS.includes(permission.permission),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return permissions;
|
return permissions;
|
||||||
|
@ -94,6 +94,7 @@ export type UiFlags = {
|
|||||||
showUserDeviceCount?: boolean;
|
showUserDeviceCount?: boolean;
|
||||||
flagOverviewRedesign?: boolean;
|
flagOverviewRedesign?: boolean;
|
||||||
licensedUsers?: boolean;
|
licensedUsers?: boolean;
|
||||||
|
granularAdminPermissions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IVersionInfo {
|
export interface IVersionInfo {
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { ADMIN, type IUnleashConfig, type IUnleashServices } from '../../types';
|
import {
|
||||||
|
ADMIN,
|
||||||
|
UPDATE_MAINTENANCE_MODE,
|
||||||
|
type IUnleashConfig,
|
||||||
|
type IUnleashServices,
|
||||||
|
} from '../../types';
|
||||||
import type { Request, Response } from 'express';
|
import type { Request, Response } from 'express';
|
||||||
import Controller from '../../routes/controller';
|
import Controller from '../../routes/controller';
|
||||||
import type { Logger } from '../../logger';
|
import type { Logger } from '../../logger';
|
||||||
@ -38,7 +43,7 @@ export default class MaintenanceController extends Controller {
|
|||||||
this.route({
|
this.route({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
path: '',
|
path: '',
|
||||||
permission: ADMIN,
|
permission: [ADMIN, UPDATE_MAINTENANCE_MODE],
|
||||||
handler: this.toggleMaintenance,
|
handler: this.toggleMaintenance,
|
||||||
middleware: [
|
middleware: [
|
||||||
this.openApiService.validPath({
|
this.openApiService.validPath({
|
||||||
@ -58,7 +63,7 @@ export default class MaintenanceController extends Controller {
|
|||||||
this.route({
|
this.route({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
path: '',
|
path: '',
|
||||||
permission: ADMIN,
|
permission: [ADMIN, UPDATE_MAINTENANCE_MODE],
|
||||||
handler: this.getMaintenance,
|
handler: this.getMaintenance,
|
||||||
middleware: [
|
middleware: [
|
||||||
this.openApiService.validPath({
|
this.openApiService.validPath({
|
||||||
|
@ -60,6 +60,7 @@ export type IFlagKey =
|
|||||||
| 'deleteStaleUserSessions'
|
| 'deleteStaleUserSessions'
|
||||||
| 'memorizeStats'
|
| 'memorizeStats'
|
||||||
| 'licensedUsers'
|
| 'licensedUsers'
|
||||||
|
| 'granularAdminPermissions'
|
||||||
| 'streaming'
|
| 'streaming'
|
||||||
| 'etagVariant'
|
| 'etagVariant'
|
||||||
| 'oidcRedirect';
|
| 'oidcRedirect';
|
||||||
@ -282,6 +283,10 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_FLAG_LICENSED_USERS,
|
process.env.UNLEASH_EXPERIMENTAL_FLAG_LICENSED_USERS,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
granularAdminPermissions: parseEnvVarBoolean(
|
||||||
|
process.env.UNLEASH_EXPERIMENTAL_GRANULAR_ADMIN_PERMISSIONS,
|
||||||
|
false,
|
||||||
|
),
|
||||||
streaming: parseEnvVarBoolean(
|
streaming: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_STREAMING,
|
process.env.UNLEASH_EXPERIMENTAL_STREAMING,
|
||||||
false,
|
false,
|
||||||
|
@ -41,6 +41,9 @@ export const CREATE_TAG_TYPE = 'CREATE_TAG_TYPE';
|
|||||||
export const UPDATE_TAG_TYPE = 'UPDATE_TAG_TYPE';
|
export const UPDATE_TAG_TYPE = 'UPDATE_TAG_TYPE';
|
||||||
export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
|
export const DELETE_TAG_TYPE = 'DELETE_TAG_TYPE';
|
||||||
|
|
||||||
|
export const UPDATE_MAINTENANCE_MODE = 'UPDATE_MAINTENANCE_MODE';
|
||||||
|
export const UPDATE_INSTANCE_BANNERS = 'UPDATE_INSTANCE_BANNERS';
|
||||||
|
|
||||||
// Project
|
// Project
|
||||||
export const CREATE_FEATURE = 'CREATE_FEATURE';
|
export const CREATE_FEATURE = 'CREATE_FEATURE';
|
||||||
export const UPDATE_FEATURE = 'UPDATE_FEATURE';
|
export const UPDATE_FEATURE = 'UPDATE_FEATURE';
|
||||||
@ -83,7 +86,7 @@ export const RELEASE_PLAN_TEMPLATE_DELETE = 'RELEASE_PLAN_TEMPLATE_DELETE';
|
|||||||
|
|
||||||
export const ROOT_PERMISSION_CATEGORIES = [
|
export const ROOT_PERMISSION_CATEGORIES = [
|
||||||
{
|
{
|
||||||
label: 'Addon',
|
label: 'Integration',
|
||||||
permissions: [CREATE_ADDON, UPDATE_ADDON, DELETE_ADDON],
|
permissions: [CREATE_ADDON, UPDATE_ADDON, DELETE_ADDON],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -141,4 +144,17 @@ export const ROOT_PERMISSION_CATEGORIES = [
|
|||||||
RELEASE_PLAN_TEMPLATE_UPDATE,
|
RELEASE_PLAN_TEMPLATE_UPDATE,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Instance maintenance',
|
||||||
|
permissions: [UPDATE_MAINTENANCE_MODE, UPDATE_INSTANCE_BANNERS],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Used on Frontend, to allow admin panel use for users with custom root roles
|
||||||
|
export const MAINTENANCE_MODE_PERMISSIONS = [
|
||||||
|
ADMIN,
|
||||||
|
READ_ROLE,
|
||||||
|
READ_CLIENT_API_TOKEN,
|
||||||
|
READ_FRONTEND_API_TOKEN,
|
||||||
|
UPDATE_MAINTENANCE_MODE,
|
||||||
];
|
];
|
||||||
|
@ -57,6 +57,7 @@ process.nextTick(async () => {
|
|||||||
showUserDeviceCount: true,
|
showUserDeviceCount: true,
|
||||||
flagOverviewRedesign: false,
|
flagOverviewRedesign: false,
|
||||||
licensedUsers: true,
|
licensedUsers: true,
|
||||||
|
granularAdminPermissions: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authentication: {
|
authentication: {
|
||||||
|
Loading…
Reference in New Issue
Block a user