Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: access manager #2492

Open
wants to merge 4 commits into
base: feat/access-manager-role
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "1.7.10-beta-3",
"@devtron-labs/devtron-fe-common-lib": "1.7.10-beta-4",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rjsf/core": "^5.13.3",
"@rjsf/utils": "^5.13.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
PermissionConfigurationForm,
usePermissionConfiguration,
} from '../../Shared/components/PermissionConfigurationForm'
import { getIsSuperAdminPermission, getRoleFilters, validateDirectPermissionForm } from '../../utils'
import { getIsSuperAdminPermission, getRolesAndAccessRoles, validateDirectPermissionForm } from '../../utils'
import { excludeKeyAndClusterValue } from '../../Shared/components/K8sObjectPermissions/utils'
import { DeleteUserPermission } from '../../UserPermissions/DeleteUserPermission'

Expand Down Expand Up @@ -104,7 +104,7 @@ const PermissionGroupForm = ({ isAddMode }: { isAddMode: boolean }) => {
}
setSubmitting(true)

const { roleFilters, accessRoleFilters } = getRoleFilters({
const { roleFilters, accessRoleFilters } = getRolesAndAccessRoles({
k8sPermission,
directPermission,
serverMode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,36 @@ import {
SelectAllDialogStatus,
BulkSelectionProvider,
BulkSelectionIdentifiersType,
Icon,
} from '@devtron-labs/devtron-fe-common-lib'

import { getPermissionGroupList } from '../../authorization.service'
import { SortableKeys } from './constants'
import { PermissionGroup } from '../../types'
import PermissionGroupContainer from './PermissionGroupContainer'
import { BulkSelectionModalConfig, BulkSelectionModalTypes } from '../../Shared/components/BulkSelection'
import { PermissionGroupRowProps } from './types'

export const PermissionGroupIcon = ({
hasSuperAdminPermission,
hasAccessManagerPermission,
}: Pick<PermissionGroupRowProps, 'hasSuperAdminPermission' | 'hasAccessManagerPermission'>) => {
if (!(hasAccessManagerPermission || hasAccessManagerPermission)) {
return null
}
return (
<Icon
name={hasSuperAdminPermission ? 'ic-crown' : 'ic-user-key'}
tooltipProps={{
content: hasSuperAdminPermission
? 'Group contains super admin permissions'
: 'Group contains access manager permissions',
alwaysShowTippyOnHover: true,
placement: 'right',
}}
color={null}
/>
)
}

const PermissionGroupList = () => {
const [bulkSelectionModalConfig, setBulkSelectionModalConfig] = useState<BulkSelectionModalConfig>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ import {
import { Link, useRouteMatch } from 'react-router-dom'
import { ReactComponent as Edit } from '@Icons/ic-pencil.svg'
import { ReactComponent as Trash } from '@Icons/ic-delete-interactive.svg'

import { PermissionGroupRowProps } from './types'
import { deletePermissionGroup } from '../../authorization.service'
import { useAuthorizationBulkSelection } from '../../Shared/components/BulkSelection'
import { DeleteUserPermission } from '../../UserPermissions/DeleteUserPermission'
import { getPermissionGroupIcon } from './utils'
import { PermissionGroupIcon } from './PermissionGroupList.component'

const PermissionGroupRow = ({
id,
Expand All @@ -45,7 +44,7 @@ const PermissionGroupRow = ({
isChecked = false,
toggleChecked,
showCheckbox,
superAdmin,
hasSuperAdminPermission,
hasAccessManagerPermission,
}: PermissionGroupRowProps) => {
const { path } = useRouteMatch()
Expand Down Expand Up @@ -104,7 +103,10 @@ const PermissionGroupRow = ({
{name}
</Link>
</span>
{getPermissionGroupIcon({ superAdmin, hasAccessManagerPermission })}
<PermissionGroupIcon
hasSuperAdminPermission={hasSuperAdminPermission}
hasAccessManagerPermission={hasAccessManagerPermission}
/>
</div>
<span className="dc__ellipsis-right">{description || '-'}</span>
<div className="flex dc__gap-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const PermissionGroupTable = ({
) : (
<>
<div className="fs-13 fw-4 lh-20 cn-9 flex-grow-1">
{permissionGroups.map((permissionGroup, index) => (
{permissionGroups.map(({ superAdmin, ...permissionGroup }, index) => (
<PermissionGroupRow
{...permissionGroup}
index={index}
Expand All @@ -86,6 +86,7 @@ const PermissionGroupTable = ({
isChecked={isBulkSelectionApplied || bulkSelectionState[permissionGroup.id]}
toggleChecked={toggleCheckForBulkSelection}
showCheckbox={isSomeRowChecked}
hasSuperAdminPermission={superAdmin}
/>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import { BulkSelectionModalConfig } from '../../Shared/components/BulkSelection'
import { PermissionGroup } from '../../types'
import { SortableKeys } from './constants'

export interface PermissionGroupRowProps extends PermissionGroup {
export interface PermissionGroupRowProps extends Omit<PermissionGroup, 'superAdmin'> {
index: number
refetchPermissionGroupList: () => void
isChecked: boolean
toggleChecked: (id: PermissionGroup['id']) => void
showCheckbox: boolean
hasSuperAdminPermission: boolean
}

export interface PermissionGroupListHeaderProps {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
ComponentSizeType,
SelectPickerOptionType,
} from '@devtron-labs/devtron-fe-common-lib'
import { getAllWorkflowsForAppNames } from '../../../../../../services/service'
import { getUserAccessAllWorkflows } from '@Pages/GlobalConfigurations/Authorization/authorization.service'
import { HELM_APP_UNASSIGNED_PROJECT, SELECT_ALL_VALUE } from '../../../../../../config'
import { allApplicationsOption, DirectPermissionFieldName } from './constants'
import { getWorkflowOptions } from '../../../utils'
Expand Down Expand Up @@ -66,9 +66,10 @@ const AppOrJobSelector = ({
const jobNames =
_permission.entityName.filter((option) => option.value !== SELECT_ALL_VALUE).map((app) => app.label) ??
[]
const {
result: { appIdWorkflowNamesMapping },
} = await getAllWorkflowsForAppNames(jobNames, abortControllerRef.current.signal)
const { appIdWorkflowNamesMapping } = await getUserAccessAllWorkflows({
appIds: jobNames,
options: { abortControllerRef },
})
const workflowOptions = getWorkflowOptions(appIdWorkflowNamesMapping)
abortControllerRef.current = null
setWorkflowList({ loading: false, options: workflowOptions })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
EntityTypes,
mapByKey,
DEFAULT_ENV,
stringComparatorBySortOrder,
ActionTypes,
} from '@devtron-labs/devtron-fe-common-lib'
import {
getUserAccessAllWorkflows,
Expand All @@ -38,7 +40,7 @@ import {
getUserAccessProjectFilteredApps,
getUserAccessProjectList,
} from '@Pages/GlobalConfigurations/Authorization/authorization.service'
import { ActionTypes, DEFAULT_ACCESS_TYPE_TO_ERROR_MAP } from '../../../constants'
import { DEFAULT_ACCESS_TYPE_TO_ERROR_MAP } from '../../../constants'
import { HELM_APP_UNASSIGNED_PROJECT, SELECT_ALL_VALUE, SERVER_MODE } from '../../../../../../config'
import K8sPermissions from '../K8sObjectPermissions/K8sPermissions.component'
import { apiGroupAll } from '../K8sObjectPermissions/utils'
Expand All @@ -62,7 +64,7 @@ import {
getRoleConfigForRoleFilter,
} from './utils'
import { getWorkflowOptions, validateDirectPermissionForm } from '../../../utils'
import { AppPermissionsDetailType, DirectPermissionRowProps } from './types'
import { AppPermissionsDetailType, DirectPermissionRowProps, EnvironmentsListType, ProjectsListType } from './types'
import { APIRoleFilter, ChartGroupPermissionsFilter, DirectPermissionsRoleFilter } from '../../../types'
import { getDefaultStatusAndTimeout } from '../../../libUtils'
import { JobList } from '../../../../../../components/Jobs/Types'
Expand Down Expand Up @@ -111,26 +113,36 @@ const AppPermissions = () => {
helmAppsProjectsMap,
jobsProjectsMap,
} = useMemo(() => {
const projectList = configData?.[0]
const projectList: ProjectsListType = {
[ACCESS_TYPE_MAP.DEVTRON_APPS]: configData?.[0]?.[ACCESS_TYPE_MAP.DEVTRON_APPS] ?? [],
[ACCESS_TYPE_MAP.HELM_APPS]: configData?.[0]?.[ACCESS_TYPE_MAP.HELM_APPS] ?? [],
[ACCESS_TYPE_MAP.JOBS]: configData?.[0][ACCESS_TYPE_MAP.JOBS] ?? [],
}

const envList: EnvironmentsListType = {
[ACCESS_TYPE_MAP.DEVTRON_APPS]: configData?.[1]?.[ACCESS_TYPE_MAP.DEVTRON_APPS] ?? [],
[ACCESS_TYPE_MAP.JOBS]: configData?.[1][ACCESS_TYPE_MAP.JOBS] ?? [],
}

return {
projectsList: projectList,
environmentsList: configData?.[1],
environmentsList: envList,
chartGroupsList: configData?.[2]?.groups ?? [],
devtronAppsProjectsMap: projectList?.[ACCESS_TYPE_MAP.DEVTRON_APPS]
? mapByKey(projectList[ACCESS_TYPE_MAP.DEVTRON_APPS], 'name')
: new Map(),
helmAppsProjectsMap: projectList?.[ACCESS_TYPE_MAP.HELM_APPS]
? mapByKey(projectList[ACCESS_TYPE_MAP.HELM_APPS], 'name')
: new Map(),
jobsProjectsMap: projectList?.[ACCESS_TYPE_MAP.JOBS]
? mapByKey(projectList[ACCESS_TYPE_MAP.JOBS], 'name')
: new Map(),
devtronAppsProjectsMap: mapByKey(projectList[ACCESS_TYPE_MAP.DEVTRON_APPS], 'name'),
helmAppsProjectsMap: mapByKey(projectList[ACCESS_TYPE_MAP.HELM_APPS], 'name'),
jobsProjectsMap: mapByKey(projectList[ACCESS_TYPE_MAP.JOBS], 'name'),
}
}, [configData])

const { environmentClusterOptions, envClustersList } = useMemo(() => {
const _envClustersList = configData?.[3] ?? []
const _envClustersList = (configData?.[3] ?? [])
.map((cluster) => ({
...cluster,
environments: (cluster.environments ?? []).sort((a, b) =>
stringComparatorBySortOrder(a.environmentName, b.environmentName),
),
}))
.sort((a, b) => stringComparatorBySortOrder(a.clusterName, b.clusterName))

return {
envClustersList: _envClustersList,
Expand All @@ -141,7 +153,7 @@ const AppPermissions = () => {
const _getEnvironmentOptions = (
entity: DirectPermissionRowProps['permission']['entity'],
accessType: DirectPermissionRowProps['permission']['accessType'],
) => getEnvironmentOptions(environmentsList[accessType], entity)
) => getEnvironmentOptions(environmentsList[accessType] || [], entity)

const appPermissionDetailConfig = getAppPermissionDetailConfig(path, serverMode)
const navLinksConfig = getNavLinksConfig(serverMode, superAdmin)
Expand Down Expand Up @@ -322,8 +334,7 @@ const AppPermissions = () => {
async function setAllWorkflows(jobOptions) {
const jobNames = jobOptions.filter((job) => job.value !== SELECT_ALL_VALUE).map((job) => job.label)
try {
const result = await getUserAccessAllWorkflows(jobNames)
const { appIdWorkflowNamesMapping } = result
const { appIdWorkflowNamesMapping } = await getUserAccessAllWorkflows(jobNames)

const workflowOptions = getWorkflowOptions(appIdWorkflowNamesMapping)
return [
Expand Down Expand Up @@ -377,7 +388,7 @@ const AppPermissions = () => {
}
return [
{ label: 'All environments', value: SELECT_ALL_VALUE },
...(environmentsList?.[ACCESS_TYPE_MAP.DEVTRON_APPS] || []).map((env) => ({
...(environmentsList[ACCESS_TYPE_MAP.DEVTRON_APPS] || []).map((env) => ({
label: env.environment_name,
value: env.environmentIdentifier,
})),
Expand Down Expand Up @@ -427,7 +438,7 @@ const AppPermissions = () => {
.split(',')
.map((directRole) => ({ value: directRole, label: directRole }))
}
const environmentListWithClusterCdActive = (environmentsList?.[ACCESS_TYPE_MAP.JOBS] || []).filter(
const environmentListWithClusterCdActive = (environmentsList[ACCESS_TYPE_MAP.JOBS] || []).filter(
(env) => env.isClusterCdActive,
)
return [
Expand Down Expand Up @@ -666,14 +677,14 @@ const AppPermissions = () => {
}
} else if (action === ReactSelectInputAction.selectOption) {
// check all environments
const environmentListWithClusterCdActive = (environmentsList?.[currentAccessType] || []).filter(
const environmentListWithClusterCdActive = (environmentsList[currentAccessType] || []).filter(
(env) => env.isClusterCdActive,
)
tempPermissions[index][name] = [
{ label: 'All environments', value: SELECT_ALL_VALUE },
...(tempPermissions[index].entity === EntityTypes.JOB
? environmentListWithClusterCdActive
: environmentsList?.[currentAccessType] || []
: environmentsList[currentAccessType] || []
).map((env) => ({
label: env.environment_name,
value: env.environmentIdentifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const DirectPermission = ({
const handleUpdateDirectPermissionRoleConfig = (updatedRoleConfig: UserRoleConfig) => {
const { baseRole, accessManagerRoles } = updatedRoleConfig
setDirectPermission((prevPermissions) => {
const tempPermissions = [...prevPermissions]
const tempPermissions = [...structuredClone(prevPermissions)]
tempPermissions[index].roleConfig = updatedRoleConfig

tempPermissions[index].roleConfigError = !baseRole && !accessManagerRoles.size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import {
UserRoleConfig,
} from '@devtron-labs/devtron-fe-common-lib'
import { useAuthorizationContext } from '../../../AuthorizationProvider'
import { JobRoleSelectorProps } from './types'
import { RoleSelectorProps } from './types'

const JobRoleSelector = ({ permission, handleUpdateDirectPermissionRoleConfig }: JobRoleSelectorProps) => {
const JobRoleSelector = ({ permission, handleUpdateDirectPermissionRoleConfig }: RoleSelectorProps) => {
const { customRoles } = useAuthorizationContext()
const { possibleJobRoles } = customRoles

Expand Down
Loading