From 7be41ef31480c3dcc9ed8cee70df0f248111e774 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Tue, 6 Jan 2026 11:26:04 +0200 Subject: [PATCH 1/6] Change: move copy_role to dedicated role files --- src/manage.h | 3 --- src/manage_roles.h | 3 +++ src/manage_sql.c | 58 ------------------------------------------ src/manage_sql_roles.c | 58 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/manage.h b/src/manage.h index 84db44f4e..e27d7f432 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2954,9 +2954,6 @@ delete_permissions_cache_for_user (user_t); int init_role_iterator (iterator_t *, get_data_t *); -int -copy_role (const char *, const char *, const char *, role_t *); - int create_role (const char *, const char *, const char *, role_t *); diff --git a/src/manage_roles.h b/src/manage_roles.h index 4b7cad299..fb7206ce0 100644 --- a/src/manage_roles.h +++ b/src/manage_roles.h @@ -19,4 +19,7 @@ trash_role_in_use (role_t); int role_in_use (role_t); +int +copy_role (const char *, const char *, const char *, role_t *); + #endif /* not _GVMD_MANAGE_ROLES_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index cf222bfa3..ebd86baed 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -35118,64 +35118,6 @@ clean_feed_role_permissions (const char *type, /* Roles. */ -/** - * @brief Create a role from an existing role. - * - * @param[in] name Name of new role. NULL to copy from existing. - * @param[in] comment Comment on new role. NULL to copy from existing. - * @param[in] role_id UUID of existing role. - * @param[out] new_role_return New role. - * - * @return 0 success, 1 role exists already, 2 failed to find existing - * role, 99 permission denied, -1 error. - */ -int -copy_role (const char *name, const char *comment, const char *role_id, - role_t *new_role_return) -{ - int ret; - role_t new_role, old_role; - - sql_begin_immediate (); - - if (acl_user_may ("create_role") == 0) - return 99; - - if (acl_role_can_super_everyone (role_id)) - return 99; - - ret = copy_resource_lock ("role", name, comment, role_id, NULL, 1, &new_role, - &old_role); - if (ret) - { - sql_rollback (); - return ret; - } - - sql ("INSERT INTO permissions" - " (uuid, owner, name, comment, resource_type, resource_uuid, resource," - " resource_location, subject_type, subject, subject_location," - " creation_time, modification_time)" - " SELECT make_uuid ()," - " (SELECT id FROM users WHERE users.uuid = '%s')," - " name, comment, resource_type," - " resource_uuid, resource, resource_location, subject_type, %llu," - " subject_location, m_now (), m_now ()" - " FROM permissions" - " WHERE subject_type = 'role'" - " AND subject = %llu" - " AND subject_location = " G_STRINGIFY (LOCATION_TABLE) - " AND (resource = 0 OR owner IS NULL);", - current_credentials.uuid, - new_role, - old_role); - - sql_commit (); - if (new_role_return) - *new_role_return = new_role; - return 0; -} - /** * @brief Create a role. * diff --git a/src/manage_sql_roles.c b/src/manage_sql_roles.c index 056c2491d..aa4f12025 100644 --- a/src/manage_sql_roles.c +++ b/src/manage_sql_roles.c @@ -51,3 +51,61 @@ manage_get_roles (GSList *log_config, const db_conn_info_t *database, return 0; } + +/** + * @brief Create a role from an existing role. + * + * @param[in] name Name of new role. NULL to copy from existing. + * @param[in] comment Comment on new role. NULL to copy from existing. + * @param[in] role_id UUID of existing role. + * @param[out] new_role_return New role. + * + * @return 0 success, 1 role exists already, 2 failed to find existing + * role, 99 permission denied, -1 error. + */ +int +copy_role (const char *name, const char *comment, const char *role_id, + role_t *new_role_return) +{ + int ret; + role_t new_role, old_role; + + sql_begin_immediate (); + + if (acl_user_may ("create_role") == 0) + return 99; + + if (acl_role_can_super_everyone (role_id)) + return 99; + + ret = copy_resource_lock ("role", name, comment, role_id, NULL, 1, &new_role, + &old_role); + if (ret) + { + sql_rollback (); + return ret; + } + + sql ("INSERT INTO permissions" + " (uuid, owner, name, comment, resource_type, resource_uuid, resource," + " resource_location, subject_type, subject, subject_location," + " creation_time, modification_time)" + " SELECT make_uuid ()," + " (SELECT id FROM users WHERE users.uuid = '%s')," + " name, comment, resource_type," + " resource_uuid, resource, resource_location, subject_type, %llu," + " subject_location, m_now (), m_now ()" + " FROM permissions" + " WHERE subject_type = 'role'" + " AND subject = %llu" + " AND subject_location = " G_STRINGIFY (LOCATION_TABLE) + " AND (resource = 0 OR owner IS NULL);", + current_credentials.uuid, + new_role, + old_role); + + sql_commit (); + if (new_role_return) + *new_role_return = new_role; + return 0; +} From 495fdfc02325917a8a643d223decf61038c2f2ff Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Tue, 6 Jan 2026 11:28:07 +0200 Subject: [PATCH 2/6] Change: move create_role to dedicated role files --- src/manage.h | 3 --- src/manage_roles.h | 3 +++ src/manage_sql.c | 61 ------------------------------------------ src/manage_sql_roles.c | 61 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/manage.h b/src/manage.h index e27d7f432..c58df0e20 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2954,9 +2954,6 @@ delete_permissions_cache_for_user (user_t); int init_role_iterator (iterator_t *, get_data_t *); -int -create_role (const char *, const char *, const char *, role_t *); - int delete_role (const char *, int); diff --git a/src/manage_roles.h b/src/manage_roles.h index fb7206ce0..2f3f9e2f7 100644 --- a/src/manage_roles.h +++ b/src/manage_roles.h @@ -22,4 +22,7 @@ role_in_use (role_t); int copy_role (const char *, const char *, const char *, role_t *); +int +create_role (const char *, const char *, const char *, role_t *); + #endif /* not _GVMD_MANAGE_ROLES_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index ebd86baed..6b2280d3f 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -35118,67 +35118,6 @@ clean_feed_role_permissions (const char *type, /* Roles. */ -/** - * @brief Create a role. - * - * @param[in] role_name Role name. - * @param[in] comment Comment on role. - * @param[in] users Users role applies to. - * @param[in] role Role return. - * - * @return 0 success, 1 role exists already, 2 failed to find user, 4 user - * name validation failed, 99 permission denied, -1 error. - */ -int -create_role (const char *role_name, const char *comment, const char *users, - role_t* role) -{ - int ret; - gchar *quoted_role_name, *quoted_comment; - - assert (current_credentials.uuid); - assert (role_name); - assert (role); - - sql_begin_immediate (); - - if (acl_user_may ("create_role") == 0) - { - sql_rollback (); - return 99; - } - - if (resource_with_name_exists (role_name, "role", 0)) - { - sql_rollback (); - return 1; - } - - quoted_role_name = sql_quote (role_name); - quoted_comment = comment ? sql_quote (comment) : g_strdup (""); - sql ("INSERT INTO roles" - " (uuid, name, owner, comment, creation_time, modification_time)" - " VALUES" - " (make_uuid (), '%s'," - " (SELECT id FROM users WHERE users.uuid = '%s')," - " '%s', m_now (), m_now ());", - quoted_role_name, - current_credentials.uuid, - quoted_comment); - g_free (quoted_comment); - g_free (quoted_role_name); - - *role = sql_last_insert_id (); - ret = add_users ("role", *role, users); - - if (ret) - sql_rollback (); - else - sql_commit (); - - return ret; -} - /** * @brief Return whether a role is predefined. * diff --git a/src/manage_sql_roles.c b/src/manage_sql_roles.c index aa4f12025..a7dc7901a 100644 --- a/src/manage_sql_roles.c +++ b/src/manage_sql_roles.c @@ -109,3 +109,64 @@ copy_role (const char *name, const char *comment, const char *role_id, *new_role_return = new_role; return 0; } + +/** + * @brief Create a role. + * + * @param[in] role_name Role name. + * @param[in] comment Comment on role. + * @param[in] users Users role applies to. + * @param[in] role Role return. + * + * @return 0 success, 1 role exists already, 2 failed to find user, 4 user + * name validation failed, 99 permission denied, -1 error. + */ +int +create_role (const char *role_name, const char *comment, const char *users, + role_t* role) +{ + int ret; + gchar *quoted_role_name, *quoted_comment; + + assert (current_credentials.uuid); + assert (role_name); + assert (role); + + sql_begin_immediate (); + + if (acl_user_may ("create_role") == 0) + { + sql_rollback (); + return 99; + } + + if (resource_with_name_exists (role_name, "role", 0)) + { + sql_rollback (); + return 1; + } + + quoted_role_name = sql_quote (role_name); + quoted_comment = comment ? sql_quote (comment) : g_strdup (""); + sql ("INSERT INTO roles" + " (uuid, name, owner, comment, creation_time, modification_time)" + " VALUES" + " (make_uuid (), '%s'," + " (SELECT id FROM users WHERE users.uuid = '%s')," + " '%s', m_now (), m_now ());", + quoted_role_name, + current_credentials.uuid, + quoted_comment); + g_free (quoted_comment); + g_free (quoted_role_name); + + *role = sql_last_insert_id (); + ret = add_users ("role", *role, users); + + if (ret) + sql_rollback (); + else + sql_commit (); + + return ret; +} From 272665d9334158b329edff429676228581f171cd Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Tue, 6 Jan 2026 11:41:57 +0200 Subject: [PATCH 3/6] Change: move predefined predicates to dedicated role files --- src/manage_sql.c | 49 +----------------------------------------- src/manage_sql_roles.c | 42 ++++++++++++++++++++++++++++++++++++ src/manage_sql_roles.h | 15 +++++++++++++ 3 files changed, 58 insertions(+), 48 deletions(-) create mode 100644 src/manage_sql_roles.h diff --git a/src/manage_sql.c b/src/manage_sql.c index 6b2280d3f..f02c5fa0b 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -50,6 +50,7 @@ #include "manage_sql_port_lists.h" #include "manage_sql_report_configs.h" #include "manage_sql_report_formats.h" +#include "manage_sql_roles.h" #include "manage_sql_tickets.h" #include "manage_sql_tls_certificates.h" #include "manage_acl.h" @@ -232,12 +233,6 @@ permission_subject (permission_t); static char * permission_subject_type (permission_t); -static int -role_is_predefined (role_t); - -static int -role_is_predefined_id (const char *); - static int report_counts_id_full (report_t, int *, int *, int *, int *, int *, int *, double *, const get_data_t*, const char* , @@ -35118,48 +35113,6 @@ clean_feed_role_permissions (const char *type, /* Roles. */ -/** - * @brief Return whether a role is predefined. - * - * @param[in] role Role. - * - * @return 1 if predefined, else 0. - */ -static int -role_is_predefined (role_t role) -{ - return sql_int ("SELECT COUNT (*) FROM roles" - " WHERE id = %llu" - " AND (uuid = '" ROLE_UUID_ADMIN "'" - " OR uuid = '" ROLE_UUID_GUEST "'" - " OR uuid = '" ROLE_UUID_MONITOR "'" - " OR uuid = '" ROLE_UUID_INFO "'" - " OR uuid = '" ROLE_UUID_USER "'" - " OR uuid = '" ROLE_UUID_SUPER_ADMIN "'" - " OR uuid = '" ROLE_UUID_OBSERVER "');", - role) - != 0; -} - -/** - * @brief Return whether a role is predefined. - * - * @param[in] uuid UUID of role. - * - * @return 1 if predefined, else 0. - */ -static int -role_is_predefined_id (const char *uuid) -{ - return uuid && ((strcmp (uuid, ROLE_UUID_ADMIN) == 0) - || (strcmp (uuid, ROLE_UUID_GUEST) == 0) - || (strcmp (uuid, ROLE_UUID_MONITOR) == 0) - || (strcmp (uuid, ROLE_UUID_INFO) == 0) - || (strcmp (uuid, ROLE_UUID_USER) == 0) - || (strcmp (uuid, ROLE_UUID_SUPER_ADMIN) == 0) - || (strcmp (uuid, ROLE_UUID_OBSERVER) == 0)); -} - /** * @brief Delete a role. * diff --git a/src/manage_sql_roles.c b/src/manage_sql_roles.c index a7dc7901a..d7464d3f8 100644 --- a/src/manage_sql_roles.c +++ b/src/manage_sql_roles.c @@ -170,3 +170,45 @@ create_role (const char *role_name, const char *comment, const char *users, return ret; } + +/** + * @brief Return whether a role is predefined. + * + * @param[in] role Role. + * + * @return 1 if predefined, else 0. + */ +int +role_is_predefined (role_t role) +{ + return sql_int ("SELECT COUNT (*) FROM roles" + " WHERE id = %llu" + " AND (uuid = '" ROLE_UUID_ADMIN "'" + " OR uuid = '" ROLE_UUID_GUEST "'" + " OR uuid = '" ROLE_UUID_MONITOR "'" + " OR uuid = '" ROLE_UUID_INFO "'" + " OR uuid = '" ROLE_UUID_USER "'" + " OR uuid = '" ROLE_UUID_SUPER_ADMIN "'" + " OR uuid = '" ROLE_UUID_OBSERVER "');", + role) + != 0; +} + +/** + * @brief Return whether a role is predefined. + * + * @param[in] uuid UUID of role. + * + * @return 1 if predefined, else 0. + */ +int +role_is_predefined_id (const char *uuid) +{ + return uuid && ((strcmp (uuid, ROLE_UUID_ADMIN) == 0) + || (strcmp (uuid, ROLE_UUID_GUEST) == 0) + || (strcmp (uuid, ROLE_UUID_MONITOR) == 0) + || (strcmp (uuid, ROLE_UUID_INFO) == 0) + || (strcmp (uuid, ROLE_UUID_USER) == 0) + || (strcmp (uuid, ROLE_UUID_SUPER_ADMIN) == 0) + || (strcmp (uuid, ROLE_UUID_OBSERVER) == 0)); +} diff --git a/src/manage_sql_roles.h b/src/manage_sql_roles.h new file mode 100644 index 000000000..0b23fdcb5 --- /dev/null +++ b/src/manage_sql_roles.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2026 Greenbone AG + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _GVMD_MANAGE_SQL_ROLES_H +#define _GVMD_MANAGE_SQL_ROLES_H + +int +role_is_predefined (role_t); + +int +role_is_predefined_id (const char *); + +#endif //_GVMD_MANAGE_SQL_ROLES_H From 358ce75a292db2b62acfd06fc35696a0b765a838 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Tue, 6 Jan 2026 11:58:01 +0200 Subject: [PATCH 4/6] Change: move find functions to dedicated role files --- src/manage_roles.h | 3 +++ src/manage_sql.c | 35 +---------------------------------- src/manage_sql.h | 5 ++++- src/manage_sql_roles.c | 31 +++++++++++++++++++++++++++++++ src/manage_sql_roles.h | 6 ++++++ 5 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/manage_roles.h b/src/manage_roles.h index 2f3f9e2f7..9632d597b 100644 --- a/src/manage_roles.h +++ b/src/manage_roles.h @@ -25,4 +25,7 @@ copy_role (const char *, const char *, const char *, role_t *); int create_role (const char *, const char *, const char *, role_t *); +gboolean +find_role_with_permission (const char *, role_t *, const char *); + #endif /* not _GVMD_MANAGE_ROLES_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index f02c5fa0b..2190ae53e 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -215,9 +215,6 @@ clean_hosts (const char *, int*); static gboolean find_user_by_name (const char *, user_t *user); -static gboolean -find_role_with_permission (const char *, role_t *, const char *); - static int user_ensure_in_db (const gchar *, const gchar *); @@ -944,7 +941,7 @@ find_resource_with_permission (const char* type, const char* uuid, * @return FALSE on success (including if failed to find resource), TRUE on * error. */ -static gboolean +gboolean find_resource_by_name (const char* type, const char* name, resource_t *resource) { gchar *quoted_name; @@ -35280,36 +35277,6 @@ delete_role (const char *role_id, int ultimate) return 0; } -/** - * @brief Find a role for a specific permission, given a UUID. - * - * @param[in] uuid UUID of role. - * @param[out] role Role return, 0 if successfully failed to find role. - * @param[in] permission Permission. - * - * @return FALSE on success (including if failed to find role), TRUE on error. - */ -static gboolean -find_role_with_permission (const char* uuid, role_t* role, - const char *permission) -{ - return find_resource_with_permission ("role", uuid, role, permission, 0); -} - -/** - * @brief Find a role given a name. - * - * @param[in] name A role name. - * @param[out] role Role return, 0 if successfully failed to find role. - * - * @return FALSE on success (including if failed to find role), TRUE on error. - */ -static gboolean -find_role_by_name (const char* name, role_t *role) -{ - return find_resource_by_name ("role", name, role); -} - /** * @brief Gets UUID of role. * diff --git a/src/manage_sql.h b/src/manage_sql.h index b108b790e..f35ce6995 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -362,7 +362,10 @@ resource_uuid (const gchar *, resource_t); gboolean find_resource_with_permission (const char *, const char *, - resource_t *, const char *, int); + resource_t *, const char *, int); + +gboolean +find_resource_by_name (const char *, const char *, resource_t *); int resource_predefined (const gchar *, resource_t); diff --git a/src/manage_sql_roles.c b/src/manage_sql_roles.c index d7464d3f8..32049f00d 100644 --- a/src/manage_sql_roles.c +++ b/src/manage_sql_roles.c @@ -4,6 +4,7 @@ */ #include "manage_roles.h" +#include "manage_sql_roles.h" #include "manage_acl.h" #include "manage_sql.h" #include "sql.h" @@ -212,3 +213,33 @@ role_is_predefined_id (const char *uuid) || (strcmp (uuid, ROLE_UUID_SUPER_ADMIN) == 0) || (strcmp (uuid, ROLE_UUID_OBSERVER) == 0)); } + +/** + * @brief Find a role for a specific permission, given a UUID. + * + * @param[in] uuid UUID of role. + * @param[out] role Role return, 0 if successfully failed to find role. + * @param[in] permission Permission. + * + * @return FALSE on success (including if failed to find role), TRUE on error. + */ +gboolean +find_role_with_permission (const char* uuid, role_t* role, + const char *permission) +{ + return find_resource_with_permission ("role", uuid, role, permission, 0); +} + +/** + * @brief Find a role given a name. + * + * @param[in] name A role name. + * @param[out] role Role return, 0 if successfully failed to find role. + * + * @return FALSE on success (including if failed to find role), TRUE on error. + */ +gboolean +find_role_by_name (const char* name, role_t *role) +{ + return find_resource_by_name ("role", name, role); +} diff --git a/src/manage_sql_roles.h b/src/manage_sql_roles.h index 0b23fdcb5..f1e549aaf 100644 --- a/src/manage_sql_roles.h +++ b/src/manage_sql_roles.h @@ -12,4 +12,10 @@ role_is_predefined (role_t); int role_is_predefined_id (const char *); +gboolean +find_role_with_permission (const char *, role_t *, const char *); + +gboolean +find_role_by_name (const char *, role_t *); + #endif //_GVMD_MANAGE_SQL_ROLES_H From ee98b5423114a4b4c297375541fbaf7901e206c1 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Tue, 6 Jan 2026 12:01:14 +0200 Subject: [PATCH 5/6] Change: move delete_role to dedicated role files --- src/manage.h | 3 - src/manage_roles.h | 3 + src/manage_sql.c | 167 ----------------------------------------- src/manage_sql_roles.c | 167 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 170 deletions(-) diff --git a/src/manage.h b/src/manage.h index c58df0e20..20bcadf3a 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2954,9 +2954,6 @@ delete_permissions_cache_for_user (user_t); int init_role_iterator (iterator_t *, get_data_t *); -int -delete_role (const char *, int); - char* role_uuid (role_t); diff --git a/src/manage_roles.h b/src/manage_roles.h index 9632d597b..ec1ff3fdf 100644 --- a/src/manage_roles.h +++ b/src/manage_roles.h @@ -28,4 +28,7 @@ create_role (const char *, const char *, const char *, role_t *); gboolean find_role_with_permission (const char *, role_t *, const char *); +int +delete_role (const char *, int); + #endif /* not _GVMD_MANAGE_ROLES_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index 2190ae53e..df9f8d92d 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -35110,173 +35110,6 @@ clean_feed_role_permissions (const char *type, /* Roles. */ -/** - * @brief Delete a role. - * - * @param[in] role_id UUID of role. - * @param[in] ultimate Whether to remove entirely, or to trashcan. - * - * @return 0 success, 1 fail because a task refers to the role, 2 failed - * to find role, 3 predefined role, -1 error. - */ -int -delete_role (const char *role_id, int ultimate) -{ - role_t role = 0; - GArray *affected_users; - iterator_t users_iter; - - sql_begin_immediate (); - - if (acl_user_may ("delete_role") == 0) - { - sql_rollback (); - return 99; - } - - if (find_role_with_permission (role_id, &role, "delete_role")) - { - sql_rollback (); - return -1; - } - - if (role == 0) - { - if (find_trash ("role", role_id, &role)) - { - sql_rollback (); - return -1; - } - if (role == 0) - { - sql_rollback (); - return 2; - } - if (ultimate == 0) - { - /* It's already in the trashcan. */ - sql_commit (); - return 0; - } - - if (trash_role_in_use (role)) - { - sql_rollback (); - return 1; - } - - sql ("DELETE FROM permissions" - " WHERE resource_type = 'role'" - " AND resource = %llu" - " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", - role); - sql ("DELETE FROM permissions_trash" - " WHERE resource_type = 'role'" - " AND resource = %llu" - " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", - role); - sql ("DELETE FROM permissions" - " WHERE subject_type = 'role'" - " AND subject = %llu" - " AND subject_location = " G_STRINGIFY (LOCATION_TRASH) ";", - role); - sql ("DELETE FROM permissions_trash" - " WHERE subject_type = 'role'" - " AND subject = %llu" - " AND subject_location = " G_STRINGIFY (LOCATION_TRASH) ";", - role); - - tags_remove_resource ("role", role, LOCATION_TRASH); - - sql ("DELETE FROM role_users_trash WHERE role = %llu;", role); - sql ("DELETE FROM roles_trash WHERE id = %llu;", role); - sql_commit (); - return 0; - } - - if (role_is_predefined (role)) - { - sql_rollback (); - return 3; - } - - if (role_in_use (role)) - { - sql_rollback (); - return 1; - } - - if (ultimate == 0) - { - role_t trash_role; - - sql ("INSERT INTO roles_trash" - " (uuid, owner, name, comment, creation_time, modification_time)" - " SELECT uuid, owner, name, comment, creation_time," - " modification_time" - " FROM roles WHERE id = %llu;", - role); - - trash_role = sql_last_insert_id (); - - sql ("INSERT INTO role_users_trash" - " (\"role\", \"user\")" - " SELECT %llu, \"user\"" - " FROM role_users WHERE \"role\" = %llu;", - trash_role, - role); - - permissions_set_locations ("role", role, trash_role, LOCATION_TRASH); - tags_set_locations ("role", role, trash_role, LOCATION_TRASH); - permissions_set_subjects ("role", role, trash_role, LOCATION_TRASH); - } - else - { - sql ("DELETE FROM permissions" - " WHERE resource_type = 'role'" - " AND resource = %llu" - " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", - role); - sql ("DELETE FROM permissions_trash" - " WHERE resource_type = 'role'" - " AND resource = %llu" - " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", - role); - sql ("DELETE FROM permissions" - " WHERE subject_type = 'role'" - " AND subject = %llu" - " AND subject_location = " G_STRINGIFY (LOCATION_TABLE) ";", - role); - sql ("DELETE FROM permissions_trash" - " WHERE subject_type = 'role'" - " AND subject = %llu" - " AND subject_location = " G_STRINGIFY (LOCATION_TABLE) ";", - role); - tags_remove_resource ("role", role, LOCATION_TABLE); - } - - affected_users = g_array_new (TRUE, TRUE, sizeof (user_t)); - init_iterator (&users_iter, - "SELECT \"user\" FROM role_users" - " WHERE \"role\" = %llu", - role); - while (next (&users_iter)) - { - user_t user = iterator_int64 (&users_iter, 0); - g_array_append_val (affected_users, user); - } - cleanup_iterator (&users_iter); - - sql ("DELETE FROM role_users WHERE \"role\" = %llu;", role); - sql ("DELETE FROM roles WHERE id = %llu;", role); - - cache_all_permissions_for_users (affected_users); - g_array_free (affected_users, TRUE); - - sql_commit (); - return 0; -} - /** * @brief Gets UUID of role. * diff --git a/src/manage_sql_roles.c b/src/manage_sql_roles.c index 32049f00d..23fca2be6 100644 --- a/src/manage_sql_roles.c +++ b/src/manage_sql_roles.c @@ -243,3 +243,170 @@ find_role_by_name (const char* name, role_t *role) { return find_resource_by_name ("role", name, role); } + +/** + * @brief Delete a role. + * + * @param[in] role_id UUID of role. + * @param[in] ultimate Whether to remove entirely, or to trashcan. + * + * @return 0 success, 1 fail because a task refers to the role, 2 failed + * to find role, 3 predefined role, -1 error. + */ +int +delete_role (const char *role_id, int ultimate) +{ + role_t role = 0; + GArray *affected_users; + iterator_t users_iter; + + sql_begin_immediate (); + + if (acl_user_may ("delete_role") == 0) + { + sql_rollback (); + return 99; + } + + if (find_role_with_permission (role_id, &role, "delete_role")) + { + sql_rollback (); + return -1; + } + + if (role == 0) + { + if (find_trash ("role", role_id, &role)) + { + sql_rollback (); + return -1; + } + if (role == 0) + { + sql_rollback (); + return 2; + } + if (ultimate == 0) + { + /* It's already in the trashcan. */ + sql_commit (); + return 0; + } + + if (trash_role_in_use (role)) + { + sql_rollback (); + return 1; + } + + sql ("DELETE FROM permissions" + " WHERE resource_type = 'role'" + " AND resource = %llu" + " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", + role); + sql ("DELETE FROM permissions_trash" + " WHERE resource_type = 'role'" + " AND resource = %llu" + " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", + role); + sql ("DELETE FROM permissions" + " WHERE subject_type = 'role'" + " AND subject = %llu" + " AND subject_location = " G_STRINGIFY (LOCATION_TRASH) ";", + role); + sql ("DELETE FROM permissions_trash" + " WHERE subject_type = 'role'" + " AND subject = %llu" + " AND subject_location = " G_STRINGIFY (LOCATION_TRASH) ";", + role); + + tags_remove_resource ("role", role, LOCATION_TRASH); + + sql ("DELETE FROM role_users_trash WHERE role = %llu;", role); + sql ("DELETE FROM roles_trash WHERE id = %llu;", role); + sql_commit (); + return 0; + } + + if (role_is_predefined (role)) + { + sql_rollback (); + return 3; + } + + if (role_in_use (role)) + { + sql_rollback (); + return 1; + } + + if (ultimate == 0) + { + role_t trash_role; + + sql ("INSERT INTO roles_trash" + " (uuid, owner, name, comment, creation_time, modification_time)" + " SELECT uuid, owner, name, comment, creation_time," + " modification_time" + " FROM roles WHERE id = %llu;", + role); + + trash_role = sql_last_insert_id (); + + sql ("INSERT INTO role_users_trash" + " (\"role\", \"user\")" + " SELECT %llu, \"user\"" + " FROM role_users WHERE \"role\" = %llu;", + trash_role, + role); + + permissions_set_locations ("role", role, trash_role, LOCATION_TRASH); + tags_set_locations ("role", role, trash_role, LOCATION_TRASH); + permissions_set_subjects ("role", role, trash_role, LOCATION_TRASH); + } + else + { + sql ("DELETE FROM permissions" + " WHERE resource_type = 'role'" + " AND resource = %llu" + " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", + role); + sql ("DELETE FROM permissions_trash" + " WHERE resource_type = 'role'" + " AND resource = %llu" + " AND resource_location = " G_STRINGIFY (LOCATION_TRASH) ";", + role); + sql ("DELETE FROM permissions" + " WHERE subject_type = 'role'" + " AND subject = %llu" + " AND subject_location = " G_STRINGIFY (LOCATION_TABLE) ";", + role); + sql ("DELETE FROM permissions_trash" + " WHERE subject_type = 'role'" + " AND subject = %llu" + " AND subject_location = " G_STRINGIFY (LOCATION_TABLE) ";", + role); + tags_remove_resource ("role", role, LOCATION_TABLE); + } + + affected_users = g_array_new (TRUE, TRUE, sizeof (user_t)); + init_iterator (&users_iter, + "SELECT \"user\" FROM role_users" + " WHERE \"role\" = %llu", + role); + while (next (&users_iter)) + { + user_t user = iterator_int64 (&users_iter, 0); + g_array_append_val (affected_users, user); + } + cleanup_iterator (&users_iter); + + sql ("DELETE FROM role_users WHERE \"role\" = %llu;", role); + sql ("DELETE FROM roles WHERE id = %llu;", role); + + cache_all_permissions_for_users (affected_users); + g_array_free (affected_users, TRUE); + + sql_commit (); + return 0; +} From 331f8123c347f5f8f1a73a34e818fc03faa0ec0d Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Tue, 6 Jan 2026 13:00:31 +0200 Subject: [PATCH 6/6] Remove duplicate header --- src/manage_roles.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/manage_roles.h b/src/manage_roles.h index ec1ff3fdf..eef86c7ad 100644 --- a/src/manage_roles.h +++ b/src/manage_roles.h @@ -25,9 +25,6 @@ copy_role (const char *, const char *, const char *, role_t *); int create_role (const char *, const char *, const char *, role_t *); -gboolean -find_role_with_permission (const char *, role_t *, const char *); - int delete_role (const char *, int);