Skip to content

Commit

Permalink
Add check customization ability (#3258)
Browse files Browse the repository at this point in the history
* Add check customization ability

* Allow users with correct abilities to customize checks
  • Loading branch information
nelsonkopliku authored Jan 29, 2025
1 parent 5bd7448 commit e1090a7
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 26 deletions.
3 changes: 3 additions & 0 deletions assets/js/pages/ChecksSelection/ChecksSelection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ const getGroupSelectedState = (checks, selectedChecks) => {
};

const defaultSelectedChecks = [];
const defaultAbilities = [];

function ChecksSelection({
catalog,
selectedChecks = defaultSelectedChecks,
loading = false,
catalogError,
userAbilities = defaultAbilities,
onUpdateCatalog,
onChange,
}) {
Expand Down Expand Up @@ -85,6 +87,7 @@ function ChecksSelection({
name={check.name}
description={check.description}
selected={check.selected}
userAbilities={userAbilities}
customizable={check.customizable}
onChange={() => {
onChange(toggle(check.id, selectedChecks));
Expand Down
5 changes: 5 additions & 0 deletions assets/js/pages/ChecksSelection/ChecksSelection.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export default {
type: { summary: 'string' },
},
},
userAbilities: {
control: 'array',
description: 'Current user abilities',
},
onUpdateCatalog: {
action: 'Update catalog',
description: 'Gets called to refresh the catalog.',
Expand All @@ -69,6 +73,7 @@ export default {
export const Default = {
args: {
catalog,
userAbilities: [{ name: 'all', resource: 'check_customization' }],
},
};

Expand Down
12 changes: 11 additions & 1 deletion assets/js/pages/ChecksSelection/ChecksSelectionItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ import classNames from 'classnames';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

import { isPermitted } from '@lib/model/users';

const defaultAbilities = [];

const CUSTOMIZATION_ALLOWED_FOR = ['all:all', 'all:check_customization'];

const isCustomizable = (abilities, customizable) =>
isPermitted(abilities, CUSTOMIZATION_ALLOWED_FOR) && customizable;

function ChecksSelectionItem({
checkID,
name,
description,
customizable = false,
selected,
userAbilities = defaultAbilities,
onChange = () => {},
onCustomize = () => {},
}) {
Expand All @@ -34,7 +44,7 @@ function ChecksSelectionItem({
</ReactMarkdown>
</div>
<Switch.Group as="div" className="flex items-center">
{customizable && (
{isCustomizable(userAbilities, customizable) && (
<button
type="button"
onClick={() => {
Expand Down
68 changes: 43 additions & 25 deletions assets/js/pages/ChecksSelection/ChecksSelectionItem.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,33 +66,50 @@ describe('ChecksSelectionItem component', () => {
});

describe('Checks Customizability', () => {
it.each`
customizable
${true}
${false}
`('should show check customization call to action', ({ customizable }) => {
const check = catalogCheckFactory.build({ customizable });
const fooBarAbility = { name: 'foo', resource: 'bar' };
const allAbility = { name: 'all', resource: 'all' };
const checkCustomizationAbility = {
name: 'all',
resource: 'check_customization',
};

render(
<ChecksSelectionItem
key={check.id}
checkID={check.id}
name={check.name}
description={check.description}
selected
customizable={check.customizable}
/>
);

const customizationCallToAction =
screen.queryByLabelText('customize-check');

if (customizable) {
expect(customizationCallToAction).toBeVisible();
} else {
expect(customizationCallToAction).toBeNull();
it.each`
customizable | abilities | expectedCallToAction
${true} | ${[]} | ${false}
${true} | ${[fooBarAbility]} | ${false}
${true} | ${[allAbility, fooBarAbility]} | ${true}
${true} | ${[checkCustomizationAbility, fooBarAbility]} | ${true}
${false} | ${[]} | ${false}
${false} | ${[allAbility]} | ${false}
${false} | ${[checkCustomizationAbility]} | ${false}
${false} | ${[fooBarAbility]} | ${false}
`(
'should show check customization call to action',
({ customizable, abilities, expectedCallToAction }) => {
const check = catalogCheckFactory.build({ customizable });

render(
<ChecksSelectionItem
key={check.id}
checkID={check.id}
name={check.name}
description={check.description}
selected
userAbilities={abilities}
customizable={check.customizable}
/>
);

const customizationCallToAction =
screen.queryByLabelText('customize-check');

if (expectedCallToAction) {
expect(customizationCallToAction).toBeVisible();
} else {
expect(customizationCallToAction).toBeNull();
}
}
});
);

it('should run the onCustomize function when the customize button is clicked', async () => {
const user = userEvent.setup();
Expand All @@ -106,6 +123,7 @@ describe('Checks Customizability', () => {
name={check.name}
description={check.description}
selected
userAbilities={[checkCustomizationAbility]}
customizable={check.customizable}
onCustomize={onCustomize}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ function ClusterSettingsPage() {
catalogError={catalogError}
loading={catalogLoading}
selectedChecks={selection}
userAbilities={abilities}
onUpdateCatalog={refreshCatalog}
onChange={setSelection}
/>
Expand Down
1 change: 1 addition & 0 deletions assets/js/pages/HostSettingsPage/HostSettingsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ function HostSettingsPage() {
catalogError={catalogError}
loading={catalogLoading}
selectedChecks={selection}
userAbilities={abilities}
onUpdateCatalog={refreshCatalog}
onChange={setSelection}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Trento.Repo.Migrations.AddChecksCustomizationAbilities do
use Ecto.Migration

def up do
execute "INSERT INTO abilities(id, name, resource, label, inserted_at, updated_at) VALUES (DEFAULT, 'all', 'check_customization', 'Permits customizing checks values', NOW(), NOW())"
end

def down do
execute "DELETE FROM abilities WHERE name = 'all' and resource = 'check_customization'"
end
end

0 comments on commit e1090a7

Please sign in to comment.