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

Further improvements to spaces role assignment tab #14

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2338e06
create spaces assigned role table
eokoneyo Jul 23, 2024
8872a5d
extend definition of roles that can be edited
eokoneyo Jul 26, 2024
bb69ad5
fix pluralization in select all button
eokoneyo Jul 26, 2024
73a0dd1
slight adjustments rendered items count
eokoneyo Jul 26, 2024
88a2c2d
fix text, and hide assign to space button when there are roles to assign
eokoneyo Jul 31, 2024
4b76e01
integrate security packages
eokoneyo Aug 1, 2024
9cbf1ec
add tests for provisioning privilege API client
eokoneyo Aug 2, 2024
8f2f38d
even more UI improvements
eokoneyo Aug 12, 2024
1bc6528
refactor trigger for flyout and integrate it with bulk actions
eokoneyo Aug 13, 2024
63035a7
make accomodation for edit existing record
eokoneyo Aug 13, 2024
9541fc4
integrate API to update roles, leverage this to update existing space…
eokoneyo Aug 13, 2024
ee5e218
add logic to handle removing roles from space
eokoneyo Aug 14, 2024
c13613e
refactor implementation to provide visual feedback on UI actions
eokoneyo Aug 15, 2024
a50eade
fix logic for excluding roles already ppart of space
eokoneyo Aug 15, 2024
ad1e526
fix logic with selectable items
eokoneyo Aug 15, 2024
f51800b
add implementation for assigning custom roles privileges
eokoneyo Aug 15, 2024
8be8076
refactor logic for selecting role cutomization anchor
eokoneyo Aug 19, 2024
e91dff4
UI cleanup
eokoneyo Aug 21, 2024
1b7d516
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 23, 2024
7f5cff9
fix failing tests
eokoneyo Aug 26, 2024
27b1428
UI tweaks
eokoneyo Aug 26, 2024
3fb9d8e
add tests for view space provider
eokoneyo Aug 26, 2024
f18eba3
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Aug 27, 2024
d29d066
add tests for space assign role privilege form
eokoneyo Aug 26, 2024
7579ac5
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Aug 27, 2024
18c0d83
pass appropriate types to component
eokoneyo Aug 27, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface PrivilegesAPIClientGetAllArgs {
*/
respectLicenseLevel: boolean;
}
// TODO: Eyo include the proper return types for contract

export abstract class PrivilegesAPIClientPublicContract {
abstract getAll(args: PrivilegesAPIClientGetAllArgs): Promise<RawKibanaPrivileges>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export interface RolesAPIClient {
getRole: (roleName: string) => Promise<Role>;
deleteRole: (roleName: string) => Promise<void>;
saveRole: (payload: RolePutPayload) => Promise<void>;
bulkUpdateRoles: (payload: { rolesUpdate: Role[] }) => Promise<void>;
}
2 changes: 1 addition & 1 deletion x-pack/packages/security/plugin_types_public/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
"@kbn/core-user-profile-common",
"@kbn/security-plugin-types-common",
"@kbn/core-security-common",
"@kbn/security-authorization-core"
"@kbn/security-authorization-core",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
kibanaFeatures,
} from '@kbn/security-role-management-model/src/__fixtures__';
import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers';
import type { Role } from '@kbn/security-plugin-types-common';

import { getDisplayedFeaturePrivileges } from './__fixtures__';
import { FeatureTable } from './feature_table';
import type { Role } from '@kbn/security-plugin-types-common';
import { PrivilegeFormCalculator } from '../privilege_form_calculator';

const createRole = (kibana: Role['kibana'] = []): Role => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import {
createKibanaPrivileges,
kibanaFeatures,
} from '@kbn/security-role-management-model/src/__fixtures__';
import type { Role } from '@kbn/security-plugin-types-common';
import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers';

import { FeatureTableExpandedRow } from './feature_table_expanded_row';
import type { Role } from '@kbn/security-plugin-types-common';
import { PrivilegeFormCalculator } from '../privilege_form_calculator';

