Username:
Password:
Role :
diff --git a/group_capabilities.php b/group_capabilities.php new file mode 100644 index 0000000..6df9f0a --- /dev/null +++ b/group_capabilities.php @@ -0,0 +1,14 @@ + 'create groups', + 'group_edit' => 'edit group info', + 'group_delete' => 'delete groups', + 'group_create_user' => 'create new users inside groups', + 'group_add_member_auth' => 'add users to groups (with password)', + 'group_add_member_no_auth' => 'add users to groups (without password)', + 'group_add_member_invite' => 'invite users to join groups', + 'group_delete_user' => 'delete users', + 'group_edit_user' => 'edit user info', + 'group_impersonate' => 'can impersonate other users', +]; diff --git a/group_controller.php b/group_controller.php index c652f82..35ff5ca 100644 --- a/group_controller.php +++ b/group_controller.php @@ -18,6 +18,16 @@ // no direct access defined('EMONCMS_EXEC') or die('Restricted access'); + +// Make sure we have our capability check function +if (is_file("Modules/user_capabilities/user_capabilities.php")) { + require_once "Modules/user_capabilities/user_capabilities.php"; +} else { + function user_has_capability($args) { + return true; + } +} + function group_controller() { global $session, $route, $mysqli, $redis, $user, $feed_settings, $log; @@ -150,6 +160,12 @@ function group_controller() { // SPECIAL USER SWITCHING FUNCTIONS // -------------------------------------------------------------------------- if ($route->action == 'setuser') { + // Check capability + if (!user_has_capability('group_impersonate')) { + http_response_code(403); + return _("You don't have permission to do that."); + } + $route->format = "text"; $groupid = (int) get('groupid'); $userid = (int) get('userid'); diff --git a/group_model.php b/group_model.php index 12b130a..55679f6 100644 --- a/group_model.php +++ b/group_model.php @@ -19,8 +19,16 @@ // no direct access defined('EMONCMS_EXEC') or die('Restricted access'); -class Group { +// Make sure we have our capability check function +if (is_file("Modules/user_capabilities/user_capabilities.php")) { + require_once "Modules/user_capabilities/user_capabilities.php"; +} else { + function user_has_capability($args) { + return true; + } +} +class Group { private $mysqli; private $user; private $feed; @@ -38,8 +46,22 @@ public function __construct($mysqli, $redis, $user, $feed, $input, $task = null) $this->task = $task; } + private function no_permission() { + http_response_code(403); + + return [ + 'success' => false, + 'message' => _("You don't have permission to do that") + ]; + } + // Create group, add creator user as administrator public function create($userid, $name, $description, $organization, $area, $visibility, $access) { + // Check capability + if (!user_has_capability('group_create')) { + return $this->no_permission(); + } + // Input sanitisation $userid = (int) $userid; $name = preg_replace('/[^\w\s-:]/', '', $name); @@ -49,31 +71,35 @@ public function create($userid, $name, $description, $organization, $area, $visi $visibility = $visibility == 'public' ? 'public' : 'private'; $access = $access == 'open' ? 'open' : 'closed'; - if ($this->exists_name($name)) { - $this->log->warn("Cannot create group, already exists"); - return array('success' => false, 'message' => _("Cannot create group, already exists")); + $this->log->warn("Cannot create group as a group with that name already exists"); + return array('success' => false, 'message' => _("Cannot create group as a group with that name already exists")); } - $stmt = $this->mysqli->prepare("INSERT INTO groups (name,description, organization, area, visibility, access) VALUES (?,?,?,?,?,?)"); + $stmt = $this->mysqli->prepare("INSERT INTO groups (name, description, organization, area, visibility, access) VALUES (?,?,?,?,?,?)"); $stmt->bind_param("ssssss", $name, $description, $organization, $area, $visibility, $access); if (!$stmt->execute()) { $this->log->error("Error creating group, problem with sql statement"); - return array('success' => false, 'message' => _("Error creating group")); + return array('success' => false, 'message' => _("Couldn't create group")); } $groupid = $this->mysqli->insert_id; if (!$this->add_user($groupid, $userid, 1)) { - $this->log->error("Error adding user to group " . $groupid); - return array('success' => false, 'message' => _("Error adding user to group")); + $this->log->error("Error adding user $userid to group $groupid"); + return array('success' => false, 'message' => _("Group created, but couldn't add you to it")); } $this->log->info("Group $groupid added"); - return array('success' => true, 'groupid' => $groupid, 'message' => _("Group $groupid added")); + return array('success' => true, 'groupid' => $groupid, 'message' => _("Group '$name' added")); } // Edit group public function editgroup($admin_userid, $groupid, $name, $description, $organization, $area, $visibility, $access) { + // Check capability + if (!user_has_capability('group_edit')) { + return $this->no_permission(); + } + // Input sanitisation $groupid = (int) $groupid; $admin_userid = (int) $admin_userid; @@ -89,18 +115,25 @@ public function editgroup($admin_userid, $groupid, $name, $description, $organiz $stmt->bind_param("ssssssi", $name, $description, $organization, $area, $visibility, $access, $groupid); if (!$stmt->execute()) { $this->log->error("Error editing group, problem with sql statement"); - return array('success' => false, 'message' => _("Error editing group")); + return array('success' => false, 'message' => _("Error updating group")); } $this->log->info("Group edited"); - return array('success' => true, 'message' => _("Group edited")); + return array('success' => true, 'message' => _("Group updated")); + } else { + $this->log->warning("Error editing group, You are not administrator of the group - Session userid: " . $admin_userid); return array('success' => false, 'message' => _("You are not administrator of the group")); } } public function createuseraddtogroup($admin_userid, $groupid, $email, $username, $password, $role, $name) { + // Check capability + if (!user_has_capability('group_create_user')) { + return $this->no_permission(); + } + // Input sanitisation $admin_userid = (int) $admin_userid; $groupid = (int) $groupid; @@ -108,14 +141,14 @@ public function createuseraddtogroup($admin_userid, $groupid, $email, $username, // email, username and password checked within $user model and $name if (!$this->exists($groupid)) { - $this->log->warn("Group " . $groupid . " does not exist"); + $this->log->warn("Group $groupid does not exist"); return array('success' => false, 'message' => _("Group does not exist")); } // 1. Check that user is a group administrator if (!$this->is_group_admin($groupid, $admin_userid)) { - $this->log->warn("You haven't got enough permissions to add a member to this group - Session userid: " . $admin_userid); - return array('success' => false, 'message' => _("You haven't got enough permissions to add a member to this group")); + $this->log->warn("User $admin_userid called createuseraddtogroup without permission"); + return array('success' => false, 'message' => _("You don't have permission to add someone to this group")); } // 2. Check username and password, return @@ -131,18 +164,24 @@ public function createuseraddtogroup($admin_userid, $groupid, $email, $username, $user_data->name = $name; $result = $this->user->set($add_userid, $user_data); - // 3. Add user to group + // 3. Add user to group if (!$this->add_user($groupid, $add_userid, $role, $admin_rights = 'full')) { $this->log->error("Error adding user to group"); - return array('success' => false, 'message' => _("Error adding user to group")); + return array('success' => false, 'message' => _("User created, but couldn't add to group")); } $this->log->info("User $add_userid:$username added to group " . $groupid); - return array('success' => true, 'message' => _("User $add_userid:$username added"), 'userid' => $add_userid); + return array('success' => true, 'message' => _("User '$username' created and added to group"), 'userid' => $add_userid); } // Add user to a group if admin user knows account username and password public function add_user_auth($admin_userid, $groupid, $username, $password, $role) { + // Check capability + if (!user_has_capability('group_add_member_auth') && + !user_has_capability('group_add_member_no_auth')) { + return $this->no_permission(); + } + // Input sanitisation $admin_userid = (int) $admin_userid; $groupid = (int) $groupid; @@ -160,15 +199,24 @@ public function add_user_auth($admin_userid, $groupid, $username, $password, $ro return array('success' => false, 'message' => _("You haven't got enough permissions to add a member to this group")); } - // 2. Check username and password, return - $result = $this->user->get_apikeys_from_login($username, $password); - if (!$result["success"]) { - $this->log->error("Error adding user to group, username and password don't match - Session userid: " . $admin_userid); - return $result; + // 2. Check username and password if required + // We only allow adding without a password if the capabilities module is loaded + if (class_exists('Capabilities') && user_has_capability('group_add_member_no_auth')) { + $add_userid = $this->user->get_id($username); + if (!$add_userid) { + $this->log->error("Error adding user to group: user $username doesn't exist"); + return [ 'success' => false, 'message' => _("User doesn't exist") ]; + } + } else { + $result = $this->user->get_apikeys_from_login($username, $password); + if (!$result["success"]) { + $this->log->error("Error adding user to group, username and password don't match - Session userid: " . $admin_userid); + return $result; + } + $add_userid = $result["userid"]; } - $add_userid = $result["userid"]; - // 3. Add user to group + // 3. Add user to group if (!$this->add_user($groupid, $add_userid, $role)) { $this->log->error("Error adding user to group"); return array('success' => false, 'message' => _("Error adding user to group")); @@ -180,12 +228,17 @@ public function add_user_auth($admin_userid, $groupid, $username, $password, $ro // Send email invite to user to join a group public function add_user_invite($userid, $groupid, $invite_userid) { + // Check capability + if (!user_has_capability('group_add_member_invite')) { + return $this->no_permission(); + } + // Input sanitisation $userid = (int) $userid; $groupid = (int) $groupid; } - // Return list of groups which $userid belongs and has right to list + // Return list of groups which $userid belongs and has right to list public function grouplist($userid) { // Input sanitisation $userid = (int) $userid; @@ -402,6 +455,11 @@ public function getuserinputs($session_userid, $groupid, $userid) { } public function delete($userid, $groupid) { + // Check capability + if (!user_has_capability('group_delete')) { + return $this->no_permission(); + } + // Input sanitisation $userid = (int) $userid; $groupid = (int) $groupid; @@ -462,6 +520,11 @@ public function remove_user($userid, $groupid, $userid_to_remove) { // Remove user from database and group public function full_remove_user($session_userid, $groupid, $userid_to_remove) { + // Check capability + if (!user_has_capability('group_delete_user')) { + return $this->no_permission(); + } + // Input sanitisation $session_userid = (int) $session_userid; $groupid = (int) $groupid; @@ -544,11 +607,16 @@ public function add_user($groupid, $userid, $role = 0, $admin_rights = 'full') { $this->log->error('Cannot add user to group, error in query'); return false; } - $this->log->info('User ' . $userid . ' added to group ' . '$groupid'); + $this->log->info("User $userid added to group $groupid"); return true; } public function setuserinfo($session_userid, $groupid, $to_set_userid, $username, $name, $email, $bio, $timezone, $location, $role, $password, $tags) { + // Check capability + if (!user_has_capability('group_edit_user')) { + return $this->no_permission(); + } + // Input sanitisation $session_userid = (int) $session_userid; $groupid = (int) $groupid; diff --git a/group_view.php b/group_view.php index bb32317..7ca1b03 100644 --- a/group_view.php +++ b/group_view.php @@ -57,17 +57,42 @@
Username:
Password:
Role :