diff --git a/src/manage.h b/src/manage.h index 20bcadf3a..0b7d6d236 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2948,30 +2948,6 @@ delete_permissions_cache_for_resource (const char*, resource_t); void delete_permissions_cache_for_user (user_t); - -/* Roles. */ - -int -init_role_iterator (iterator_t *, get_data_t *); - -char* -role_uuid (role_t); - -gchar * -role_users (role_t); - -int -trash_role_writable (role_t); - -int -role_writable (role_t); - -int -role_count (const get_data_t*); - -int -modify_role (const char *, const char *, const char *, const char *); - /* Schema. */ diff --git a/src/manage_roles.c b/src/manage_roles.c index a1b01b496..868c38991 100644 --- a/src/manage_roles.c +++ b/src/manage_roles.c @@ -4,6 +4,7 @@ */ #include "manage_roles.h" +#include "manage_sql_roles.h" #undef G_LOG_DOMAIN /** @@ -36,3 +37,31 @@ trash_role_in_use (role_t role) { return 0; } + +/** + * @brief Check whether a role is writable. + * + * @param[in] role Role. + * + * @return 1 yes, 0 no. + */ +int +role_writable (role_t role) +{ + if (role_is_predefined (role)) + return 0; + return 1; +} + +/** + * @brief Check whether a trashcan role is writable. + * + * @param[in] role Role. + * + * @return 1 yes, 0 no. + */ +int +trash_role_writable (role_t role) +{ + return 1; +} diff --git a/src/manage_roles.h b/src/manage_roles.h index eef86c7ad..5e442b60a 100644 --- a/src/manage_roles.h +++ b/src/manage_roles.h @@ -28,4 +28,25 @@ create_role (const char *, const char *, const char *, role_t *); int delete_role (const char *, int); +int +init_role_iterator (iterator_t *, get_data_t *); + +int +role_count (const get_data_t *); + +int +modify_role (const char *, const char *, const char *, const char *); + +char* +role_uuid (role_t); + +gchar * +role_users (role_t); + +int +trash_role_writable (role_t); + +int +role_writable (role_t); + #endif /* not _GVMD_MANAGE_ROLES_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index df9f8d92d..f4e5700db 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -35107,277 +35107,6 @@ clean_feed_role_permissions (const char *type, return; } - -/* Roles. */ - -/** - * @brief Gets UUID of role. - * - * @param[in] role Role. - * - * @return Users. - */ -gchar * -role_uuid (role_t role) -{ - return sql_string ("SELECT uuid FROM roles WHERE id = %llu;", - role); -} - -/** - * @brief Gets users of role as a string. - * - * @param[in] role Role. - * - * @return Users. - */ -gchar * -role_users (role_t role) -{ - return sql_string ("SELECT group_concat (name, ', ')" - " FROM (SELECT users.name FROM users, role_users" - " WHERE role_users.role = %llu" - " AND role_users.user = users.id" - " GROUP BY users.name)" - " AS sub;", - role); -} - -/** - * @brief Check whether a role is writable. - * - * @param[in] role Role. - * - * @return 1 yes, 0 no. - */ -int -role_writable (role_t role) -{ - if (role_is_predefined (role)) - return 0; - return 1; -} - -/** - * @brief Check whether a trashcan role is writable. - * - * @param[in] role Role. - * - * @return 1 yes, 0 no. - */ -int -trash_role_writable (role_t role) -{ - return 1; -} - -/** - * @brief Modify a role. - * - * @param[in] role_id UUID of role. - * @param[in] name Name of role. - * @param[in] comment Comment on role. - * @param[in] users Role users. - * - * @return 0 success, 1 failed to find role, 2 failed to find user, 3 role_id - * required, 4 user name validation failed, 5 role with new name - * exists, 99 permission denied, -1 internal error. - */ -int -modify_role (const char *role_id, const char *name, const char *comment, - const char *users) -{ - int ret; - gchar *quoted_name, *quoted_comment; - role_t role; - GArray *affected_users; - iterator_t users_iter; - - assert (current_credentials.uuid); - - if (role_id == NULL) - return 3; - - sql_begin_immediate (); - - if (acl_user_may ("modify_role") == 0) - { - sql_rollback (); - return 99; - } - - role = 0; - - if (find_role_with_permission (role_id, &role, "modify_role")) - { - sql_rollback (); - return -1; - } - - if (role == 0) - { - sql_rollback (); - return 1; - } - - /* Check whether a role with the same name exists already. */ - if (name) - { - if (resource_with_name_exists (name, "role", role)) - { - sql_rollback (); - return 5; - } - } - - quoted_name = sql_quote (name ?: ""); - quoted_comment = sql_quote (comment ?: ""); - - sql ("UPDATE roles SET" - " name = '%s'," - " comment = '%s'," - " modification_time = m_now ()" - " WHERE id = %llu;", - quoted_name, - quoted_comment, - role); - - g_free (quoted_comment); - g_free (quoted_name); - - 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); - - ret = add_users ("role", role, users); - - init_iterator (&users_iter, - "SELECT \"user\" FROM role_users" - " WHERE \"role\" = %llu", - role); - - // users not looked for in this loop were removed - // -> possible permissions change - while (next (&users_iter)) - { - int index, found_user; - user_t user = iterator_int64 (&users_iter, 0); - - found_user = 0; - for (index = 0; index < affected_users->len && found_user == 0; index++) - { - if (g_array_index (affected_users, user_t, index) == user) - { - found_user = 1; - break; - } - } - - if (found_user) - { - // users found here stay in the role -> no change in permissions - g_array_remove_index_fast (affected_users, index); - } - else - { - // user added to role -> possible permissions change - g_array_append_val (affected_users, user); - } - } - - cleanup_iterator (&users_iter); - - cache_all_permissions_for_users (affected_users); - - g_array_free (affected_users, TRUE); - - if (ret) - sql_rollback (); - else - sql_commit (); - - return ret; -} - -/** - * @brief Filter columns for role iterator. - */ -#define ROLE_ITERATOR_FILTER_COLUMNS \ - { GET_ITERATOR_FILTER_COLUMNS, NULL } - -/** - * @brief Role iterator columns. - */ -#define ROLE_ITERATOR_COLUMNS \ - { \ - GET_ITERATOR_COLUMNS (roles), \ - { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ - } - -/** - * @brief Role iterator columns for trash case. - */ -#define ROLE_ITERATOR_TRASH_COLUMNS \ - { \ - GET_ITERATOR_COLUMNS (roles_trash), \ - { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ - } - -/** - * @brief Count number of roles. - * - * @param[in] get GET params. - * - * @return Total number of roles in roleed set. - */ -int -role_count (const get_data_t *get) -{ - static const char *extra_columns[] = ROLE_ITERATOR_FILTER_COLUMNS; - static column_t columns[] = ROLE_ITERATOR_COLUMNS; - static column_t trash_columns[] = ROLE_ITERATOR_TRASH_COLUMNS; - return count ("role", get, columns, trash_columns, extra_columns, - 0, 0, 0, TRUE); -} - -/** - * @brief Initialise a role iterator, including observed roles. - * - * @param[in] iterator Iterator. - * @param[in] get GET data. - * - * @return 0 success, 1 failed to find role, 2 failed to find role (filt_id), - * -1 error. - */ -int -init_role_iterator (iterator_t* iterator, get_data_t *get) -{ - static const char *filter_columns[] = ROLE_ITERATOR_FILTER_COLUMNS; - static column_t columns[] = ROLE_ITERATOR_COLUMNS; - static column_t trash_columns[] = ROLE_ITERATOR_TRASH_COLUMNS; - - return init_get_iterator (iterator, - "role", - get, - columns, - trash_columns, - filter_columns, - 0, - NULL, - NULL, - TRUE); -} - /* Schema. */ diff --git a/src/manage_sql_roles.c b/src/manage_sql_roles.c index 23fca2be6..d890f3654 100644 --- a/src/manage_sql_roles.c +++ b/src/manage_sql_roles.c @@ -410,3 +410,243 @@ delete_role (const char *role_id, int ultimate) sql_commit (); return 0; } + +/** + * @brief Filter columns for role iterator. + */ +#define ROLE_ITERATOR_FILTER_COLUMNS \ + { GET_ITERATOR_FILTER_COLUMNS, NULL } + +/** + * @brief Role iterator columns. + */ +#define ROLE_ITERATOR_COLUMNS \ + { \ + GET_ITERATOR_COLUMNS (roles), \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } + +/** + * @brief Role iterator columns for trash case. + */ +#define ROLE_ITERATOR_TRASH_COLUMNS \ + { \ + GET_ITERATOR_COLUMNS (roles_trash), \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } + +/** + * @brief Count number of roles. + * + * @param[in] get GET params. + * + * @return Total number of roles in roleed set. + */ +int +role_count (const get_data_t *get) +{ + static const char *extra_columns[] = ROLE_ITERATOR_FILTER_COLUMNS; + static column_t columns[] = ROLE_ITERATOR_COLUMNS; + static column_t trash_columns[] = ROLE_ITERATOR_TRASH_COLUMNS; + return count ("role", get, columns, trash_columns, extra_columns, + 0, 0, 0, TRUE); +} + +/** + * @brief Initialise a role iterator, including observed roles. + * + * @param[in] iterator Iterator. + * @param[in] get GET data. + * + * @return 0 success, 1 failed to find role, 2 failed to find role (filt_id), + * -1 error. + */ +int +init_role_iterator (iterator_t* iterator, get_data_t *get) +{ + static const char *filter_columns[] = ROLE_ITERATOR_FILTER_COLUMNS; + static column_t columns[] = ROLE_ITERATOR_COLUMNS; + static column_t trash_columns[] = ROLE_ITERATOR_TRASH_COLUMNS; + + return init_get_iterator (iterator, + "role", + get, + columns, + trash_columns, + filter_columns, + 0, + NULL, + NULL, + TRUE); +} + +/** + * @brief Modify a role. + * + * @param[in] role_id UUID of role. + * @param[in] name Name of role. + * @param[in] comment Comment on role. + * @param[in] users Role users. + * + * @return 0 success, 1 failed to find role, 2 failed to find user, 3 role_id + * required, 4 user name validation failed, 5 role with new name + * exists, 99 permission denied, -1 internal error. + */ +int +modify_role (const char *role_id, const char *name, const char *comment, + const char *users) +{ + int ret; + gchar *quoted_name, *quoted_comment; + role_t role; + GArray *affected_users; + iterator_t users_iter; + + assert (current_credentials.uuid); + + if (role_id == NULL) + return 3; + + sql_begin_immediate (); + + if (acl_user_may ("modify_role") == 0) + { + sql_rollback (); + return 99; + } + + role = 0; + + if (find_role_with_permission (role_id, &role, "modify_role")) + { + sql_rollback (); + return -1; + } + + if (role == 0) + { + sql_rollback (); + return 1; + } + + /* Check whether a role with the same name exists already. */ + if (name) + { + if (resource_with_name_exists (name, "role", role)) + { + sql_rollback (); + return 5; + } + } + + quoted_name = sql_quote (name ?: ""); + quoted_comment = sql_quote (comment ?: ""); + + sql ("UPDATE roles SET" + " name = '%s'," + " comment = '%s'," + " modification_time = m_now ()" + " WHERE id = %llu;", + quoted_name, + quoted_comment, + role); + + g_free (quoted_comment); + g_free (quoted_name); + + 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); + + ret = add_users ("role", role, users); + + init_iterator (&users_iter, + "SELECT \"user\" FROM role_users" + " WHERE \"role\" = %llu", + role); + + // users not looked for in this loop were removed + // -> possible permissions change + while (next (&users_iter)) + { + int index, found_user; + user_t user = iterator_int64 (&users_iter, 0); + + found_user = 0; + for (index = 0; index < affected_users->len && found_user == 0; index++) + { + if (g_array_index (affected_users, user_t, index) == user) + { + found_user = 1; + break; + } + } + + if (found_user) + { + // users found here stay in the role -> no change in permissions + g_array_remove_index_fast (affected_users, index); + } + else + { + // user added to role -> possible permissions change + g_array_append_val (affected_users, user); + } + } + + cleanup_iterator (&users_iter); + + cache_all_permissions_for_users (affected_users); + + g_array_free (affected_users, TRUE); + + if (ret) + sql_rollback (); + else + sql_commit (); + + return ret; +} + +/** + * @brief Gets UUID of role. + * + * @param[in] role Role. + * + * @return Users. + */ +gchar * +role_uuid (role_t role) +{ + return sql_string ("SELECT uuid FROM roles WHERE id = %llu;", + role); +} + +/** + * @brief Gets users of role as a string. + * + * @param[in] role Role. + * + * @return Users. + */ +gchar * +role_users (role_t role) +{ + return sql_string ("SELECT group_concat (name, ', ')" + " FROM (SELECT users.name FROM users, role_users" + " WHERE role_users.role = %llu" + " AND role_users.user = users.id" + " GROUP BY users.name)" + " AS sub;", + role); +} diff --git a/src/manage_sql_roles.h b/src/manage_sql_roles.h index f1e549aaf..b51f7fa30 100644 --- a/src/manage_sql_roles.h +++ b/src/manage_sql_roles.h @@ -6,6 +6,30 @@ #ifndef _GVMD_MANAGE_SQL_ROLES_H #define _GVMD_MANAGE_SQL_ROLES_H +/** + * @brief Filter columns for role iterator. + */ +#define ROLE_ITERATOR_FILTER_COLUMNS \ + { GET_ITERATOR_FILTER_COLUMNS, NULL } + +/** + * @brief Role iterator columns. + */ +#define ROLE_ITERATOR_COLUMNS \ + { \ + GET_ITERATOR_COLUMNS (roles), \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } + +/** + * @brief Role iterator columns for trash case. + */ +#define ROLE_ITERATOR_TRASH_COLUMNS \ + { \ + GET_ITERATOR_COLUMNS (roles_trash), \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } + int role_is_predefined (role_t);