Skip to content

Commit

Permalink
feat(cjux-278): maintenance root roles (#8875)
Browse files Browse the repository at this point in the history
Custom root roles for changing maintenance mode state and banners.

Internal ticket: CJUX-278
  • Loading branch information
Tymek authored Dec 10, 2024
1 parent c860d8e commit 5cc0e58
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 9 deletions.
3 changes: 2 additions & 1 deletion frontend/src/component/admin/banners/Banners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuar
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
import { BannersTable } from './BannersTable/BannersTable';
import { UPDATE_INSTANCE_BANNERS } from '@server/types/permissions';

export const Banners = () => {
const { isEnterprise } = useUiConfig();
Expand All @@ -13,7 +14,7 @@ export const Banners = () => {

return (
<div>
<PermissionGuard permissions={ADMIN}>
<PermissionGuard permissions={[ADMIN, UPDATE_INSTANCE_BANNERS]}>
<BannersTable />
</PermissionGuard>
</div>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/component/admin/maintenance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { Box, styled } from '@mui/material';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { MaintenanceTooltip } from './MaintenanceTooltip';
import { MaintenanceToggle } from './MaintenanceToggle';
import { UPDATE_MAINTENANCE_MODE } from '@server/types/permissions';

export const MaintenanceAdmin = () => (
<div>
<PermissionGuard permissions={ADMIN}>
<PermissionGuard permissions={[ADMIN, UPDATE_MAINTENANCE_MODE]}>
<MaintenancePage />
</PermissionGuard>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export const RolePermissionCategories = ({
});

const releasePlansEnabled = useUiFlag('releasePlans');
const granularAdminPermissionsEnabled = useUiFlag(
'granularAdminPermissions',
);

const isProjectRole = PROJECT_ROLE_TYPES.includes(type);

Expand Down Expand Up @@ -85,10 +88,15 @@ export const RolePermissionCategories = ({
releasePlansEnabled ||
label !== 'Release plan templates',
)
.filter(
({ label }) =>
granularAdminPermissionsEnabled ||
label !== 'Instance maintenance',
)
.map(({ label, type, permissions }) => (
<RolePermissionCategory
key={label}
title={`${label} permissions`}
title={label}
context={label.toLowerCase()}
Icon={
type === PROJECT_PERMISSION_TYPE ? (
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/hooks/api/getters/useAuth/useAuthPermissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from './useAuthEndpoint';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import type { IUiConfig } from 'interfaces/uiConfig';
import { MAINTENANCE_MODE_PERMISSIONS } from '@server/types/permissions';

interface IUseAuthPermissionsOutput {
permissions?: IPermission[];
Expand All @@ -22,8 +23,8 @@ const getPermissions = (
? auth.data.permissions
: undefined;
if (permissions && uiConfig?.maintenanceMode) {
permissions = permissions.filter(
(permission) => permission.permission === 'ADMIN',
permissions = permissions.filter((permission) =>
MAINTENANCE_MODE_PERMISSIONS.includes(permission.permission),
);
}
return permissions;
Expand Down
1 change: 1 addition & 0 deletions frontend/src/interfaces/uiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export type UiFlags = {
showUserDeviceCount?: boolean;
flagOverviewRedesign?: boolean;
licensedUsers?: boolean;
granularAdminPermissions?: boolean;
};

export interface IVersionInfo {
Expand Down
11 changes: 8 additions & 3 deletions src/lib/features/maintenance/maintenance-controller.ts
Original file line number Diff line number Diff line change
@@ -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 Controller from '../../routes/controller';
import type { Logger } from '../../logger';
Expand Down Expand Up @@ -38,7 +43,7 @@ export default class MaintenanceController extends Controller {
this.route({
method: 'post',
path: '',
permission: ADMIN,
permission: [ADMIN, UPDATE_MAINTENANCE_MODE],
handler: this.toggleMaintenance,
middleware: [
this.openApiService.validPath({
Expand All @@ -58,7 +63,7 @@ export default class MaintenanceController extends Controller {
this.route({
method: 'get',
path: '',
permission: ADMIN,
permission: [ADMIN, UPDATE_MAINTENANCE_MODE],
handler: this.getMaintenance,
middleware: [
this.openApiService.validPath({
Expand Down
5 changes: 5 additions & 0 deletions src/lib/types/experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export type IFlagKey =
| 'deleteStaleUserSessions'
| 'memorizeStats'
| 'licensedUsers'
| 'granularAdminPermissions'
| 'streaming'
| 'etagVariant'
| 'oidcRedirect';
Expand Down Expand Up @@ -282,6 +283,10 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_FLAG_LICENSED_USERS,
false,
),
granularAdminPermissions: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_GRANULAR_ADMIN_PERMISSIONS,
false,
),
streaming: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_STREAMING,
false,
Expand Down
18 changes: 17 additions & 1 deletion src/lib/types/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export const CREATE_TAG_TYPE = 'CREATE_TAG_TYPE';
export const UPDATE_TAG_TYPE = 'UPDATE_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
export const CREATE_FEATURE = 'CREATE_FEATURE';
export const UPDATE_FEATURE = 'UPDATE_FEATURE';
Expand Down Expand Up @@ -83,7 +86,7 @@ export const RELEASE_PLAN_TEMPLATE_DELETE = 'RELEASE_PLAN_TEMPLATE_DELETE';

export const ROOT_PERMISSION_CATEGORIES = [
{
label: 'Addon',
label: 'Integration',
permissions: [CREATE_ADDON, UPDATE_ADDON, DELETE_ADDON],
},
{
Expand Down Expand Up @@ -141,4 +144,17 @@ export const ROOT_PERMISSION_CATEGORIES = [
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,
];
1 change: 1 addition & 0 deletions src/server-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ process.nextTick(async () => {
showUserDeviceCount: true,
flagOverviewRedesign: false,
licensedUsers: true,
granularAdminPermissions: true,
},
},
authentication: {
Expand Down

0 comments on commit 5cc0e58

Please sign in to comment.