Skip to content

Commit

Permalink
prevent removing or modifying the last admin group, allow otherwise
Browse files Browse the repository at this point in the history
  • Loading branch information
t-aleksander committed Dec 16, 2024
1 parent 4dcc8d4 commit 01fdd32
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
24 changes: 22 additions & 2 deletions src/handlers/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,23 @@ pub(crate) async fn modify_group(
// TODO: update LDAP
}

if group.is_admin != group_info.is_admin && !group_info.is_admin {
// prevent removing admin permissions from the last admin group
let admin_groups_count = Group::find_by_permission(&appstate.pool, Permission::IsAdmin)
.await?
.len();
if admin_groups_count == 1 {
error!(
"Can't remove admin permissions from the last admin group: {}",
name
);
return Ok(ApiResponse {
json: json!({}),
status: StatusCode::BAD_REQUEST,
});
}
}

group
.set_permission(&mut *transaction, Permission::IsAdmin, group_info.is_admin)
.await?;
Expand Down Expand Up @@ -400,8 +417,11 @@ pub(crate) async fn delete_group(
debug!("Deleting group {name}");
// Administrative groups must not be removed.
// Note: Group names are unique, so this condition should be sufficient.
let admin_groups = Group::find_by_permission(&appstate.pool, Permission::IsAdmin).await?;
if admin_groups.iter().any(|group| group.name == name) {
let admin_group_count = Group::find_by_permission(&appstate.pool, Permission::IsAdmin)
.await?
.len();
if admin_group_count == 1 {
error!("Cannot delete the last admin group: {name}");
return Ok(ApiResponse {
json: json!({}),
status: StatusCode::BAD_REQUEST,
Expand Down
18 changes: 14 additions & 4 deletions web/src/pages/groups/components/GroupsList/GroupsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ export const GroupsList = ({ groups, search }: Props) => {
);
}, [groups, search]);

const renderRow = useCallback((data: ListData) => <CustomRow group={data} />, []);

const listHeaders = useMemo((): ListHeader[] => {
return [
{
Expand All @@ -60,6 +58,17 @@ export const GroupsList = ({ groups, search }: Props) => {
];
}, []);

const adminGroupCount = useCallback(() => {
return groups.filter((group) => group.is_admin).length;
}, [groups]);

const renderRow = useCallback(
(data: ListData) => (
<CustomRow group={data} disableDelete={adminGroupCount() === 1 && data.is_admin} />
),
[],

Check failure on line 69 in web/src/pages/groups/components/GroupsList/GroupsList.tsx

View workflow job for this annotation

GitHub Actions / lint-web

React Hook useCallback has a missing dependency: 'adminGroupCount'. Either include it or remove the dependency array
);

return (
<VirtualizedList
id="groups-list"
Expand All @@ -81,9 +90,10 @@ export const GroupsList = ({ groups, search }: Props) => {

type RowProps = {
group: GroupInfo;
disableDelete: boolean;
};

const CustomRow = ({ group }: RowProps) => {
const CustomRow = ({ group, disableDelete }: RowProps) => {
const openModal = useAddGroupModal((s) => s.open);
const [isDeleteModalOpen, setDeleteModalOpen] = useState(false);

Expand Down Expand Up @@ -142,7 +152,7 @@ const CustomRow = ({ group }: RowProps) => {
openModal(group);
}}
/>
{group.name.toLowerCase() !== 'admin' && (
{!disableDelete && (
<EditButtonOption
styleVariant={EditButtonOptionStyleVariant.WARNING}
text={LL.common.controls.delete()}
Expand Down

0 comments on commit 01fdd32

Please sign in to comment.