From ecd9b020eb0a9f54564b555316e70ff21123660d Mon Sep 17 00:00:00 2001 From: Ludovico Pavesi Date: Thu, 25 Apr 2024 21:09:25 +0200 Subject: [PATCH] Lint everything --- public/authentication.php | 19 +- public/groups.php | 6 +- public/people.php | 46 ++-- public/personal.php | 28 ++- public/register.php | 28 ++- public/register_done.php | 3 +- public/sir.php | 32 +-- src/Authentication.php | 85 ++++--- src/AuthenticationException.php | 6 +- src/Ldap.php | 372 +++++++++++++++-------------- src/LdapException.php | 6 +- src/OpenIDConnectRefreshClient.php | 16 +- src/Sir.php | 57 +++-- src/SirException.php | 6 +- src/Template.php | 17 +- src/Validation.php | 220 +++++++++-------- src/ValidationException.php | 6 +- templates/400.php | 2 +- templates/403.php | 2 +- templates/404.php | 1 + templates/500.php | 2 +- templates/authenticationeditor.php | 4 +- templates/authenticationform.php | 2 +- templates/base.php | 13 +- templates/grouplist.php | 97 ++++---- templates/index.php | 4 +- templates/logout.php | 1 + templates/navbar.php | 80 +++---- templates/personaleditor.php | 4 +- templates/register_done.php | 1 + templates/registerform.php | 6 +- templates/safety_test.php | 20 +- templates/sessions.php | 1 + templates/tos.php | 1 + templates/usereditor.php | 24 +- templates/userform.php | 26 +- templates/userlist.php | 65 ++--- templates/websiteuserlist.php | 24 +- 38 files changed, 713 insertions(+), 620 deletions(-) diff --git a/public/authentication.php b/public/authentication.php index 07ccc52..d0afecc 100644 --- a/public/authentication.php +++ b/public/authentication.php @@ -9,21 +9,27 @@ $error = null; try { - $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, - CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); - - if(isset($_POST) && !empty($_POST)) { + $ldap = new Ldap( + CRAUTO_LDAP_URL, + CRAUTO_LDAP_BIND_DN, + CRAUTO_LDAP_PASSWORD, + CRAUTO_LDAP_USERS_DN, + CRAUTO_LDAP_GROUPS_DN, + CRAUTO_LDAP_STARTTLS + ); + + if (isset($_POST) && !empty($_POST)) { Validation::handlePasswordChangePost($ldap, $_SESSION['uid'], $_POST); $_SESSION['success'] = 'Password updated successfully'; http_response_code(303); header("Location: authentication.php"); exit; } -} catch(LdapException | ValidationException | InvalidArgumentException $e) { +} catch (LdapException | ValidationException | InvalidArgumentException $e) { $error = $e->getMessage(); } -if(isset($_SESSION['success'])) { +if (isset($_SESSION['success'])) { $success = $_SESSION['success']; unset($_SESSION['success']); } else { @@ -36,4 +42,3 @@ 'error' => $error, 'success' => $success ]); - diff --git a/public/groups.php b/public/groups.php index 75f13ed..888405e 100644 --- a/public/groups.php +++ b/public/groups.php @@ -6,7 +6,7 @@ require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; Authentication::requireLogin(); -if(!Authentication::isAdmin()) { +if (!Authentication::isAdmin()) { $template = Template::create(); echo $template->render('403'); exit; @@ -17,7 +17,7 @@ try { $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); $users = $ldap->getUsersList(new DateTimeZone('Europe/Rome')); -} catch(LdapException $e) { +} catch (LdapException $e) { $error = $e->getMessage(); } @@ -27,5 +27,3 @@ 'users' => $users, 'error' => $error, ]); - - diff --git a/public/people.php b/public/people.php index 22ea454..000de66 100644 --- a/public/people.php +++ b/public/people.php @@ -7,15 +7,15 @@ require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; Authentication::requireLogin(); -if(!Authentication::isAdmin()) { +if (!Authentication::isAdmin()) { $template = Template::create(); echo $template->render('403'); exit; } -if(isset($_GET['uid'])) { - $allowedAttributes = Validation::allowedAttributesAdmin; - $editableAttributes = array_combine(Validation::editableAttributesAdmin, Validation::editableAttributesAdmin); +if (isset($_GET['uid'])) { + $allowedAttributes = Validation::ALLOWED_ATTRIBUTES_ADMIN; + $editableAttributes = array_combine(Validation::EDITABLE_ATTRIBUTES_ADMIN, Validation::EDITABLE_ATTRIBUTES_ADMIN); $targetUid = $_GET['uid']; @@ -23,8 +23,14 @@ $allGroups = []; $error = null; try { - $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, - CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); + $ldap = new Ldap( + CRAUTO_LDAP_URL, + CRAUTO_LDAP_BIND_DN, + CRAUTO_LDAP_PASSWORD, + CRAUTO_LDAP_USERS_DN, + CRAUTO_LDAP_GROUPS_DN, + CRAUTO_LDAP_STARTTLS + ); $attributes = $ldap->getUser($targetUid, array_merge($allowedAttributes, ['createtimestamp', 'modifytimestamp'])); $targetUid = $attributes['uid'] ?? $targetUid; // Canonicalize uid, or use the supplied one // Do not move elsewhere, otherwise you get empty groups in case of errors above here @@ -37,8 +43,8 @@ // useless... $requireOldPasswordForChange = strtolower($_SESSION['uid']) === strtolower($attributes['uid']); - if(isset($_POST) && !empty($_POST)) { - if(isset($_POST['password1'])) { + if (isset($_POST) && !empty($_POST)) { + if (isset($_POST['password1'])) { Validation::handlePasswordChangePost($ldap, $targetUid, $_POST, $requireOldPasswordForChange); } else { Validation::handleUserEditPost($editableAttributes, $ldap, $targetUid, $attributes); @@ -48,12 +54,12 @@ header("Location: ${_SERVER['REQUEST_URI']}"); exit; } - } catch(LdapException | ValidationException | InvalidArgumentException $e) { + } catch (LdapException | ValidationException | InvalidArgumentException $e) { $error = $e->getMessage(); } $groups = []; - foreach($attributes['memberof'] as $dn) { + foreach ($attributes['memberof'] as $dn) { $groups[] = Ldap::groupDnToName($dn); } $attributes['memberof'] = $groups; @@ -69,8 +75,8 @@ 'editableAttributes' => $editableAttributes, 'allowedAttributes' => $allowedAttributes, 'adminRequireOldPassword' => $requireOldPasswordForChange ?? true, - 'allGroups' => $allGroups - ]); + 'allGroups' => $allGroups + ]); } else { $error = null; $users = []; @@ -78,28 +84,28 @@ try { $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); $users = $ldap->getUsersList(new DateTimeZone('Europe/Rome'), $website ? ['degreecourse', 'websitedescription'] : ['websitedescription']); - } catch(LdapException $e) { + } catch (LdapException $e) { $error = $e->getMessage(); } $template = Template::create(); $template->addData(['currentSection' => 'people'], 'navbar'); - if($website) { + if ($website) { $excludedGroups = explode(',', CRAUTO_WEBSITE_IGNORE_GROUPS); $excludedGroups = array_combine($excludedGroups, $excludedGroups); - if(count($excludedGroups) > 0) { + if (count($excludedGroups) > 0) { $usersFiltered = []; - foreach($users as $user) { + foreach ($users as $user) { $groups = $user['memberof'] ?? []; $exclude = false; - foreach($groups as $group) { - if(array_key_exists($group, $excludedGroups)) { + foreach ($groups as $group) { + if (array_key_exists($group, $excludedGroups)) { $exclude = true; break; } } - if(!$exclude) { + if (!$exclude) { $usersFiltered[] = $user; } } @@ -119,5 +125,3 @@ ]); } } - - diff --git a/public/personal.php b/public/personal.php index fb32c70..82dec1f 100644 --- a/public/personal.php +++ b/public/personal.php @@ -7,25 +7,31 @@ require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; Authentication::requireLogin(); -$allowedAttributes = Validation::allowedAttributesUser; -if(Authentication::isAdmin()) { - $editableAttributes = array_combine(Validation::editableAttributesAdmin, Validation::editableAttributesAdmin); +$allowedAttributes = Validation::ALLOWED_ATTRIBUTES_USER; +if (Authentication::isAdmin()) { + $editableAttributes = array_combine(Validation::EDITABLE_ATTRIBUTES_ADMIN, Validation::EDITABLE_ATTRIBUTES_ADMIN); // Some attributes are editable, but only on the "people" page, not on the personal page, where they aren't even shown... $editableAttributes = array_intersect($editableAttributes, $allowedAttributes); } else { - $editableAttributes = array_combine(Validation::editableAttributesUser, Validation::editableAttributesUser); + $editableAttributes = array_combine(Validation::EDITABLE_ATTRIBUTES_USER, Validation::EDITABLE_ATTRIBUTES_USER); } $attributes = []; $allGroups = []; $error = null; try { - $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, - CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); + $ldap = new Ldap( + CRAUTO_LDAP_URL, + CRAUTO_LDAP_BIND_DN, + CRAUTO_LDAP_PASSWORD, + CRAUTO_LDAP_USERS_DN, + CRAUTO_LDAP_GROUPS_DN, + CRAUTO_LDAP_STARTTLS + ); $attributes = $ldap->getUser($_SESSION['uid'], $allowedAttributes); $allGroups = $ldap->getGroups(); - if(isset($_GET['download'])) { + if (isset($_GET['download'])) { header('Content-Type: application/json'); header('Content-Transfer-Encoding: Binary'); header('Content-Description: File Transfer'); @@ -34,18 +40,18 @@ exit; } - if(isset($_POST) && !empty($_POST)) { + if (isset($_POST) && !empty($_POST)) { Validation::handleUserEditPost($editableAttributes, $ldap, $_SESSION['uid'], $attributes); http_response_code(303); header('Location: personal.php'); exit; } -} catch(LdapException | ValidationException | InvalidArgumentException $e) { +} catch (LdapException | ValidationException | InvalidArgumentException $e) { $error = $e->getMessage(); } $groups = []; -foreach($attributes['memberof'] as $dn) { +foreach ($attributes['memberof'] as $dn) { $groups[] = Ldap::groupDnToName($dn); } $attributes['memberof'] = $groups; @@ -59,5 +65,5 @@ 'attributes' => $attributes, 'allowedAttributes' => $allowedAttributes, 'editableAttributes' => $editableAttributes, - 'allGroups' => $allGroups + 'allGroups' => $allGroups ]); diff --git a/public/register.php b/public/register.php index 709941c..bea7036 100644 --- a/public/register.php +++ b/public/register.php @@ -5,7 +5,7 @@ require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; $loggedin = Authentication::isLoggedIn(); -if($loggedin) { +if ($loggedin) { $template = Template::create(); $template->addData(['authenticated' => $loggedin, 'isAdmin' => $loggedin && Authentication::isAdmin()], 'navbar'); echo $template->render('403'); @@ -458,11 +458,17 @@ $template->addData(['authenticated' => $loggedin, 'isAdmin' => $loggedin && Authentication::isAdmin()], 'navbar'); try { - $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, - CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); - if(isset($_GET['invite'])) { + $ldap = new Ldap( + CRAUTO_LDAP_URL, + CRAUTO_LDAP_BIND_DN, + CRAUTO_LDAP_PASSWORD, + CRAUTO_LDAP_USERS_DN, + CRAUTO_LDAP_GROUPS_DN, + CRAUTO_LDAP_STARTTLS + ); + if (isset($_GET['invite'])) { $defaultAttributes = $ldap->getInvitedUser($_GET['invite'], CRAUTO_LDAP_INVITES_DN); - if($defaultAttributes === null) { + if ($defaultAttributes === null) { $template = Template::create(); echo $template->render('403', ['error' => 'Invalid invite code']); exit; @@ -472,7 +478,7 @@ echo $template->render('403', ['error' => 'Missing invite code']); exit; } -} catch(LdapException | ValidationException $e) { +} catch (LdapException | ValidationException $e) { $error = $e->getMessage(); echo $template->render('500', ['error' => $error]); exit; @@ -480,21 +486,21 @@ // Invite code is valid and $defaultAttributes is available, if getting here try { - if(isset($_POST) && !empty($_POST)) { - Validation::handleUserRegisterPost($_POST, Validation::allowedAttributesRegister, $ldap, $degreeCourses, $countries, $province); + if (isset($_POST) && !empty($_POST)) { + Validation::handleUserRegisterPost($_POST, Validation::ALLOWED_ATTRIBUTES_REGISTER, $ldap, $degreeCourses, $countries, $province); $ldap->deleteInvite(CRAUTO_LDAP_INVITES_DN, $_GET['invite']); http_response_code(303); $_SESSION['register_done'] = true; header('Location: register_done.php'); exit; } -} catch(LdapException | ValidationException $e) { +} catch (LdapException | ValidationException $e) { $error = $e->getMessage(); } -if(isset($defaultAttributes['degreecourse'])) { - if(!isset($degreeCourses[$defaultAttributes['degreecourse']])) { +if (isset($defaultAttributes['degreecourse'])) { + if (!isset($degreeCourses[$defaultAttributes['degreecourse']])) { unset($defaultAttributes['degreecourse']); } } diff --git a/public/register_done.php b/public/register_done.php index 6d5dc05..63e8a47 100644 --- a/public/register_done.php +++ b/public/register_done.php @@ -6,7 +6,7 @@ session_start(); -if(isset($_SESSION['register_done'])) { +if (isset($_SESSION['register_done'])) { unset($_SESSION['register_done']); $template = Template::create(); echo $template->render('register_done'); @@ -15,4 +15,3 @@ $template->addData(['authenticated' => Authentication::isLoggedIn(), 'isAdmin' => Authentication::isLoggedIn() && Authentication::isAdmin()], 'navbar'); echo $template->render('403'); } - diff --git a/public/sir.php b/public/sir.php index 43cb87e..3b0ff64 100644 --- a/public/sir.php +++ b/public/sir.php @@ -6,13 +6,13 @@ require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; Authentication::requireLogin(); -if(!Authentication::isAdmin()) { +if (!Authentication::isAdmin()) { $template = Template::create(); echo $template->render('403'); exit; } -if(isset($_GET['uid'])) { +if (isset($_GET['uid'])) { $targetUid = $_GET['uid']; $getTheseAttributes = [ 'givenname', @@ -23,24 +23,30 @@ ]; try { - $ldap = new Ldap(CRAUTO_LDAP_URL, CRAUTO_LDAP_BIND_DN, CRAUTO_LDAP_PASSWORD, CRAUTO_LDAP_USERS_DN, - CRAUTO_LDAP_GROUPS_DN, CRAUTO_LDAP_STARTTLS); + $ldap = new Ldap( + CRAUTO_LDAP_URL, + CRAUTO_LDAP_BIND_DN, + CRAUTO_LDAP_PASSWORD, + CRAUTO_LDAP_USERS_DN, + CRAUTO_LDAP_GROUPS_DN, + CRAUTO_LDAP_STARTTLS + ); $attributes = $ldap->getUser($targetUid, $getTheseAttributes); - if($attributes === null) { + if ($attributes === null) { $template = Template::create(); echo $template->render('404'); exit; } - foreach($getTheseAttributes as $name) { - if(!array_key_exists($name, $attributes)) { + foreach ($getTheseAttributes as $name) { + if (!array_key_exists($name, $attributes)) { throw new InvalidArgumentException("$name is required"); } $attr = $attributes[$name]; - if(is_array($attr) && count($attr) <= 0) { + if (is_array($attr) && count($attr) <= 0) { throw new InvalidArgumentException("$name is empty (and multivalued)"); } - if($attr === null || $attr === '') { + if ($attr === null || $attr === '') { throw new InvalidArgumentException("$name is empty"); } } @@ -62,12 +68,11 @@ readfile($pdf); exit; - - } catch(LdapException | SirException | ValidationException | InvalidArgumentException $e) { + } catch (LdapException | SirException | ValidationException | InvalidArgumentException $e) { $error = $e->getMessage(); } - if($error !== null) { + if ($error !== null) { $template = Template::create(); echo $template->render('500', [ 'error' => $error, @@ -75,12 +80,9 @@ exit; } - } else { $template = Template::create(); echo $template->render('400', ['error' => 'For which user?']); exit; } - - diff --git a/src/Authentication.php b/src/Authentication.php index e07c0be..396e6e6 100644 --- a/src/Authentication.php +++ b/src/Authentication.php @@ -1,8 +1,10 @@ signOut($token, CRAUTO_URL . '/logout_done.php'); @@ -117,14 +123,16 @@ public static function signOut() { * * @return bool True if id token is expired, false otherwise */ - private static function idTokenExpired(int $expires): bool { + private static function idTokenExpired(int $expires): bool + { return $expires <= time(); } /** * Redirect to login page and stop execution. */ - private static function redirectToLogin() { + private static function redirectToLogin() + { $_SESSION['redirect_after_login'] = $_SERVER['REQUEST_URI']; http_response_code(303); header("Location: /login.php"); @@ -137,7 +145,8 @@ private static function redirectToLogin() { * @return bool If execution can continue or not (in case a redirect header has been set) * @throws AuthenticationException */ - private static function performRefresh(): bool { + private static function performRefresh(): bool + { /* * So, everyone is handling this thing differently. * From what I've gathered, the best and most secure way to handle this is to issue a somewhat short lived @@ -158,7 +167,7 @@ private static function performRefresh(): bool { * WSO2 IS doesn't delete tokens when it's restarted. * SAML2 single sign-out doesn't invalidate anything from OIDC sessions (so it's not a real single sign-out). */ - if(!isset($_SESSION['refresh_token'])) { + if (!isset($_SESSION['refresh_token'])) { throw new LogicException('No refresh token available'); } $oidc = self::getOidc(true); @@ -167,9 +176,9 @@ private static function performRefresh(): bool { // For an explanation, see: // https://github.com/WEEE-Open/tarallo/blob/89ffe90a042054cc40c886253a58ce64527b3420/src/HTTP/AuthManager.php#L344-L433 - if(isset($json->error)) { + if (isset($json->error)) { throw new AuthenticationException($json->error_description ?? $json->error); - } elseif(isset($json->id_token) && isset($json->access_token)) { + } elseif (isset($json->id_token) && isset($json->access_token)) { // Exhibit A: OIDC Tokens and Despair // This should return a new access token and a new refresh token. @@ -207,10 +216,10 @@ private static function performRefresh(): bool { try { // Validate the ID token signature $valid = $oidc->verifyJWTsignature($json->id_token); - if(!$valid) { + if (!$valid) { throw new AuthenticationException('Invalid JWT signature'); } - } catch(OpenIDConnectClientException $e) { + } catch (OpenIDConnectClientException $e) { throw new AuthenticationException('OpenIDConnectClientException: ' . $e->getMessage()); } @@ -230,12 +239,12 @@ private static function performRefresh(): bool { $method = new ReflectionMethod($oidc, 'verifyJWTclaims'); $method->setAccessible(true); $valid = $method->invoke($oidc, $claims, $json->access_token); - if(!$valid) { + if (!$valid) { throw new AuthenticationException('verifyJWTclaims failed'); } - } catch(ReflectionException $e) { + } catch (ReflectionException $e) { throw new AuthenticationException('ReflectionException: ' . $e->getMessage()); - } /** @noinspection PhpRedundantCatchClauseInspection */ catch(OpenIDConnectClientException $e) { + } /** @noinspection PhpRedundantCatchClauseInspection */ catch (OpenIDConnectClientException $e) { throw new AuthenticationException('JWT claims validation failed: ' . $e->getMessage()); } @@ -248,7 +257,8 @@ private static function performRefresh(): bool { throw new AuthenticationException('No id token in refresh token response'); } - private static function returnToPreviousPage() { + private static function returnToPreviousPage() + { // Comes from $_SERVER['REQUEST_URI'] which is already url encoded $location = $_SESSION['redirect_after_login'] ?? '/'; http_response_code(303); @@ -261,10 +271,11 @@ private static function returnToPreviousPage() { * * @return OpenIDConnectClient|OpenIDConnectRefreshClient */ - private static function getOidc(bool $refresh = false) { + private static function getOidc(bool $refresh = false) + { require_once '..' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php'; - if($refresh) { + if ($refresh) { $oidc = new OpenIDConnectRefreshClient(CRAUTO_OIDC_ISSUER, CRAUTO_OIDC_CLIENT_KEY, CRAUTO_OIDC_CLIENT_SECRET); } else { $oidc = new OpenIDConnectClient(CRAUTO_OIDC_ISSUER, CRAUTO_OIDC_CLIENT_KEY, CRAUTO_OIDC_CLIENT_SECRET); @@ -276,8 +287,9 @@ private static function getOidc(bool $refresh = false) { return $oidc; } - private static function setAttributes(OpenIDConnectClient $oidc, $claims = null, ?string $idt = null) { - if($claims) { + private static function setAttributes(OpenIDConnectClient $oidc, $claims = null, ?string $idt = null) + { + if ($claims) { // Convert array (or stdObj) to stdObj. $claims = (object) $claims; } else { @@ -327,7 +339,8 @@ private static function setAttributes(OpenIDConnectClient $oidc, $claims = null, * * @return bool */ - public static function isAdmin(): bool { + public static function isAdmin(): bool + { // For WSO2 IS: //$groups = Authentication::splitGroups($_SESSION['groups']); //return isset($groups['HR']); diff --git a/src/AuthenticationException.php b/src/AuthenticationException.php index 218e4c2..e44b395 100644 --- a/src/AuthenticationException.php +++ b/src/AuthenticationException.php @@ -1,11 +1,9 @@ ['io'], 'websitedescription' => "Il capo supremo\nSu due righe", 'description' => '', - 'nsaccountlock' => null - ], - 'alice' => [ - 'uid' => 'alice', - 'cn' => 'Alice Test', - 'givenname' => 'Alice', - 'sn' => 'Test', - 'memberof' => ["cn=Cloud,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it", "cn=Riparatori,ou=Groups,dc=weeeopen,dc=it"] , - 'createtimestamp' => '20191025105022Z', - 'modifytimestamp' => '20191025155317Z', - 'safetytestdate' => '20991104', - 'signedsir' => null, - 'haskey' => null, - 'schacpersonaluniquecode' => 's22222', - 'telegramid' => null, - 'telegramnickname' => null, - 'sshpublickey' => [], - 'weeelabnickname' => [], - 'websitedescription' => 'Persona', - 'description' => '', - 'nsaccountlock' => 'true' - ], - 'brodino' => [ - 'uid' => 'brodino', - 'cn' => 'Bro Dino', - 'givenname' => 'Bro', - 'sn' => 'Dino', - 'memberof' => ["cn=Admin,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it"], - 'createtimestamp' => '20191025105022Z', - 'modifytimestamp' => '20191025155317Z', - 'safetytestdate' => '20201104', - 'signedsir' => 'true', - 'haskey' => null, - 'nsaccountlock' => 'true', - 'telegramid' => '123456789', - 'schacpersonaluniquecode' => 's333333', - 'sshpublickey' => [], - 'weeelabnickname' => [], - 'description' => '', - 'telegramnickname' => 'brodino' - ], + 'nsaccountlock' => null + ], + 'alice' => [ + 'uid' => 'alice', + 'cn' => 'Alice Test', + 'givenname' => 'Alice', + 'sn' => 'Test', + 'memberof' => ["cn=Cloud,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it", "cn=Riparatori,ou=Groups,dc=weeeopen,dc=it"] , + 'createtimestamp' => '20191025105022Z', + 'modifytimestamp' => '20191025155317Z', + 'safetytestdate' => '20991104', + 'signedsir' => null, + 'haskey' => null, + 'schacpersonaluniquecode' => 's22222', + 'telegramid' => null, + 'telegramnickname' => null, + 'sshpublickey' => [], + 'weeelabnickname' => [], + 'websitedescription' => 'Persona', + 'description' => '', + 'nsaccountlock' => 'true' + ], + 'brodino' => [ + 'uid' => 'brodino', + 'cn' => 'Bro Dino', + 'givenname' => 'Bro', + 'sn' => 'Dino', + 'memberof' => ["cn=Admin,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it"], + 'createtimestamp' => '20191025105022Z', + 'modifytimestamp' => '20191025155317Z', + 'safetytestdate' => '20201104', + 'signedsir' => 'true', + 'haskey' => null, + 'nsaccountlock' => 'true', + 'telegramid' => '123456789', + 'schacpersonaluniquecode' => 's333333', + 'sshpublickey' => [], + 'weeelabnickname' => [], + 'description' => '', + 'telegramnickname' => 'brodino' + ], 'bob' => [ 'uid' => 'bob', 'cn' => 'Bob "Il grande testatore" Testington', @@ -94,53 +94,55 @@ class Ldap { 'description' => '', 'nsaccountlock' => null ], - 'broski' => [ - 'uid' => 'broski', - 'cn' => 'Bro Ski', - 'givenname' => 'Bro', - 'sn' => 'Ski', - 'memberof' => ["cn=Admin,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it"], - 'createtimestamp' => '20191025105022Z', - 'modifytimestamp' => '20191025155317Z', - 'safetytestdate' => '20201025', - 'signedsir' => null, - 'haskey' => null, - 'nsaccountlock' => null, - 'schacpersonaluniquecode' => 's4444444', - 'telegramnickname' => null, - 'sshpublickey' => [], - 'weeelabnickname' => [], - 'description' => '', - 'telegramid' => '123456789' - ], + 'broski' => [ + 'uid' => 'broski', + 'cn' => 'Bro Ski', + 'givenname' => 'Bro', + 'sn' => 'Ski', + 'memberof' => ["cn=Admin,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it"], + 'createtimestamp' => '20191025105022Z', + 'modifytimestamp' => '20191025155317Z', + 'safetytestdate' => '20201025', + 'signedsir' => null, + 'haskey' => null, + 'nsaccountlock' => null, + 'schacpersonaluniquecode' => 's4444444', + 'telegramnickname' => null, + 'sshpublickey' => [], + 'weeelabnickname' => [], + 'description' => '', + 'telegramid' => '123456789' + ], ]; private const EXAMPLE_GROUPS = ['Admin', 'Persone', 'Cloud']; - public function __construct(string $url, string $bindDn, string $password, string $usersDn, string $groupsDn, bool $startTls = true) { + public function __construct(string $url, string $bindDn, string $password, string $usersDn, string $groupsDn, bool $startTls = true) + { $this->url = $url; $this->starttls = $startTls; $this->groupsDn = $groupsDn; $this->usersDn = $usersDn; - if(defined('TEST_MODE') && TEST_MODE) { + if (defined('TEST_MODE') && TEST_MODE) { error_log('TEST_MODE, not connecting to LDAP'); return; } $this->ds = ldap_connect($url); - if(!$this->ds) { + if (!$this->ds) { throw new LdapException('Cannot connect to LDAP server'); } - if($startTls) { - if(!ldap_start_tls($this->ds)) { + if ($startTls) { + if (!ldap_start_tls($this->ds)) { throw new LdapException('Cannot STARTTLS with LDAP server'); } } - if(!ldap_bind($this->ds, $bindDn, $password)) { + if (!ldap_bind($this->ds, $bindDn, $password)) { throw new LdapException('Bind with LDAP server failed'); } } - private static function usernameify(string $string): string { - if(extension_loaded('iconv')) { + private static function usernameify(string $string): string + { + if (extension_loaded('iconv')) { $string = preg_replace("/[^\p{L}]/u", '', $string); $string = iconv('utf-8', 'us-ascii//TRANSLIT', $string); } else { @@ -149,76 +151,81 @@ private static function usernameify(string $string): string { return strtolower($string); } - public function getUser(string $uid, ?array $attributes = null): ?array { - if(defined('TEST_MODE') && TEST_MODE) { + public function getUser(string $uid, ?array $attributes = null): ?array + { + if (defined('TEST_MODE') && TEST_MODE) { error_log('TEST_MODE, returning sample user'); return self::EXAMPLE_USERS[$uid]; } $sr = $this->searchByUid($uid, $attributes); - if($sr === null) { + if ($sr === null) { return null; } $user = ldap_get_entries($this->ds, $sr)[0]; $user = self::simplify($user); - if($attributes !== null) { + if ($attributes !== null) { $user = self::fillAndSortAttributes($user, $attributes); } return $user; } - public function getInvitedUser(string $inviteCode, string $invitesDn): ?array { + public function getInvitedUser(string $inviteCode, string $invitesDn): ?array + { $sr = $this->searchByInvite($inviteCode, $invitesDn, ['givenname', 'sn', 'mail', 'schacpersonaluniquecode', 'degreecourse', 'telegramid', 'telegramnickname']); - if($sr === null) { + if ($sr === null) { return null; } $attr = ldap_get_entries($this->ds, $sr)[0]; $attr = self::simplify($attr); - if(isset($attr['givenname']) && isset($attr['sn'])) { + if (isset($attr['givenname']) && isset($attr['sn'])) { $attr['uid'] = self::usernameify($attr['givenname']) . '.' . self::usernameify($attr['sn']); } return $attr; } - public function getGroups(): array { - if(defined('TEST_MODE') && TEST_MODE) { - error_log('TEST_MODE, returning sample groups'); - return self::EXAMPLE_GROUPS; - } else { - $attributes = ['cn']; - $sr = ldap_search($this->ds, $this->groupsDn, '(cn=*)'); - if(!$sr) { - throw new LdapException('Cannot search groups'); - } - - $simpler = $this->simplifyAll($sr, $attributes); - - $groups = []; - foreach($simpler as $entry) { - if(isset($entry['cn'])) { - $groups[] = $entry['cn']; - } - } - - return $groups; - } - } - - public function getUserDn(string $uid): string { + public function getGroups(): array + { + if (defined('TEST_MODE') && TEST_MODE) { + error_log('TEST_MODE, returning sample groups'); + return self::EXAMPLE_GROUPS; + } else { + $attributes = ['cn']; + $sr = ldap_search($this->ds, $this->groupsDn, '(cn=*)'); + if (!$sr) { + throw new LdapException('Cannot search groups'); + } + + $simpler = $this->simplifyAll($sr, $attributes); + + $groups = []; + foreach ($simpler as $entry) { + if (isset($entry['cn'])) { + $groups[] = $entry['cn']; + } + } + + return $groups; + } + } + + public function getUserDn(string $uid): string + { $sr = $this->searchByUid($uid, ['entrydn']); - if($sr === null) { + if ($sr === null) { throw new LdapException('Cannot find DN for user'); } $theOnlyResult = ldap_first_entry($this->ds, $sr); return ldap_get_dn($this->ds, $theOnlyResult); } - public function getUsers(array $attributes): array { - if(defined('TEST_MODE') && TEST_MODE) { + public function getUsers(array $attributes): array + { + if (defined('TEST_MODE') && TEST_MODE) { error_log('TEST_MODE, returning sample users'); return array_values(self::EXAMPLE_USERS); } - if(version_compare(PHP_VERSION, '7.3', '>=')) { + if (version_compare(PHP_VERSION, '7.3', '>=')) { // From PHP 7.3 onward, the serverctrls parameter is available. This is the only reasonable way to have the results sorted. // Well, if there's more than one page which is actually not supported, but let's use it anyway. $serverctrls = [ @@ -241,13 +248,15 @@ public function getUsers(array $attributes): array { } else { $sr = ldap_search($this->ds, $this->usersDn, '(uid=*)', $attributes); } - if(!$sr) { + if (!$sr) { throw new LdapException('Cannot search users'); } $simpler = $this->simplifyAll($sr, $attributes); - usort($simpler, function(array $a, array $b): int { return strcasecmp($a['uid'], $b['uid']); }); + usort($simpler, function (array $a, array $b): int { + return strcasecmp($a['uid'], $b['uid']); + }); return $simpler; } @@ -258,69 +267,73 @@ public function getUsers(array $attributes): array { * @return resource|null $sr from ldap_search or none if no users are found * @throws LdapException if cannot search or more than one user is found */ - private function searchByUid(string $uid, ?array $attributes = null) { + private function searchByUid(string $uid, ?array $attributes = null) + { $uid = ldap_escape($uid, '', LDAP_ESCAPE_FILTER); $sr = ldap_search($this->ds, $this->usersDn, "(uid=$uid)", $attributes); - if(!$sr) { + if (!$sr) { throw new LdapException('Cannot search for uid'); } $count = ldap_count_entries($this->ds, $sr); - if($count === 0) { + if ($count === 0) { return null; - } else if($count > 1) { + } elseif ($count > 1) { throw new LdapException("$uid is not unique in $this->usersDn, $count results found"); } return $sr; } - private function searchByInvite(string $inviteCode, string $invitesDn, ?array $attributes = null) { + private function searchByInvite(string $inviteCode, string $invitesDn, ?array $attributes = null) + { $inviteCode = ldap_escape($inviteCode, '', LDAP_ESCAPE_FILTER); $sr = ldap_search($this->ds, $invitesDn, "(inviteCode=$inviteCode)", $attributes); - if(!$sr) { + if (!$sr) { throw new LdapException('Cannot search for invite code'); } $count = ldap_count_entries($this->ds, $sr); - if($count === 0) { + if ($count === 0) { return null; - } else if($count > 1) { + } elseif ($count > 1) { throw new LdapException("Duplicate invite code, $count results found"); } return $sr; } - public function updatePassword(string $dn, string $password) { + public function updatePassword(string $dn, string $password) + { $result = ldap_mod_replace($this->ds, $dn, ['userPassword' => $password]); - if(!$result) { + if (!$result) { throw new LdapException('Cannot update password: ' . ldap_error($this->ds)); } } - public function updateUser(string $uid, array $replace, array $previous) { + public function updateUser(string $uid, array $replace, array $previous) + { $dn = $this->getUserDn($uid); $modlist = []; - foreach($replace as $attr => $values) { - if($attr === 'memberof') { + foreach ($replace as $attr => $values) { + if ($attr === 'memberof') { continue; } // Something changed - if(!self::attrEquals($previous[$attr], $values)) { + if (!self::attrEquals($previous[$attr], $values)) { // Values needs to be an array for modlist - if($values === null) { + if ($values === null) { $values = []; - } elseif(!is_array($values)) { + } elseif (!is_array($values)) { $values = [$values]; } - if(count($values) > 0 && self::isEmpty($attr, $previous)) { + if (count($values) > 0 && self::isEmpty($attr, $previous)) { // Does not exist: add $modlist[] = [ "attrib" => $attr, "modtype" => LDAP_MODIFY_BATCH_ADD, "values" => $values ]; - } elseif(count($values) <= 0) { + } elseif (count($values) <= 0) { // Actually delete (had a value, now has none) $modlist[] = [ "attrib" => $attr, @@ -336,7 +349,7 @@ public function updateUser(string $uid, array $replace, array $previous) { } } } - if(isset($replace['memberof'])) { + if (isset($replace['memberof'])) { $replace['memberof'] = $replace['memberof'] ?? []; $previousMembership = $previous['memberof'] ?? []; $removedGroups = array_diff($previousMembership, $replace['memberof']); @@ -344,28 +357,29 @@ public function updateUser(string $uid, array $replace, array $previous) { $entry = [ 'member' => $dn, ]; - foreach($addedGroups as $group) { + foreach ($addedGroups as $group) { $result = ldap_mod_add($this->ds, $group, $entry); - if(!$result) { + if (!$result) { throw new LdapException("Cannot add $dn to $group"); } } - foreach($removedGroups as $group) { + foreach ($removedGroups as $group) { $result = ldap_mod_del($this->ds, $group, $entry); - if(!$result) { + if (!$result) { throw new LdapException("Cannot remove $dn from $group"); } } } - if(!empty($modlist)) { + if (!empty($modlist)) { $result = ldap_modify_batch($this->ds, $dn, $modlist); - if($result === false) { + if ($result === false) { throw new LdapException('Modification failed (' . ldap_error($this->ds) . ')'); } } } - public function addUser(array $edited) { + public function addUser(array $edited) + { $edited['objectClass'] = [ 'schacLinkageIdentifiers', 'schacPersonalCharacteristics', @@ -375,12 +389,13 @@ public function addUser(array $edited) { ]; $dn = 'uid=' . ldap_escape($edited['uid'], '', LDAP_ESCAPE_DN) . ',' . $this->usersDn; $result = ldap_add($this->ds, $dn, $edited); - if($result === false) { + if ($result === false) { throw new LdapException('User add failed (' . ldap_error($this->ds) . ')'); } } - public function getUsersList(DateTimeZone $tz, array $moreAttrs = []): array { + public function getUsersList(DateTimeZone $tz, array $moreAttrs = []): array + { $users = $this->getUsers(array_merge([ 'uid', 'cn', @@ -396,15 +411,15 @@ public function getUsersList(DateTimeZone $tz, array $moreAttrs = []): array { 'createtimestamp', ], $moreAttrs)); - foreach($users as &$user) { - if(isset($user['memberof'])) { + foreach ($users as &$user) { + if (isset($user['memberof'])) { $groups = []; - foreach($user['memberof'] as $dn) { + foreach ($user['memberof'] as $dn) { $groups[] = Ldap::groupDnToName($dn); } $user['memberof'] = $groups; } - if(isset($user['safetytestdate'])) { + if (isset($user['safetytestdate'])) { $user['safetytestdate'] = DateTime::createFromFormat('Ymd', $user['safetytestdate'], $tz); } } @@ -412,26 +427,28 @@ public function getUsersList(DateTimeZone $tz, array $moreAttrs = []): array { return $users; } - public function deleteInvite(string $invitesDn, string $inviteCode) { + public function deleteInvite(string $invitesDn, string $inviteCode) + { $sr = $this->searchByInvite($inviteCode, $invitesDn, ['entrydn']); - if($sr !== null) { + if ($sr !== null) { $theOnlyResult = ldap_first_entry($this->ds, $sr); $dn = ldap_get_dn($this->ds, $theOnlyResult); ldap_delete($this->ds, $dn); // TODO: check result, if DN does not exist then it is deleted - if(!$dn) { + if (!$dn) { throw new LdapException('Cannot delete invite'); } } } - protected static function simplify(array $result): array { + protected static function simplify(array $result): array + { $things = []; - foreach($result as $k => $v) { + foreach ($result as $k => $v) { // dn seems to be always null!? - if(!is_int($k) && $k !== 'count' && $k !== 'dn') { + if (!is_int($k) && $k !== 'count' && $k !== 'dn') { $attr = strtolower($k); // Should be already done, but repeat it anyway - if($v['count'] === 1 && !isset(self::$multivalued[$k])) { + if ($v['count'] === 1 && !isset(self::$multivalued[$k])) { $things[$attr] = $v[0]; } else { $things[$attr] = array_diff_key($v, ['count' => true]); @@ -441,13 +458,14 @@ protected static function simplify(array $result): array { return $things; } - protected static function fillAndSortAttributes(array $result, array $attributes): array { + protected static function fillAndSortAttributes(array $result, array $attributes): array + { $sorted = []; - foreach($attributes as $attribute) { - if(isset($result[$attribute])) { + foreach ($attributes as $attribute) { + if (isset($result[$attribute])) { $sorted[$attribute] = $result[$attribute]; } else { - if(isset(self::$multivalued[$attribute])) { + if (isset(self::$multivalued[$attribute])) { $sorted[$attribute] = []; } else { $sorted[$attribute] = null; @@ -457,27 +475,29 @@ protected static function fillAndSortAttributes(array $result, array $attributes return $sorted; } - public static function groupDnToName(string $dn): string { + public static function groupDnToName(string $dn): string + { $pieces = ldap_explode_dn($dn, 1); - if($pieces['count'] === 4 && strtolower($pieces[1]) === 'groups') { + if ($pieces['count'] === 4 && strtolower($pieces[1]) === 'groups') { return $pieces[0]; } throw new InvalidArgumentException("$dn is not a group DN"); } - public function groupNamesToDn(array $names): array { - if(count($names) <= 0) { + public function groupNamesToDn(array $names): array + { + if (count($names) <= 0) { return []; } $escaped = []; $results = []; - foreach($names as $name) { + foreach ($names as $name) { $escaped[] = 'cn=' . ldap_escape($name, '', LDAP_ESCAPE_FILTER); $results[strtolower($name)] = null; } $filter = '(|(' . implode(')(', $escaped) . '))'; $sr = ldap_search($this->ds, $this->groupsDn, $filter, ['dn']); - if(!$sr) { + if (!$sr) { throw new LdapException('Cannot search groups'); } @@ -488,61 +508,67 @@ public function groupNamesToDn(array $names): array { $results[$groupCn] = $dn; } while ($entry = ldap_next_entry($this->ds, $entry)); - foreach($results as $name => $dn) { - if($dn === null) { + foreach ($results as $name => $dn) { + if ($dn === null) { throw new LdapException("Cannot find group '$name'", 1); } } - if(count($results) !== count($names)) { + if (count($results) !== count($names)) { throw new LdapException('Groups mismatch, converted names ' . implode(', ', $names) . ' to DNs ' . implode(' ', $results), 1); } return array_values($results); } - private static function attrEquals($a, $b): bool { - if(is_array($a) && is_array($b)) { + private static function attrEquals($a, $b): bool + { + if (is_array($a) && is_array($b)) { return self::arrayEquals($a, $b); } return $a === $b; } - private static function arrayEquals(array $a, array $b): bool { - if(count($a) !== count($b)) { + private static function arrayEquals(array $a, array $b): bool + { + if (count($a) !== count($b)) { return false; } - if(!empty(array_diff($a, $b))) { + if (!empty(array_diff($a, $b))) { return false; } - if(!empty(array_diff($b, $a))) { + if (!empty(array_diff($b, $a))) { return false; } return true; } - private static function isEmpty(string $attr, array $attributes): bool { + private static function isEmpty(string $attr, array $attributes): bool + { return $attributes[$attr] === null || (is_array($attributes[$attr]) && count($attributes[$attr]) === 0); } - public function getUrl(): string { + public function getUrl(): string + { return $this->url; } - public function getStarttls(): bool { + public function getStarttls(): bool + { return $this->starttls; } - private function simplifyAll($sr, array $attributes): array { + private function simplifyAll($sr, array $attributes): array + { $count = ldap_count_entries($this->ds, $sr); - if($count === 0) { + if ($count === 0) { return []; } $entries = ldap_get_entries($this->ds, $sr); $simpler = []; - foreach($entries as $k => $entry) { - if($k !== 'count') { + foreach ($entries as $k => $entry) { + if ($k !== 'count') { $user = self::simplify($entry); $user = self::fillAndSortAttributes($user, $attributes); $simpler[] = $user; diff --git a/src/LdapException.php b/src/LdapException.php index 53464a9..d6b5ad9 100644 --- a/src/LdapException.php +++ b/src/LdapException.php @@ -1,11 +1,9 @@ setNonce($nonce); } - protected function setNonce($nonce) { + protected function setNonce($nonce) + { $this->nonce = $nonce; return $nonce; } - protected function getNonce() { + protected function getNonce() + { return $this->nonce; } - protected function startSession() { + protected function startSession() + { error_log('startSession called, override mode methods to prevent this'); } } diff --git a/src/Sir.php b/src/Sir.php index ec59464..dbfd6ce 100644 --- a/src/Sir.php +++ b/src/Sir.php @@ -1,18 +1,18 @@ directory = $directory; @@ -21,20 +21,22 @@ public function __construct(string $directory) { } /** @noinspection PhpSameParameterValueInspection */ - private function definationFilePath(string $filename, string $ext): string { + private function definationFilePath(string $filename, string $ext): string + { return "$this->directory/output/$filename.$ext"; } - public function getSir(string $targetUid, array $replacements): string { - if(str_starts_with(strtolower($replacements['[CDL]']), 'dottorato')) { + public function getSir(string $targetUid, array $replacements): string + { + if (str_starts_with(strtolower($replacements['[CDL]']), 'dottorato')) { $template = $this->directory . '/template-dottorandi.csv'; } else { $template = $this->directory . '/template-studenti.csv'; } - $filename = "sir-$targetUid-".sha1(var_export($replacements, 1)); + $filename = "sir-$targetUid-" . sha1(var_export($replacements, 1)); $pdf = $this->definationFilePath($filename, 'pdf'); - if(is_file($pdf)) { + if (is_file($pdf)) { return $pdf; } @@ -43,11 +45,12 @@ public function getSir(string $targetUid, array $replacements): string { return $pdf; } - private function generateSir(string $filename, string $template, array $replacements): void { + private function generateSir(string $filename, string $template, array $replacements): void + { $parsed = $this->readCsvTemplate($template); $keys = array_keys($replacements); $values = array_values($replacements); - foreach($parsed as &$lineRef) { + foreach ($parsed as &$lineRef) { $lineRef[0] = intval($lineRef[0]); // page $lineRef[1] = intval($lineRef[1]); // x $lineRef[2] = intval($lineRef[2]); // y @@ -56,7 +59,7 @@ private function generateSir(string $filename, string $template, array $replacem } $fmod = $this->directory . '/F-MOD-LABORATORI.pdf'; $input = fopen($fmod, "r"); - if($input === false) { + if ($input === false) { throw new SirException("Cannot open template file $fmod"); } try { @@ -64,14 +67,14 @@ private function generateSir(string $filename, string $template, array $replacem $pdf->setSourceFile($input); // There's no way to get the page count from the template file, apparently - for($page = 1; $page <= 3; $page++) { + for ($page = 1; $page <= 3; $page++) { $tmplPage = $pdf->importPage($page); $pdf->AddPage(); $pdf->useTemplate($tmplPage, 0, 0, null, null, true); - foreach($parsed as $line) { - if($line[0] === $page) { + foreach ($parsed as $line) { + if ($line[0] === $page) { $pdf->SetFont('Courier', '', $line[3]); $pdf->SetXY($line[1], $line[2]); $pdf->Write(8, $line[4]); @@ -80,22 +83,23 @@ private function generateSir(string $filename, string $template, array $replacem } $pdf->Output("F", $filename); - } catch(PdfParserException $e) { + } catch (PdfParserException $e) { throw new SirException("Cannot parse $fmod: " . $e->getMessage()); - } catch(PdfReaderException $e) { + } catch (PdfReaderException $e) { throw new SirException("Cannot read $fmod: " . $e->getMessage()); } finally { fclose($input); } } - private function ensureDirectory(string $directory): void { - if(!is_dir($directory)) { - if(!mkdir($directory, 0750, true)) { + private function ensureDirectory(string $directory): void + { + if (!is_dir($directory)) { + if (!mkdir($directory, 0750, true)) { throw new SirException("$directory is not a directory and cannot be created"); } } - if(!is_writable($directory)) { + if (!is_writable($directory)) { throw new SirException("$directory is not writable"); } } @@ -109,19 +113,20 @@ private function ensureDirectory(string $directory): void { // } // } - protected function readCsvTemplate(string $template): array { + protected function readCsvTemplate(string $template): array + { $result = []; $row = 0; $handle = fopen($template, "r"); - if($handle === false) { + if ($handle === false) { throw new SirException("Cannot open template $template"); } try { - while(($data = fgetcsv($handle)) !== false) { + while (($data = fgetcsv($handle)) !== false) { $row++; $x = count($data); - if($x != 5) { + if ($x != 5) { throw new SirException("Error reading template $template at row $row, expected 4 fields but found " . $x); } $result[] = $data; diff --git a/src/SirException.php b/src/SirException.php index 3eef24b..03dedcc 100644 --- a/src/SirException.php +++ b/src/SirException.php @@ -1,11 +1,9 @@ addData([ @@ -16,17 +17,19 @@ public static function create(): Plates { return $engine; } - public static function telegramColumn($nickname, $id): string { - if(isset($nickname)) { + public static function telegramColumn($nickname, $id): string + { + if (isset($nickname)) { return '@' . $nickname; - } elseif(isset($id)) { + } elseif (isset($id)) { return 'ID Only'; } else { return 'N/A'; } } - public static function shortListEntry(string $uid, string $cn, ?string $schacpersonaluniquecode): string { + public static function shortListEntry(string $uid, string $cn, ?string $schacpersonaluniquecode): string + { $schacpersonaluniquecode = $schacpersonaluniquecode ?? 'no matricola'; return /** @lang HTML */ "$cn, $schacpersonaluniquecode Get SIR"; } diff --git a/src/Validation.php b/src/Validation.php index fa0c35e..d3fc393 100644 --- a/src/Validation.php +++ b/src/Validation.php @@ -1,6 +1,5 @@ $v) { + protected static function normalize(Ldap $ldap, array $inputs): array + { + foreach ($inputs as $k => $v) { $inputs[$k] = trim($v); - if($v === '') { + if ($v === '') { $inputs[$k] = null; } } - if(self::hasValue('telegramid', $inputs)) { + if (self::hasValue('telegramid', $inputs)) { $inputs['telegramid'] = (string) ((int) $inputs['telegramid']); } - if(self::hasValue('nsaccountlock', $inputs)) { + if (self::hasValue('nsaccountlock', $inputs)) { $inputs['nsaccountlock'] = boolval($inputs['nsaccountlock']) ? 'true' : ''; } - if(self::hasValue('haskey', $inputs)) { + if (self::hasValue('haskey', $inputs)) { $inputs['haskey'] = boolval($inputs['haskey']) ? 'true' : ''; } - if(self::hasValue('signedsir', $inputs)) { + if (self::hasValue('signedsir', $inputs)) { $inputs['signedsir'] = boolval($inputs['signedsir']) ? 'true' : ''; } - if(self::hasValue('schacpersonaluniquecode', $inputs)) { + if (self::hasValue('schacpersonaluniquecode', $inputs)) { $id = $inputs['schacpersonaluniquecode']; $letter = substr($id, 0, 1); $letter = strtolower($letter); - if(ctype_digit($letter)) { + if (ctype_digit($letter)) { $numbers = $id; $letter = 's'; } else { @@ -126,53 +127,59 @@ protected static function normalize(Ldap $ldap, array $inputs): array { } $inputs['schacpersonaluniquecode'] = $letter . $numbers; } - if(self::hasValue('schacdateofbirth', $inputs)) { - if(preg_match('#^\d{4}-\d{2}-\d{2}$#u', $inputs['schacdateofbirth']) !== 1) { + if (self::hasValue('schacdateofbirth', $inputs)) { + if (preg_match('#^\d{4}-\d{2}-\d{2}$#u', $inputs['schacdateofbirth']) !== 1) { throw new ValidationException('Date of birth should be in YYYY-MM-DD format (or whatever the date picker chooses)'); } } - if(self::hasValue('safetytestdate', $inputs)) { - if(preg_match('#^\d{4}-\d{2}-\d{2}$#u', $inputs['safetytestdate']) !== 1) { + if (self::hasValue('safetytestdate', $inputs)) { + if (preg_match('#^\d{4}-\d{2}-\d{2}$#u', $inputs['safetytestdate']) !== 1) { throw new ValidationException('Date of the test on safety should be in YYYY-MM-DD format (or whatever the date picker chooses)'); } } - if(self::hasValue('schacdateofbirth', $inputs)) { + if (self::hasValue('schacdateofbirth', $inputs)) { $inputs['schacdateofbirth'] = self::dateHtmlToSchac($inputs['schacdateofbirth']); } - if(self::hasValue('safetytestdate', $inputs)) { + if (self::hasValue('safetytestdate', $inputs)) { $inputs['safetytestdate'] = self::dateHtmlToSchac($inputs['safetytestdate']); } - if(self::hasValue('mobile', $inputs)) { + if (self::hasValue('mobile', $inputs)) { $inputs['mobile'] = self::mobile($inputs['mobile']); } - if(self::hasValue('sshpublickey', $inputs)) { + if (self::hasValue('sshpublickey', $inputs)) { $inputs['sshpublickey'] = explode("\r\n", $inputs['sshpublickey']); - $inputs['sshpublickey'] = array_filter($inputs['sshpublickey'], function($name) { return $name !== ''; }); + $inputs['sshpublickey'] = array_filter($inputs['sshpublickey'], function ($name) { + return $name !== ''; + }); } - if(self::hasValue('weeelabnickname', $inputs)) { + if (self::hasValue('weeelabnickname', $inputs)) { $inputs['weeelabnickname'] = explode("\r\n", $inputs['weeelabnickname']); - $inputs['weeelabnickname'] = array_filter($inputs['weeelabnickname'], function($name) { return $name !== ''; }); + $inputs['weeelabnickname'] = array_filter($inputs['weeelabnickname'], function ($name) { + return $name !== ''; + }); } - if(self::hasValue('memberof', $inputs)) { + if (self::hasValue('memberof', $inputs)) { try { $groupNames = explode("\r\n", $inputs['memberof']); - $groupNames = array_filter($groupNames, function($name) { return $name !== ''; }); + $groupNames = array_filter($groupNames, function ($name) { + return $name !== ''; + }); $inputs['memberof'] = $ldap->groupNamesToDn($groupNames); - } catch(LdapException $e) { - if($e->getCode() === 1) { + } catch (LdapException $e) { + if ($e->getCode() === 1) { throw new ValidationException($e->getMessage(), 0, $e); } else { throw $e; } } } - if(array_key_exists('sshpublickey', $inputs) && !is_array($inputs['sshpublickey'])) { + if (array_key_exists('sshpublickey', $inputs) && !is_array($inputs['sshpublickey'])) { $inputs['sshpublickey'] = []; } - if(array_key_exists('weeelabnickname', $inputs) && !is_array($inputs['weeelabnickname'])) { + if (array_key_exists('weeelabnickname', $inputs) && !is_array($inputs['weeelabnickname'])) { $inputs['weeelabnickname'] = []; } - if(array_key_exists('memberof', $inputs) && !is_array($inputs['memberof'])) { + if (array_key_exists('memberof', $inputs) && !is_array($inputs['memberof'])) { $inputs['memberof'] = []; } @@ -180,31 +187,32 @@ protected static function normalize(Ldap $ldap, array $inputs): array { return $inputs; } - protected static function validate(array $inputs) { - foreach($inputs as $attr => $input) { - if(is_array($input)) { + protected static function validate(array $inputs) + { + foreach ($inputs as $attr => $input) { + if (is_array($input)) { continue; } $strlen = mb_strlen($input); - if($attr === 'description') { - if($strlen > 10000) { + if ($attr === 'description') { + if ($strlen > 10000) { throw new ValidationException("Notes too long: $strlen characters, limit is 10000"); } - } elseif($attr === 'sshpublickey') { - if($strlen > 10000) { + } elseif ($attr === 'sshpublickey') { + if ($strlen > 10000) { throw new ValidationException("SSH public keys too long: $strlen characters, limit is 10000"); } - } elseif($strlen > 500) { + } elseif ($strlen > 500) { throw new ValidationException("$attr too long: $strlen characters, limit is 500"); } } - if(self::hasValue('mail', $inputs)) { + if (self::hasValue('mail', $inputs)) { // Email should be: // At least 3 characters long (a@b) // Not start with an @ // Not end with an @ // Contain at least one @ somewhere ("@"@example.com should be valid, I think) - if( + if ( strlen($inputs['mail']) < 3 || substr($inputs['mail'], 0, 1) === '@' || substr($inputs['mail'], -1, 1) === '@' || @@ -213,67 +221,67 @@ protected static function validate(array $inputs) { throw new ValidationException('Invalid email address'); } } - if(self::hasValue('schacpersonaluniquecode', $inputs)) { - if(strlen($inputs['schacpersonaluniquecode']) < 2) { + if (self::hasValue('schacpersonaluniquecode', $inputs)) { + if (strlen($inputs['schacpersonaluniquecode']) < 2) { throw new ValidationException('ID number too short (just 1 character?)'); } $letter = substr($inputs['schacpersonaluniquecode'], 0, 1); $numbers = substr($inputs['schacpersonaluniquecode'], 1); - if($letter !== 's' && $letter !== 'd') { + if ($letter !== 's' && $letter !== 'd') { throw new ValidationException('ID number should begin with "s" or "d"'); } - if(!ctype_digit($numbers)) { + if (!ctype_digit($numbers)) { throw new ValidationException('ID number should begin with "s" or "d", followed by numbers'); } } - if(self::hasValue('schacplaceofbirth', $inputs)) { - if(preg_match('#^\w[\w\s]*(?:\([A-Za-z][A-Za-z]\))?, .+$#u', $inputs['schacplaceofbirth']) !== 1) { + if (self::hasValue('schacplaceofbirth', $inputs)) { + if (preg_match('#^\w[\w\s]*(?:\([A-Za-z][A-Za-z]\))?, .+$#u', $inputs['schacplaceofbirth']) !== 1) { throw new ValidationException('Place of birth does not match regex'); } } - if(self::hasValue('schacdateofbirth', $inputs)) { - if(strlen($inputs['schacdateofbirth']) !== 8 || !is_numeric($inputs['schacdateofbirth'])) { + if (self::hasValue('schacdateofbirth', $inputs)) { + if (strlen($inputs['schacdateofbirth']) !== 8 || !is_numeric($inputs['schacdateofbirth'])) { throw new ValidationException('Date of birth cannot be converted to SCHAC format'); } } - if(self::hasValue('safetytestdate', $inputs)) { - if(strlen($inputs['safetytestdate']) !== 8 || !is_numeric($inputs['safetytestdate'])) { + if (self::hasValue('safetytestdate', $inputs)) { + if (strlen($inputs['safetytestdate']) !== 8 || !is_numeric($inputs['safetytestdate'])) { throw new ValidationException('Date of the test on safety cannot be converted to SCHAC format'); } } - if(self::hasValue('nsaccountlock', $inputs)) { - if($inputs['nsaccountlock'] !== 'true') { + if (self::hasValue('nsaccountlock', $inputs)) { + if ($inputs['nsaccountlock'] !== 'true') { throw new ValidationException('nsAccountLock can only be true or be removed'); } } - if(self::hasValue('haskey', $inputs)) { - if($inputs['haskey'] !== 'true') { + if (self::hasValue('haskey', $inputs)) { + if ($inputs['haskey'] !== 'true') { throw new ValidationException('hasKey can only be true or be removed'); } } - if(self::hasValue('signedsir', $inputs)) { - if($inputs['signedsir'] !== 'true') { + if (self::hasValue('signedsir', $inputs)) { + if ($inputs['signedsir'] !== 'true') { throw new ValidationException('signedSir can only be true or be removed'); } } - if(self::hasValue('uid', $inputs)) { - if(preg_match('#^[a-zA-Z][a-zA-Z0-9-_\.]*$#', $inputs['uid']) !== 1) { + if (self::hasValue('uid', $inputs)) { + if (preg_match('#^[a-zA-Z][a-zA-Z0-9-_\.]*$#', $inputs['uid']) !== 1) { throw new ValidationException('Username should contain only alphanumeric characters, dash, underscore and dot (A-Z a-z 0-9 - _ .), and begin with a letter'); } - if(strlen($inputs['uid']) > 50) { + if (strlen($inputs['uid']) > 50) { throw new ValidationException('Username too long, maximum is 50 characters'); } } - if(self::hasValue('mobile', $inputs)) { - if(strlen($inputs['mobile']) < 2) { + if (self::hasValue('mobile', $inputs)) { + if (strlen($inputs['mobile']) < 2) { throw new ValidationException('Cellphone number too short (1 digit?)'); } - if($inputs['mobile'][0] === '+') { + if ($inputs['mobile'][0] === '+') { $num = substr($inputs['mobile'], 1); } else { $num = $inputs['mobile']; } - if(!ctype_digit($num)) { + if (!ctype_digit($num)) { throw new ValidationException('Cellphone number should contain only digits and optionally a +, sorry if you have a number with an extension or some weird symbols in it'); } } @@ -287,7 +295,8 @@ protected static function validate(array $inputs) { * * @return string Y-m-d for HTML input tags */ - public static function dateSchacToHtml(string $date): string { + public static function dateSchacToHtml(string $date): string + { return DateTime::createFromFormat('Ymd', $date)->format('Y-m-d'); } @@ -299,17 +308,20 @@ public static function dateSchacToHtml(string $date): string { * * @return string Ymd for LDAP */ - public static function dateHtmlToSchac(string $date): string { + public static function dateHtmlToSchac(string $date): string + { return DateTime::createFromFormat('Y-m-d', $date)->format('Ymd'); } - private static function mobile(string $mobile): string { + private static function mobile(string $mobile): string + { $plus = substr($mobile, 0, 1) === '+' ? '+' : ''; $mobile = preg_replace('/[^0-9]/', '', $mobile); return $plus . $mobile; } - private static function hasValue(string $attr, array $attrs): bool { + private static function hasValue(string $attr, array $attrs): bool + { return isset($attrs[$attr]) && $attrs[$attr] !== '' && $attrs[$attr] !== null; } @@ -321,18 +333,19 @@ private static function hasValue(string $attr, array $attrs): bool { * @param string $uid UID to update * @param array|null $previous attributes */ - public static function handleUserEditPost(array $editableAttributes, Ldap $ldap, string $uid, ?array $previous): void { + public static function handleUserEditPost(array $editableAttributes, Ldap $ldap, string $uid, ?array $previous): void + { $edited = array_intersect_key($_POST, $editableAttributes); - if(isset($editableAttributes['nsaccountlock']) && !isset($edited['nsaccountlock'])) { + if (isset($editableAttributes['nsaccountlock']) && !isset($edited['nsaccountlock'])) { $edited['nsaccountlock'] = ''; } - if(isset($editableAttributes['haskey']) && !isset($edited['haskey'])) { + if (isset($editableAttributes['haskey']) && !isset($edited['haskey'])) { $edited['haskey'] = ''; } - if(isset($editableAttributes['signedsir']) && !isset($edited['signedsir'])) { + if (isset($editableAttributes['signedsir']) && !isset($edited['signedsir'])) { $edited['signedsir'] = ''; } - if(isset($edited['memberof'])) { + if (isset($edited['memberof'])) { // Backwards compatibility layer $edited['memberof'] = implode("\r\n", $edited['memberof']); } @@ -351,21 +364,22 @@ public static function handleUserEditPost(array $editableAttributes, Ldap $ldap, * @param string[] $countries * @param string[] $province */ - public static function handleUserRegisterPost(array $attributes, array $allowedAttributes, Ldap $ldap, array $degreeCourses, array $countries, array $province): void { - if(!self::hasValue('register-tos', $attributes) || $attributes['register-tos'] !== 'on') { + public static function handleUserRegisterPost(array $attributes, array $allowedAttributes, Ldap $ldap, array $degreeCourses, array $countries, array $province): void + { + if (!self::hasValue('register-tos', $attributes) || $attributes['register-tos'] !== 'on') { throw new ValidationException('Accept our privacy policy to continue'); } // Check degree course according to the list - if(!self::hasValue('degreecourse', $attributes)) { + if (!self::hasValue('degreecourse', $attributes)) { throw new ValidationException('Select a degree course'); } // Key and value are the same, no need to get the value - if(!isset($degreeCourses[$attributes['degreecourse']])) { + if (!isset($degreeCourses[$attributes['degreecourse']])) { throw new ValidationException('Invalid degree course, select one from the list'); } - if(!self::hasValue('givenname', $attributes) || !self::hasValue('sn', $attributes)) { + if (!self::hasValue('givenname', $attributes) || !self::hasValue('sn', $attributes)) { // This is checked again later, but oh well... throw new ValidationException('Name and surname are mandatory'); } @@ -377,10 +391,10 @@ public static function handleUserRegisterPost(array $attributes, array $allowedA // This may become longer than 500 characters and fail validation later. Well... too bad. $attributes['cn'] = $attributes['givenname'] . ' ' . $attributes['sn']; - if(!self::hasValue('password1', $attributes) || !self::hasValue('password2', $attributes)) { + if (!self::hasValue('password1', $attributes) || !self::hasValue('password2', $attributes)) { throw new ValidationException('Missing password or password confirmation'); } - if($attributes['password1'] !== $attributes['password2']) { + if ($attributes['password1'] !== $attributes['password2']) { throw new ValidationException('Password and password confirmation do not match'); } $password = $attributes['userpassword'] = $attributes['password1']; @@ -393,25 +407,25 @@ public static function handleUserRegisterPost(array $attributes, array $allowedA // Trimming may have eliminated some fields, let's see... - if(!self::hasValue('uid', $edited)) { + if (!self::hasValue('uid', $edited)) { throw new ValidationException('Username is mandatory'); } // Password already validated - if(!self::hasValue('givenname', $edited)) { + if (!self::hasValue('givenname', $edited)) { throw new ValidationException('Name is mandatory'); } - if(!self::hasValue('sn', $edited)) { + if (!self::hasValue('sn', $edited)) { throw new ValidationException('Surname is mandatory'); } - if(!self::hasValue('degreecourse', $edited)) { + if (!self::hasValue('degreecourse', $edited)) { throw new ValidationException('Degree course is mandatory'); } - if(!self::hasValue('schacpersonaluniquecode', $edited)) { + if (!self::hasValue('schacpersonaluniquecode', $edited)) { throw new ValidationException('Student ID is mandatory'); } @@ -423,19 +437,19 @@ public static function handleUserRegisterPost(array $attributes, array $allowedA $edited['memberOf'] = $ldap->groupNamesToDn(explode(',', CRAUTO_DEFAULT_GROUPS)); - if($edited['mail'] === null) { + if ($edited['mail'] === null) { unset($edited['mail']); } - if($edited['schacdateofbirth'] === null) { + if ($edited['schacdateofbirth'] === null) { unset($edited['schacdateofbirth']); } - if($edited['telegramid'] === null) { + if ($edited['telegramid'] === null) { unset($edited['telegramid']); } - if($edited['telegramnickname'] === null) { + if ($edited['telegramnickname'] === null) { unset($edited['telegramnickname']); } @@ -452,27 +466,28 @@ public static function handleUserRegisterPost(array $attributes, array $allowedA * @param array $form form values * @param bool $requireOldPassword */ - public static function handlePasswordChangePost(Ldap $ldap, string $uid, array $form, bool $requireOldPassword = true): void { + public static function handlePasswordChangePost(Ldap $ldap, string $uid, array $form, bool $requireOldPassword = true): void + { $required = ['password1', 'password2']; - if($requireOldPassword) { + if ($requireOldPassword) { $required[] = 'oldpassword'; } $form = array_intersect_key($form, array_combine($required, $required)); - if(count($form) < count($required)) { + if (count($form) < count($required)) { throw new ValidationException('Provide all the required passwords'); } - if($form['password1'] !== $form['password2']) { + if ($form['password1'] !== $form['password2']) { throw new ValidationException('Password does not match confirmation password'); } $dn = $ldap->getUserDn($uid); - if($requireOldPassword) { + if ($requireOldPassword) { try { // If this doesn't throw any exception, we're good to go new Ldap($ldap->getUrl(), $dn, $form['oldpassword'], '', '', $ldap->getStarttls()); - } catch(LdapException $e) { - if($e->getMessage() === 'Bind with LDAP server failed') { + } catch (LdapException $e) { + if ($e->getMessage() === 'Bind with LDAP server failed') { throw new LdapException('Current password is incorrect (' . $e->getMessage() . ')'); } throw $e; @@ -482,12 +497,13 @@ public static function handlePasswordChangePost(Ldap $ldap, string $uid, array $ $ldap->updatePassword($dn, $form['password1']); } - protected static function generateUniqueId(): ?string { + protected static function generateUniqueId(): ?string + { try { $data = random_bytes(16); - } catch(Exception $e) { + } catch (Exception $e) { $data = ''; - for($i = 0; $i < 16; ++$i) { + for ($i = 0; $i < 16; ++$i) { $data .= chr(mt_rand(0, 255)); } } diff --git a/src/ValidationException.php b/src/ValidationException.php index 45017fa..dea0256 100644 --- a/src/ValidationException.php +++ b/src/ValidationException.php @@ -1,11 +1,9 @@ layout('base', ['title' => 'Bad Request']) ?>

400 - Bad Request

- + diff --git a/templates/403.php b/templates/403.php index 9129913..51ccd23 100644 --- a/templates/403.php +++ b/templates/403.php @@ -7,7 +7,7 @@

403 - Forbidden

You are not authorized to access this page

- + diff --git a/templates/404.php b/templates/404.php index ade9ef4..0272392 100644 --- a/templates/404.php +++ b/templates/404.php @@ -1,4 +1,5 @@ layout('base', ['title' => 'Internal Server Error']) ?>

500 - Internal Server Error

- + diff --git a/templates/authenticationeditor.php b/templates/authenticationeditor.php index eac7767..f6e3c9f 100644 --- a/templates/authenticationeditor.php +++ b/templates/authenticationeditor.php @@ -6,12 +6,12 @@

Authentication

- + - + diff --git a/templates/authenticationform.php b/templates/authenticationform.php index c05f81c..002efac 100644 --- a/templates/authenticationform.php +++ b/templates/authenticationform.php @@ -2,7 +2,7 @@ /** @var $requireOldPassword bool */ ?>
- +
diff --git a/templates/base.php b/templates/base.php index 3f62e7d..e3e5ac2 100644 --- a/templates/base.php +++ b/templates/base.php @@ -1,15 +1,16 @@ - - - <?= $this->e($title) ?> - Crauto - - + + + <?= $this->e($title) ?> - Crauto + + - + fetch('navbar') ?> diff --git a/templates/grouplist.php b/templates/grouplist.php index 12c9707..ab68edd 100644 --- a/templates/grouplist.php +++ b/templates/grouplist.php @@ -1,4 +1,5 @@

Groups

- - + + $group): ?> -

- - - - - - - - - - - - - - > - - - - - - - - - -
UsernameFull nameOther GroupsTest doneTelegram
e($user['uid']) ?>e($user['cn']) ?> -
-
+foreach ($groups as $name => $group) : ?> +

+ + + + + + + + + + + + + + > + + + + + + + + + +
UsernameFull nameOther GroupsTest doneTelegram
e($user['uid']) ?>e($user['cn']) ?> +
+
diff --git a/templates/index.php b/templates/index.php index a0642e5..0d4bd64 100644 --- a/templates/index.php +++ b/templates/index.php @@ -12,8 +12,8 @@
  • Crauto - account management system, where you are now
  • $service[0]"; diff --git a/templates/logout.php b/templates/logout.php index 0e13d14..1afe7fa 100644 --- a/templates/logout.php +++ b/templates/logout.php @@ -1,4 +1,5 @@ layout('base', ['title' => 'Logged out']) ?>

    You are now logged out.

    diff --git a/templates/navbar.php b/templates/navbar.php index dc6e430..547cc35 100644 --- a/templates/navbar.php +++ b/templates/navbar.php @@ -2,44 +2,44 @@ diff --git a/templates/personaleditor.php b/templates/personaleditor.php index 91076df..5cc4a81 100644 --- a/templates/personaleditor.php +++ b/templates/personaleditor.php @@ -10,7 +10,7 @@

    - + @@ -21,7 +21,7 @@ 'editableAttributes' => $editableAttributes, 'allowedAttributes' => $allowedAttributes, 'selfImage' => true, - 'allGroups' => $allGroups + 'allGroups' => $allGroups ])?>

    diff --git a/templates/register_done.php b/templates/register_done.php index b2ab365..191f7aa 100644 --- a/templates/register_done.php +++ b/templates/register_done.php @@ -1,4 +1,5 @@ Register - +

    - + @@ -85,7 +85,7 @@ diff --git a/templates/safety_test.php b/templates/safety_test.php index ff7360f..27a8341 100644 --- a/templates/safety_test.php +++ b/templates/safety_test.php @@ -1,11 +1,12 @@ diff($user['safetytestdate'])->format('%R%a'); - if($daysDiff >= 0) { + if ($daysDiff >= 0) { $sortkey = $user['sn'] . ' ' . $user['cn'] . ' ' . $user['uid']; - if(!is_null($testdates)) { + if (!is_null($testdates)) { $testdates[$user['safetytestdate']->format('Y-m-d')][$sortkey] = $user; } } @@ -14,18 +15,19 @@ function safetyTest(array $user, ?array &$testdates, DateTimeImmutable $today) { return [0, false]; } -function safetyTestIcon(int $testDaysDiff, bool $testScheduled, bool $signedSir): string { - if($signedSir) { +function safetyTestIcon(int $testDaysDiff, bool $testScheduled, bool $signedSir): string +{ + if ($signedSir) { $sir = ''; } else { $sir = ''; } - if($testScheduled) { - if($testDaysDiff < 0) { + if ($testScheduled) { + if ($testDaysDiff < 0) { // Test done in the past: checkmark and optionally printer return '' . $sir; - } else if($testDaysDiff === 0) { + } elseif ($testDaysDiff === 0) { // Test today: hourglass and optionally printer return '' . $sir; } else { diff --git a/templates/sessions.php b/templates/sessions.php index efe2dc5..bb0f043 100644 --- a/templates/sessions.php +++ b/templates/sessions.php @@ -1,4 +1,5 @@ layout('base', ['title' => 'Privacy policy']) ?>

    Informazioni sul trattamento dei dati personali (privacy policy)

    diff --git a/templates/usereditor.php b/templates/usereditor.php index 2f59269..90eeade 100644 --- a/templates/usereditor.php +++ b/templates/usereditor.php @@ -17,25 +17,25 @@

    - - + + - - + + fetch('userform', ['attributes' => $attributes, - 'editableAttributes' => $editableAttributes, - 'allowedAttributes' => $allowedAttributes, - 'allGroups' => $allGroups, + 'editableAttributes' => $editableAttributes, + 'allowedAttributes' => $allowedAttributes, + 'allGroups' => $allGroups, ]); ?> fetch('authenticationform', ['requireOldPassword' => $adminRequireOldPassword]) ?> Created - Last modified diff --git a/templates/userform.php b/templates/userform.php index c5d4a5f..85fd0d0 100644 --- a/templates/userform.php +++ b/templates/userform.php @@ -6,10 +6,10 @@ sort($allGroups); ?>
@@ -118,45 +118,45 @@
- +
- +
- +
- +
name="nsaccountlock" >
- - + +
name="signedsir" >
- - + +
name="haskey" >
- +
diff --git a/templates/userlist.php b/templates/userlist.php index bd47384..a806edb 100644 --- a/templates/userlist.php +++ b/templates/userlist.php @@ -1,4 +1,5 @@

People

- + @@ -38,27 +39,27 @@ - - - - - - + + + + + + - + + if (!isset($user['nsaccountlock']) || $user['nsaccountlock'] === null) : ?> - - - + + + @@ -71,7 +72,7 @@ $columns = (count($testdates) > 0 ? 1 : 0) + (count($sirsToSign) > 0 ? 1 : 0) + (count($keys) > 0 ? 1 : 0); -switch($columns) { +switch ($columns) { case 3: $class = 'col-xl-4 col-lg-6'; break; @@ -83,18 +84,18 @@ $class = ''; break; } -if($columns > 0): -?> +if ($columns > 0) : + ?>
- 0): ?> + 0) : ?>

Upcoming tests on safety

- $usersTestOnSafety): ?> + $usersTestOnSafety) : ?>
    e($user['schacpersonaluniquecode']) : null; ?>
  • e($user['uid']), $this->e($user['cn']), $schacpersonaluniquecode) ?>
  • @@ -103,11 +104,11 @@
- 0): ?> + 0) : ?>

SIRs to print

    - e($user['schacpersonaluniquecode']) : null; ?>
  • e($user['uid']), $this->e($user['cn']), $schacpersonaluniquecode) ?>
  • @@ -115,11 +116,11 @@
- 0): ?> + 0) : ?>