const createRole = (kibana: Role['kibana'] = []): Role => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import type {
SubFeaturePrivilege,
SubFeaturePrivilegeGroup,
} from '@kbn/security-role-management-model';

import { NO_PRIVILEGE_VALUE } from '../constants';
import type { PrivilegeFormCalculator } from '../privilege_form_calculator';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
createKibanaPrivileges,
kibanaFeatures,
} from '@kbn/security-role-management-model/src/__fixtures__';
import type { Role } from '@kbn/security-plugin-types-common';

import { PrivilegeFormCalculator } from './privilege_form_calculator';
import type { Role } from '@kbn/security-plugin-types-common';

const createRole = (kibana: Role['kibana'] = []): Role => {
return {
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/security/public/authentication/index.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const authorizationMock = {
getRole: jest.fn(),
deleteRole: jest.fn(),
saveRole: jest.fn(),
bulkUpdateRoles: jest.fn(),
},
privileges: {
getAll: jest.fn(),
Expand All @@ -43,6 +44,7 @@ export const authorizationMock = {
getRole: jest.fn(),
deleteRole: jest.fn(),
saveRole: jest.fn(),
bulkUpdateRoles: jest.fn(),
},
privileges: {
getAll: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class AuthorizationService {
getRole: rolesAPIClient.getRole,
deleteRole: rolesAPIClient.deleteRole,
saveRole: rolesAPIClient.saveRole,
bulkUpdateRoles: rolesAPIClient.bulkUpdateRoles,
},
privileges: {
getAll: privilegesAPIClient.getAll.bind(privilegesAPIClient),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export const rolesAPIClientMock = {
getRole: jest.fn(),
deleteRole: jest.fn(),
saveRole: jest.fn(),
bulkUpdateRoles: jest.fn(),
}),
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ export class RolesAPIClient {
});
};

public bulkUpdateRoles = async ({ rolesUpdate }: { rolesUpdate: Role[] }) => {
await this.http.post('/api/security/roles', {
body: JSON.stringify({
roles: rolesUpdate.reduce((transformed, value) => {
transformed[value.name] = this.transformRoleForSave(copyRole(value));
return transformed;
}, {} as Record<string, ReturnType<typeof this.transformRoleForSave>>),
}),
});
};

private transformRoleForSave = (role: Role) => {
// Remove any placeholder index privileges
const isPlaceholderPrivilege = (
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/security/public/plugin.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ describe('Security Plugin', () => {
"getAll": [Function],
},
"roles": Object {
"bulkUpdateRoles": [Function],
"deleteRole": [Function],
"getRole": [Function],
"getRoles": [Function],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { PrivilegesAPIClientPublicContract } from '@kbn/security-plugin-types-public';

export const createPrivilegeAPIClientMock = (): PrivilegesAPIClientPublicContract => {
return {
getAll: jest.fn(),
};
};

export const getPrivilegeAPIClientMock = jest
.fn()
.mockResolvedValue(createPrivilegeAPIClientMock());
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const createRolesAPIClientMock = (): RolesAPIClient => {
getRole: jest.fn(),
saveRole: jest.fn(),
deleteRole: jest.fn(),
bulkUpdateRoles: jest.fn(),
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ describe('spacesManagementApp', () => {
css="You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop)."
data-test-subj="kbnRedirectAppLink"
>
Spaces View Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"serverBasePath":"","http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"overlays":{"banners":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{}},"spaceId":"some-space","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/some-space","search":"","hash":""}},"allowFeatureVisibility":true,"allowSolutionVisibility":true}
Spaces View Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"serverBasePath":"","http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"overlays":{"banners":{}},"notifications":{"toasts":{}},"theme":{"theme$":{}},"i18n":{},"spacesManager":{"onActiveSpaceChange$":{}},"spaceId":"some-space","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/some-space","search":"","hash":""}},"allowFeatureVisibility":true,"allowSolutionVisibility":true}
</div>
</div>
`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const spacesManagementApp = Object.freeze({
config,
eventTracker,
getRolesAPIClient,
getPrivilegesAPIClient,
}: CreateParams) {
const title = i18n.translate('xpack.spaces.displayName', {
defaultMessage: 'Spaces',
Expand Down Expand Up @@ -71,7 +72,7 @@ export const spacesManagementApp = Object.freeze({
text: title,
href: `/`,
};
const { notifications, application, chrome, http, overlays } = coreStart;
const { notifications, application, chrome, http, overlays, theme } = coreStart;

chrome.docTitle.change(title);

Expand Down Expand Up @@ -147,6 +148,8 @@ export const spacesManagementApp = Object.freeze({
http={http}
overlays={overlays}
notifications={notifications}
theme={theme}
i18n={coreStart.i18n}
spacesManager={spacesManager}
spaceId={spaceId}
onLoadSpace={onLoadSpace}
Expand All @@ -155,6 +158,7 @@ export const spacesManagementApp = Object.freeze({
getRolesAPIClient={getRolesAPIClient}
allowFeatureVisibility={config.allowFeatureVisibility}
allowSolutionVisibility={config.allowSolutionVisibility}
getPrivilegesAPIClient={getPrivilegesAPIClient}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type { KibanaFeature } from '@kbn/features-plugin/public';
import type { Space } from '../../../../common';
import { getTabs, type GetTabsProps, type ViewSpaceTab } from '../view_space_tabs';

type UseTabsProps = Pick<GetTabsProps, 'roles' | 'capabilities'> & {
type UseTabsProps = Pick<GetTabsProps, 'capabilities' | 'rolesCount'> & {
space: Space | null;
features: KibanaFeature[] | null;
currentSelectedTabId: string;
Expand Down

This file was deleted.

40 changes: 40 additions & 0 deletions x-pack/plugins/spaces/public/management/view_space/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import type { ComponentProps, PropsWithChildren } from 'react';

import { ViewSpaceProvider, type ViewSpaceProviderProps } from './provider';
import { ViewSpace } from './view_space';

type ViewSpacePageProps = ComponentProps<typeof ViewSpace> & ViewSpaceProviderProps;

export function ViewSpacePage({
spaceId,
getFeatures,
history,
onLoadSpace,
selectedTabId,
allowFeatureVisibility,
allowSolutionVisibility,
children,
...viewSpaceServicesProps
}: PropsWithChildren<ViewSpacePageProps>) {
return (
<ViewSpaceProvider {...viewSpaceServicesProps}>
<ViewSpace
spaceId={spaceId}
getFeatures={getFeatures}
history={history}
onLoadSpace={onLoadSpace}
selectedTabId={selectedTabId}
allowFeatureVisibility={allowFeatureVisibility}
allowSolutionVisibility={allowSolutionVisibility}
/>
</ViewSpaceProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@
* 2.0.
*/

export { ViewSpacePage } from './view_space';
export { ViewSpaceProvider, useViewSpaceServices, useViewSpaceStore } from './view_space_provider';
export type {
ViewSpaceProviderProps,
ViewSpaceServices,
ViewSpaceStore,
} from './view_space_provider';
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { type Reducer } from 'react';

import type { Role } from '@kbn/security-plugin-types-common';

export type IDispatchAction =
| {
/** @description updates a single role record */
type: 'update_roles' | 'remove_roles';
payload: Role[];
}
| {
type: 'string';
payload: any;
};

export interface IViewSpaceStoreState {
/** roles assigned to current space */
roles: Map<Role['name'], Role>;
}

export const createSpaceRolesReducer: Reducer<IViewSpaceStoreState, IDispatchAction> = (
state,
action
) => {
const _state = structuredClone(state);

switch (action.type) {
case 'update_roles': {
action.payload.forEach((role) => {
_state.roles.set(role.name, role);
});

return _state;
}
case 'remove_roles': {
action.payload.forEach((role) => {
_state.roles.delete(role.name);
});

return _state;
}
default: {
return _state;
}
}
};
Loading
Loading