Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lbplanner/classes/enums/CAPABILITY.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ class CAPABILITY extends Enum {
* @return int the bitmappable flag
* @link CAPABILITY_FLAG
*/
public static function to_capability(string $str): int {
$name = self::name_from($str);
return constant('CAPABILITY_FLAG::'.$name);
public static function to_flag(string $str): int {
return CAPABILITY_FLAG::get(self::name_from($str));
}
}
3 changes: 1 addition & 2 deletions lbplanner/classes/enums/CAPABILITY_FLAG.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class CAPABILITY_FLAG extends Enum {
* @link CAPABILITY
*/
public static function to_capability(int $num): string {
$name = self::name_from($num);
return constant('CAPABILITY::'.$name);
return CAPABILITY::get(self::name_from($num));
}
}
70 changes: 8 additions & 62 deletions lbplanner/classes/helpers/user_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@

namespace local_lbplanner\helpers;

use coding_exception;
use context_system;
use dml_exception;
use moodle_exception;
use stdClass;
use user_picture;
use core_user;

use local_lbplanner\enums\{CAPABILITY, CAPABILITY_FLAG};
use local_lbplanner\enums\CAPABILITY;
use local_lbplanner\model\user;

/**
Expand All @@ -51,7 +49,13 @@ class user_helper {
*/
public static function check_access(int $userid): bool {
global $USER;
return ((int) $USER->id) === $userid;

if (((int) $USER->id) === $userid) {
return true;
} else {
$context = context_system::instance();
return has_capability(CAPABILITY::ADMIN, $context, $USER->id);
}
}

/**
Expand All @@ -69,64 +73,6 @@ public static function assert_access(int $userid): void {
}
}

/**
* Checks if the given user is an admin.
*
* @param int $userid The id of the user to check.
*
* @return bool True if the given user is an admin, false otherwise.
* @throws coding_exception
* @throws dml_exception
*/
public static function is_admin(int $userid): bool {
$context = context_system::instance();
return has_capability(CAPABILITY::ADMIN, $context, $userid, false);
}

/**
* Gives back a bitmask which represents the capabilities of the given user.
* 0 = no capabilities
* 1 = admin
* 2 = manager
* 3 = admin + manager
* 4 = teacher
* 5 = admin + teacher
* 6 = manager + teacher
* 7 = admin + manager + teacher
* 8 = student
* 9 = admin + student
* 10 = manager + student
* 11 = admin + manager + student
* 12 = teacher + student
* 13 = admin + teacher + student
* 14 = manager + teacher + student
* 15 = admin + manager + teacher + student
*
*
* @param int $userid The id of the user to check access for.
*
* @return int The capabilities of the given user.
* @throws coding_exception
* @throws dml_exception
*/
public static function get_user_capability_bitmask(int $userid): int {
$capabilities = 0;
$context = context_system::instance();
if (has_capability(CAPABILITY::ADMIN, $context, $userid, false)) {
$capabilities += CAPABILITY_FLAG::ADMIN;
}
if (has_capability(CAPABILITY::MANAGER, $context, $userid, false)) {
$capabilities += CAPABILITY_FLAG::MANAGER;
}
if (has_capability(CAPABILITY::TEACHER, $context, $userid, false)) {
$capabilities += CAPABILITY_FLAG::TEACHER;
}
if (has_capability(CAPABILITY::STUDENT, $context, $userid, false)) {
$capabilities += CAPABILITY_FLAG::STUDENT;
}
return $capabilities;
}

/**
* Checks if the given user exists in the LB_PLANNER_USER database.
*
Expand Down
68 changes: 49 additions & 19 deletions lbplanner/classes/model/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@
namespace local_lbplanner\model;

use coding_exception;
use context_system;
use external_single_structure;
use external_value;
use local_lbplanner\enums\CAPABILITY;
use local_lbplanner\enums\CAPABILITY_FLAG;
use local_lbplanner\helpers\plan_helper;
use local_lbplanner\helpers\user_helper;
use user_picture;
Expand Down Expand Up @@ -81,6 +84,11 @@ class user {
*/
private ?int $planid;

/**
* @var ?int $capabilitybitmask the cached user capability bitmask
*/
private ?int $capabilitybitmask;

/**
* Constructs a new course
* @param int $lbpid ID of the lb planner user
Expand All @@ -107,6 +115,7 @@ public function __construct(
$this->set_displaytaskcount($displaytaskcount);
$this->planid = null;
$this->pfp = null;
$this->capabilitybitmask = null;

if ($mdlid === (int) $USER->id) {
$this->mdluser = $USER;
Expand Down Expand Up @@ -240,6 +249,24 @@ public function get_pfp(): string {
return $this->pfp;
}

/**
* gets the user's capability bitmask
* @return int
*/
public function get_capabilitybitmask(): int {
if ($this->capabilitybitmask === null) {
$context = context_system::instance();
$this->capabilitybitmask = 0;
foreach (CAPABILITY::cases() as $case) {
if (has_capability($case->value, $context, $this->mdlid, false)) {
$this->capabilitybitmask |= CAPABILITY::to_flag($case->value);
}
}
}

return $this->capabilitybitmask;
}

/**
* Prepares data for the DB endpoint.
* doesn't set ID if it's 0
Expand Down Expand Up @@ -269,14 +296,21 @@ public function prepare_for_db(): object {
*/
public function prepare_for_api_short(): array {
$mdluser = $this->get_mdluser();
return [
$capabilitybm = $this->get_capabilitybitmask();

$data = [
'userid' => $this->mdlid,
'username' => $mdluser->username,
'firstname' => $mdluser->firstname,
'lastname' => $mdluser->lastname,
'profileimageurl' => $this->get_pfp(),
'vintage' => $mdluser->address,
];

if ($capabilitybm & CAPABILITY_FLAG::STUDENT) {
$data['vintage'] = $mdluser->address;
}

return $data;
}

/**
Expand All @@ -292,7 +326,7 @@ public static function api_structure_short(): external_single_structure {
'firstname' => new external_value(PARAM_TEXT, 'The firstname of the user'),
'lastname' => new external_value(PARAM_TEXT, 'The lastname of the user'),
'profileimageurl' => new external_value(PARAM_URL, 'The url of the profile image'),
'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'),
'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user', VALUE_DEFAULT),
]
);
}
Expand All @@ -303,21 +337,17 @@ public static function api_structure_short(): external_single_structure {
* @return array a full representation of this user and its data
*/
public function prepare_for_api(): array {
$mdluser = $this->get_mdluser();
return [
'userid' => $mdluser->id,
'username' => $mdluser->username,
'firstname' => $mdluser->firstname,
'lastname' => $mdluser->lastname,
'theme' => $this->theme,
'lang' => $this->lang,
'profileimageurl' => $this->get_pfp(),
'planid' => $this->get_planid(),
'colorblindness' => $this->colorblindness,
'displaytaskcount' => $this->displaytaskcount,
'capabilities' => user_helper::get_user_capability_bitmask($this->mdlid),
'vintage' => $mdluser->address,
];
return array_merge(
$this->prepare_for_api_short(),
[
'theme' => $this->theme,
'lang' => $this->lang,
'planid' => $this->get_planid(),
'colorblindness' => $this->colorblindness,
'displaytaskcount' => $this->displaytaskcount,
'capabilities' => $this->get_capabilitybitmask(),
]
);
}

/**
Expand All @@ -339,7 +369,7 @@ public static function api_structure(): external_single_structure {
'colorblindness' => new external_value(PARAM_TEXT, 'The colorblindness of the user'),
'displaytaskcount' => new external_value(PARAM_INT, 'If the user has the taskcount-enabled 1-yes 0-no'),
'capabilities' => new external_value(PARAM_INT, 'The capabilities of the user represented as a bitmask value'),
'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user'),
'vintage' => new external_value(PARAM_TEXT, 'The vintage of the user', VALUE_DEFAULT),
]
);
}
Expand Down
50 changes: 43 additions & 7 deletions lbplanner/classes/polyfill/Enum.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Enum {
* @return ?EnumCase the matching enum case or null if not found and $try==true
* @throws ValueError if not found and $try==false
*/
private static function find(mixed $value, bool $try): ?EnumCase {
private static function find($value, bool $try): ?EnumCase {
foreach (static::cases() as $case) {
if ($case->value === $value) {
return $case;
Expand All @@ -53,12 +53,32 @@ private static function find(mixed $value, bool $try): ?EnumCase {
throw new ValueError("value {$value} cannot be represented as a value in enum ".static::class);
}
}
/**
* tries to match the passed value to one of the enum values
* @param string $name the value to be matched
* @param bool $try whether to return null (true) or throw an error (false) if not found
* @return ?EnumCase the matching enum case or null if not found and $try==true
* @throws ValueError if not found and $try==false
*/
private static function find_from_name(string $name, bool $try): ?EnumCase {
foreach (static::cases() as $case) {
if ($case->name === $name) {
return $case;
}
}

if ($try) {
return null;
} else {
throw new ValueError("name {$name} doesn't exist in ".static::class);
}
}
/**
* tries to match the passed value to one of the enum values
* @param mixed $value the value to be matched
* @return mixed either the matching enum value or null if not found
*/
public static function try_from(mixed $value): mixed {
public static function try_from($value) {
// TODO: replace with nullsafe operator in php8.
$case = static::find($value, true);
if (is_null($case)) {
Expand All @@ -73,16 +93,15 @@ public static function try_from(mixed $value): mixed {
* @return mixed the matching enum value
* @throws ValueError if not found
*/
public static function from(mixed $value): mixed {
public static function from($value) {
return static::find($value, false)->value;
}
/**
* tries to match the passed value to one of the enum values
* @param mixed $value the value to be matched
* @return string the matching enum case name
* @throws mixed either the matching enum case name or null if not found
* @return ?string either the matching enum case name or null if not found
*/
public static function try_name_from(mixed $value): ?string {
public static function try_name_from($value): ?string {
// TODO: replace with nullsafe operator in php8.
$case = static::find($value, true);
if (is_null($case)) {
Expand All @@ -97,9 +116,26 @@ public static function try_name_from(mixed $value): ?string {
* @return string the matching enum case name
* @throws ValueError if not found
*/
public static function name_from(mixed $value): string {
public static function name_from($value): string {
return static::find($value, false)->name;
}
/**
* tries to get a value based on the name
* @param string $name the name to look for
* @return mixed the matching enum case value
* @throws ValueError if not found
*/
public static function get(string $name) {
return static::find_from_name($name, false)->value;
}
/**
* tries to get a value based on the name
* @param string $name the name to look for
* @return ?mixed either the matching enum case value or null if not found
*/
public static function try_get(string $name) {
return static::find_from_name($name, false)->value;
}
/**
* Returns an array of all the cases that exist in this enum
*
Expand Down
6 changes: 2 additions & 4 deletions lbplanner/services/user/delete_user.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,11 @@ public static function delete_user_parameters(): external_function_parameters {
* @throws moodle_exception
*/
public static function delete_user($userid) {
global $DB, $USER;
global $DB;

self::validate_parameters(self::delete_user_parameters(), ['userid' => $userid]);

if (!user_helper::is_admin($USER->id)) {
user_helper::assert_access($userid);
}
user_helper::assert_access($userid);

// Check if User is in user table.
if (!$DB->record_exists(user_helper::LB_PLANNER_USER_TABLE, ['userid' => $userid])) {
Expand Down
Loading