diff --git a/include/cms_users.php b/include/cms_users.php index bb625c9e..2c41e5f8 100644 --- a/include/cms_users.php +++ b/include/cms_users.php @@ -28,7 +28,7 @@ // Execution of queries in cms_users_page.php $cms_users_lower_level_query = ' - SELECT u.*, NOT u.is_admin AS visible, g.label AS usergroup, 0 AS preventdelete, 0 as disableifistrue + SELECT u.*, NOT u.is_admin AS visible, g.label AS usergroup, 0 AS preventdelete, 0 as disableifistrue, 0 AS preventedit FROM cms_users AS u LEFT OUTER JOIN cms_usergroups AS g ON g.id = u.cms_usergroups_id LEFT OUTER JOIN cms_usergroups_camps AS uc ON uc.cms_usergroups_id = g.id @@ -46,13 +46,14 @@ // Do not forget to specify :userGroupLevel and :user in the db call later // related to this trello card https://trello.com/c/KI47eGPI $cms_users_same_or_upper_level_query = ' - SELECT u.*, 0 AS visible, g.label AS usergroup, 1 AS preventdelete, 1 as disableifistrue + SELECT u.*, IF(u.id = :user, 1, 0) AS visible, g.label AS usergroup, 1 AS preventdelete, 1 as disableifistrue, IF(u.id = :user, 0, 1) AS preventedit FROM cms_users AS u INNER JOIN cms_usergroups AS g ON g.id = u.cms_usergroups_id INNER JOIN cms_usergroups_camps AS uc ON uc.cms_usergroups_id = g.id INNER JOIN cms_usergroups_levels AS l ON l.id = g.userlevel - WHERE (l.level >= :userGroupLevel AND u.id != :user) - AND uc.camp_id IN ('.($_SESSION['camp']['id'] ?: 0).') + WHERE l.level >= :userGroupLevel + AND (u.id != :user OR :userGroupLevel = 100) + AND uc.camp_id IN ('.(intval($_SESSION['camp']['id']) ?: 0).') AND NOT (u.valid_lastday < CURDATE() AND UNIX_TIMESTAMP(u.valid_lastday) != 0) AND UNIX_TIMESTAMP(u.deleted) = 0 GROUP BY u.id diff --git a/include/cms_users_deactivated.php b/include/cms_users_deactivated.php index ad95eb65..500713cc 100644 --- a/include/cms_users_deactivated.php +++ b/include/cms_users_deactivated.php @@ -24,7 +24,7 @@ ); // Execution of queries in cms_users_page.php - $cms_users_lower_level_query = 'SELECT u.id, u.naam, SUBSTR(u.email, 1, LENGTH(u.email)-LENGTH(".deleted.")-LENGTH(u.id)) AS email, u.valid_firstday, u.valid_lastday, NOT u.is_admin AS visible, g.label AS usergroup, 0 AS preventdelete, 1 as disableifistrue + $cms_users_lower_level_query = 'SELECT u.id, u.naam, SUBSTR(u.email, 1, LENGTH(u.email)-LENGTH(".deleted.")-LENGTH(u.id)) AS email, u.valid_firstday, u.valid_lastday, NOT u.is_admin AS visible, g.label AS usergroup, 0 AS preventdelete, 1 as disableifistrue, 0 as preventedit FROM cms_users AS u LEFT OUTER JOIN cms_usergroups AS g ON g.id = u.cms_usergroups_id LEFT OUTER JOIN cms_usergroups_camps AS uc ON uc.cms_usergroups_id = g.id @@ -40,7 +40,7 @@ // Do not forget to specify :usergroup and :user in the db call later $cms_users_same_level_query = ' - SELECT u.id, u.naam, SUBSTR(u.email, 1, LENGTH(u.email)-LENGTH(".deleted.")-LENGTH(u.id)) AS email, u.valid_firstday, u.valid_lastday, 0 AS visible, g.label AS usergroup, 1 AS preventdelete, 1 as disableifistrue + SELECT u.id, u.naam, SUBSTR(u.email, 1, LENGTH(u.email)-LENGTH(".deleted.")-LENGTH(u.id)) AS email, u.valid_firstday, u.valid_lastday, 0 AS visible, g.label AS usergroup, 1 AS preventdelete, 1 as disableifistrue, 1 AS preventedit FROM cms_users AS u LEFT OUTER JOIN cms_usergroups AS g ON g.id = u.cms_usergroups_id WHERE u.cms_usergroups_id = :usergroup diff --git a/include/cms_users_edit.php b/include/cms_users_edit.php index f576fa31..78f91869 100644 --- a/include/cms_users_edit.php +++ b/include/cms_users_edit.php @@ -74,10 +74,41 @@ WHERE ug.id = :id AND (NOT ug.deleted OR ug.deleted IS NULL)', ['id' => $_POST['cms_usergroups_id'][0]]); $is_admin = $_SESSION['user']['is_admin']; $organisation_allowed = ($_SESSION['organisation']['id'] == $posteduser['organisation_id']); - // allow admins to create another admin account + // allow HoO to create another HoO account // related to this trello card https://trello.com/c/YAF3Az4P $userlevel_allowed = ($_SESSION['usergroup']['userlevel'] > $posteduser['userlevel']) || ($_SESSION['usergroup']['userlevel'] == $posteduser['userlevel'] && '100' == $_SESSION['usergroup']['userlevel']); + // Prevent HoO user from downgrading their usergroup if they're the only HoO + if (!$is_admin + && $_POST['id'] == $_SESSION['user']['id'] + && 100 == $_SESSION['usergroup']['userlevel']) { + // Count how many HoO users exist in this organization + $hoo_count = db_value( + ' + SELECT COUNT(DISTINCT u.id) + FROM cms_users AS u + LEFT JOIN cms_usergroups AS ug ON ug.id = u.cms_usergroups_id + LEFT JOIN cms_usergroups_levels AS ugl ON ugl.id = ug.userlevel + WHERE ug.organisation_id = :org_id + AND ugl.level = 100 + AND (NOT u.deleted OR u.deleted IS NULL) + AND (NOT ug.deleted OR ug.deleted IS NULL) + AND NOT (u.valid_lastday < CURDATE() AND UNIX_TIMESTAMP(u.valid_lastday) != 0)', + ['org_id' => $_SESSION['organisation']['id']] + ); + + // If this is the last HoO, prevent the change + if ($hoo_count <= 1) { + if ($posteduser['userlevel'] < $_SESSION['usergroup']['userlevel']) { + redirect('?action=cms_users_edit&id='.$_POST['id'].'&origin='.$_POST['_origin'].'&warning=1&message=You cannot downgrade yourself. Your organisation must have at least one Head of Operations user.'); + trigger_error('You cannot downgrade yourself. Your organisation must have at least one Head of Operations user.', E_USER_NOTICE); + } elseif (('' !== $_POST['valid_firstday']) || ('' !== $_POST['valid_lastday'])) { + redirect('?action=cms_users_edit&id='.$_POST['id'].'&origin='.$_POST['_origin'].'&warning=1&message=You cannot edit yourself. Your organisation must have at least one Head of Operations user.'); + trigger_error('You cannot edit yourself. Your organisation must have at least one Head of Operations user.', E_USER_NOTICE); + } + } + } + if ($is_admin || ($organisation_allowed && $userlevel_allowed)) { $keys = ['naam', 'email', 'cms_usergroups_id', 'valid_firstday', 'valid_lastday']; $userId = db_transaction(function () use ($table, $keys, $userId) { @@ -114,7 +145,12 @@ FROM cms_usergroups AS ug LEFT OUTER JOIN cms_usergroups_levels AS ugl ON ugl.id=ug.userlevel WHERE ug.id = :id AND (NOT ug.deleted OR ug.deleted IS NULL)', ['id' => $data['cms_usergroups_id']]); - if (!$_SESSION['user']['is_admin'] && ($data && ($data['is_admin'] || ($_SESSION['organisation']['id'] != $requesteduser['organisation_id']) || ($_SESSION['usergroup']['userlevel'] <= $requesteduser['userlevel'])))) { + if (!$_SESSION['user']['is_admin'] + && $data + && $data['id'] != $_SESSION['user']['id'] + && ($data['is_admin'] + || $_SESSION['organisation']['id'] != $requesteduser['organisation_id'] + || $_SESSION['usergroup']['userlevel'] <= $requesteduser['userlevel'])) { throw new Exception('You do not have access to this user!', 403); } @@ -130,11 +166,14 @@ // display admin role in the usergroup - only for user with admin roles // related to this trello card https://trello.com/c/YAF3Az4P $usergroups = db_array(' - SELECT ug.id AS value, ug.label - FROM cms_usergroups AS ug - LEFT OUTER JOIN cms_usergroups_levels AS ugl ON (ugl.id=ug.userlevel) - WHERE ug.organisation_id = :organisation_id AND (ugl.level < :userlevel OR :is_admin OR (ugl.level <= :userlevel AND 100 = :userlevel)) AND (NOT ug.deleted OR ug.deleted IS NULL) - ORDER BY ug.label', ['organisation_id' => $_SESSION['organisation']['id'], 'userlevel' => $_SESSION['usergroup']['userlevel'], 'is_admin' => $_SESSION['user']['is_admin']]); + SELECT ug.id AS value, ug.label + FROM cms_usergroups AS ug + LEFT OUTER JOIN cms_usergroups_levels AS ugl ON (ugl.id=ug.userlevel) + WHERE ug.organisation_id = :organisation_id + AND (:is_admin OR (ugl.level < :userlevel OR (ugl.level <= :userlevel AND 100 = :userlevel))) + AND (:is_admin OR ug.label != "Boxtribute God") + AND (NOT ug.deleted OR ug.deleted IS NULL) + ORDER BY ug.label', ['organisation_id' => $_SESSION['organisation']['id'], 'userlevel' => $_SESSION['usergroup']['userlevel'], 'is_admin' => $_SESSION['user']['is_admin']]); addfield('select', 'Select user group', 'cms_usergroups_id', ['required' => true, 'options' => $usergroups, 'testid' => 'user_group']); addfield('line'); diff --git a/include/cms_users_expired.php b/include/cms_users_expired.php index 8cfcb899..1514b4ea 100644 --- a/include/cms_users_expired.php +++ b/include/cms_users_expired.php @@ -29,7 +29,7 @@ ); // Execution of queries in cms_users_page.php - $cms_users_lower_level_query = 'SELECT u.*, NOT u.is_admin AS visible, g.label AS usergroup, 0 AS preventdelete, 1 as disableifistrue + $cms_users_lower_level_query = 'SELECT u.*, NOT u.is_admin AS visible, g.label AS usergroup, 0 AS preventdelete, 1 as disableifistrue, 0 AS preventedit FROM cms_users AS u LEFT OUTER JOIN cms_usergroups AS g ON g.id = u.cms_usergroups_id LEFT OUTER JOIN cms_usergroups_camps AS uc ON uc.cms_usergroups_id = g.id @@ -46,7 +46,7 @@ // Do not forget to specify :usergroup and :user in the db call later $cms_users_same_level_query = ' - SELECT u.*, 0 AS visible, g.label AS usergroup, 1 AS preventdelete, 1 as disableifistrue + SELECT u.*, 0 AS visible, g.label AS usergroup, 1 AS preventdelete, 1 as disableifistrue, 1 AS preventedit FROM cms_users AS u LEFT OUTER JOIN cms_usergroups AS g ON g.id = u.cms_usergroups_id WHERE u.cms_usergroups_id = :usergroup