From 2d43438e45e9f1bf6277165ead0c66f00aa5dc90 Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Wed, 27 Nov 2024 17:02:09 +0100
Subject: [PATCH 1/4] feat: maintenance root roles
---
.../features/maintenance/maintenance-controller.ts | 11 ++++++++---
src/lib/types/permissions.ts | 7 +++++++
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/lib/features/maintenance/maintenance-controller.ts b/src/lib/features/maintenance/maintenance-controller.ts
index bba95b8d5921..f7db299245a9 100644
--- a/src/lib/features/maintenance/maintenance-controller.ts
+++ b/src/lib/features/maintenance/maintenance-controller.ts
@@ -1,4 +1,9 @@
-import { ADMIN, type IUnleashConfig, type IUnleashServices } from '../../types';
+import {
+ NONE,
+ 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';
@@ -38,7 +43,7 @@ export default class MaintenanceController extends Controller {
this.route({
method: 'post',
path: '',
- permission: ADMIN,
+ permission: UPDATE_MAINTENANCE_MODE,
handler: this.toggleMaintenance,
middleware: [
this.openApiService.validPath({
@@ -58,7 +63,7 @@ export default class MaintenanceController extends Controller {
this.route({
method: 'get',
path: '',
- permission: ADMIN,
+ permission: NONE,
handler: this.getMaintenance,
middleware: [
this.openApiService.validPath({
diff --git a/src/lib/types/permissions.ts b/src/lib/types/permissions.ts
index 245526ca2b3e..06f89baec1d9 100644
--- a/src/lib/types/permissions.ts
+++ b/src/lib/types/permissions.ts
@@ -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';
@@ -141,4 +144,8 @@ export const ROOT_PERMISSION_CATEGORIES = [
RELEASE_PLAN_TEMPLATE_UPDATE,
],
},
+ {
+ label: 'Instance maintenance',
+ permissions: [UPDATE_MAINTENANCE_MODE, UPDATE_INSTANCE_BANNERS],
+ },
];
From 7a05ec6ba5f9878154eb4f6563069bf983344179 Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Thu, 28 Nov 2024 18:04:14 +0100
Subject: [PATCH 2/4] feat(cjux-278): gradual permissions for maintenance
---
frontend/src/component/admin/banners/Banners.tsx | 3 ++-
frontend/src/component/admin/maintenance/index.tsx | 3 ++-
.../RolePermissionCategories.tsx | 10 +++++++++-
.../hooks/api/getters/useAuth/useAuthPermissions.ts | 5 +++--
frontend/src/interfaces/uiConfig.ts | 1 +
src/lib/types/experimental.ts | 7 ++++++-
src/lib/types/permissions.ts | 11 ++++++++++-
src/server-dev.ts | 1 +
8 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/frontend/src/component/admin/banners/Banners.tsx b/frontend/src/component/admin/banners/Banners.tsx
index 9e4a2070a8df..db86315e1495 100644
--- a/frontend/src/component/admin/banners/Banners.tsx
+++ b/frontend/src/component/admin/banners/Banners.tsx
@@ -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();
@@ -13,7 +14,7 @@ export const Banners = () => {
return (
diff --git a/frontend/src/component/admin/maintenance/index.tsx b/frontend/src/component/admin/maintenance/index.tsx
index 505dd10e4963..9774adbc312e 100644
--- a/frontend/src/component/admin/maintenance/index.tsx
+++ b/frontend/src/component/admin/maintenance/index.tsx
@@ -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 = () => (
diff --git a/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx b/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx
index 0fbe05ea7967..d8097bc22a25 100644
--- a/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx
+++ b/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx
@@ -42,6 +42,9 @@ export const RolePermissionCategories = ({
});
const releasePlansEnabled = useUiFlag('releasePlans');
+ const granularAdminPermissionsEnabled = useUiFlag(
+ 'granularAdminPermissions',
+ );
const isProjectRole = PROJECT_ROLE_TYPES.includes(type);
@@ -85,10 +88,15 @@ export const RolePermissionCategories = ({
releasePlansEnabled ||
label !== 'Release plan templates',
)
+ .filter(
+ ({ label }) =>
+ granularAdminPermissionsEnabled ||
+ label !== 'Instance maintenance',
+ )
.map(({ label, type, permissions }) => (
permission.permission === 'ADMIN',
+ permissions = permissions.filter((permission) =>
+ MAINTENANCE_MODE_PERMISSIONS.includes(permission.permission),
);
}
return permissions;
diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts
index 19263be2b3e2..b135df6b0219 100644
--- a/frontend/src/interfaces/uiConfig.ts
+++ b/frontend/src/interfaces/uiConfig.ts
@@ -94,6 +94,7 @@ export type UiFlags = {
showUserDeviceCount?: boolean;
flagOverviewRedesign?: boolean;
licensedUsers?: boolean;
+ granularAdminPermissions?: boolean;
};
export interface IVersionInfo {
diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts
index 4bea097ec534..39f5e0bf73a4 100644
--- a/src/lib/types/experimental.ts
+++ b/src/lib/types/experimental.ts
@@ -61,7 +61,8 @@ export type IFlagKey =
| 'memorizeStats'
| 'licensedUsers'
| 'streaming'
- | 'etagVariant';
+ | 'etagVariant'
+ | 'granularAdminPermissions';
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
@@ -290,6 +291,10 @@ const flags: IFlags = {
feature_enabled: false,
enabled: false,
},
+ granularAdminPermissions: parseEnvVarBoolean(
+ process.env.UNLEASH_EXPERIMENTAL_GRANULAR_ADMIN_PERMISSIONS,
+ false,
+ ),
};
export const defaultExperimentalOptions: IExperimentalOptions = {
diff --git a/src/lib/types/permissions.ts b/src/lib/types/permissions.ts
index 06f89baec1d9..2ce1d977a011 100644
--- a/src/lib/types/permissions.ts
+++ b/src/lib/types/permissions.ts
@@ -86,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],
},
{
@@ -149,3 +149,12 @@ export const ROOT_PERMISSION_CATEGORIES = [
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,
+];
diff --git a/src/server-dev.ts b/src/server-dev.ts
index 1b0d7b0eb7e5..d4b7e36deb20 100644
--- a/src/server-dev.ts
+++ b/src/server-dev.ts
@@ -57,6 +57,7 @@ process.nextTick(async () => {
showUserDeviceCount: true,
flagOverviewRedesign: false,
licensedUsers: true,
+ granularAdminPermissions: true,
},
},
authentication: {
From a7716f1f40d3b3a6dd08fed8fa4c64b70d9a96ec Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Fri, 29 Nov 2024 13:09:54 +0100
Subject: [PATCH 3/4] update maintenance permissions
---
src/lib/features/maintenance/maintenance-controller.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lib/features/maintenance/maintenance-controller.ts b/src/lib/features/maintenance/maintenance-controller.ts
index f7db299245a9..71df5702ed0c 100644
--- a/src/lib/features/maintenance/maintenance-controller.ts
+++ b/src/lib/features/maintenance/maintenance-controller.ts
@@ -1,5 +1,5 @@
import {
- NONE,
+ ADMIN,
UPDATE_MAINTENANCE_MODE,
type IUnleashConfig,
type IUnleashServices,
@@ -43,7 +43,7 @@ export default class MaintenanceController extends Controller {
this.route({
method: 'post',
path: '',
- permission: UPDATE_MAINTENANCE_MODE,
+ permission: [ADMIN, UPDATE_MAINTENANCE_MODE],
handler: this.toggleMaintenance,
middleware: [
this.openApiService.validPath({
@@ -63,7 +63,7 @@ export default class MaintenanceController extends Controller {
this.route({
method: 'get',
path: '',
- permission: NONE,
+ permission: [ADMIN, UPDATE_MAINTENANCE_MODE],
handler: this.getMaintenance,
middleware: [
this.openApiService.validPath({
From ca25fb3aa4db632df0c2209816f654a70e9bba99 Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Mon, 9 Dec 2024 12:34:31 +0100
Subject: [PATCH 4/4] fix: typo
---
src/lib/types/experimental.ts | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts
index 39f5e0bf73a4..72cd6cffacb4 100644
--- a/src/lib/types/experimental.ts
+++ b/src/lib/types/experimental.ts
@@ -60,9 +60,9 @@ export type IFlagKey =
| 'deleteStaleUserSessions'
| 'memorizeStats'
| 'licensedUsers'
+ | 'granularAdminPermissions'
| 'streaming'
- | 'etagVariant'
- | 'granularAdminPermissions';
+ | 'etagVariant';
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
@@ -282,6 +282,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,
@@ -291,10 +295,6 @@ const flags: IFlags = {
feature_enabled: false,
enabled: false,
},
- granularAdminPermissions: parseEnvVarBoolean(
- process.env.UNLEASH_EXPERIMENTAL_GRANULAR_ADMIN_PERMISSIONS,
- false,
- ),
};
export const defaultExperimentalOptions: IExperimentalOptions = {