Who has keys to the lab

@@ -129,9 +130,9 @@ @@ -152,17 +153,17 @@
+ foreach ($users as $user) : ?> format('Y-m-d'); - if(isset($user['nsaccountlock']) && $user['nsaccountlock'] === 'true'): ?> + if (isset($user['nsaccountlock']) && $user['nsaccountlock'] === 'true') : ?> diff --git a/templates/websiteuserlist.php b/templates/websiteuserlist.php index ee2d3da..25234e8 100644 --- a/templates/websiteuserlist.php +++ b/templates/websiteuserlist.php @@ -8,7 +8,7 @@ ?>

People (website code version)

- + @@ -16,15 +16,15 @@ <style style="display:hidden;">.persona {box-sizing:border-box;width:25%;text-align:center;border-bottom:0.3rem solid #333;padding:0.4em;} .persona .name {font-size: 130%;font-weight:bold;} .persona .area {font-weight:bold;}</style> <div style="display:flex;flex-wrap:wrap;justify-content:space-around;align-items:stretch;flex-direction:row;"> - <div class="persona"> <p class="name"></p> -<p class="area"></p> -<p><small>Studente di </small></p> + <p class="area"></p> + <p><small>Studente di </small></p> </div> </div>
UsernameFull nameRole and groupsTest doneTelegramUsernameFull nameRole and groupsTest doneTelegram
e($user['uid']) ?> e($user['cn']) ?>

e($user['uid']) ?>