From 3ab65d1c5177df4b781df93871810fa5658204c6 Mon Sep 17 00:00:00 2001 From: Evann Regnault Date: Wed, 19 Jun 2024 16:47:56 +0200 Subject: [PATCH] Roles Folder --- index.php | 19 +++++----- src/Collections/HomeCollection.php | 8 ++-- src/Collections/RolesCollection.php | 38 +++++++++++++++++++ src/Keycloak/KeycloakAuth.php | 35 ++++++++++++----- .../{CustomBackend.php => RolesBackend.php} | 24 +++++++++--- 5 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 src/Collections/RolesCollection.php rename src/Principal/{CustomBackend.php => RolesBackend.php} (57%) diff --git a/index.php b/index.php index 76fd586..e734816 100755 --- a/index.php +++ b/index.php @@ -1,6 +1,8 @@ load(); - -$aclPlugin = new \Sabre\DAVACL\Plugin(); - +$principalBackend = new RolesBackend(); // Set Auth -$authBackend = new Keycloak\KeycloakAuth($aclPlugin,$_ENV['client_id'], $_ENV['client_secret'], $_ENV['keycloak_token_url'] ); +$authBackend = new Keycloak\KeycloakAuth($principalBackend,$_ENV['client_id'], $_ENV['client_secret'], $_ENV['keycloak_token_url'] ); $authBackend->setRealm($_ENV['realm']); $authPlugin = new DAV\Auth\Plugin($authBackend); +$path = $_ENV['users_path']; // The server object is responsible for making sense out of the WebDAV protocol -$server = new DAV\Server([new HomeCollection($authPlugin, $_ENV['users_path'])]); +$server = new DAV\Server([new HomeCollection($authPlugin, $path), new RolesCollection($principalBackend, $path)]); // If your server is not on your webroot, make sure the following line has the // correct information @@ -34,12 +35,12 @@ $lockPlugin = new DAV\Locks\Plugin($lockBackend); $server->addPlugin($lockPlugin); +$principalPlugin = new Sabre\DAVACL\Plugin($principalBackend); -// This ensures that we get a pretty index in the browser, but it is -// optional. -$server->addPlugin(new DAV\Browser\Plugin()); $server->addPlugin($authPlugin); -$server->addPlugin($aclPlugin); +$server->addPlugin($principalPlugin); +$server->addPlugin(new DAV\Browser\Plugin()); + // All we need to do now, is to fire up the server $server->start(); diff --git a/src/Collections/HomeCollection.php b/src/Collections/HomeCollection.php index daa76e9..b63bebd 100644 --- a/src/Collections/HomeCollection.php +++ b/src/Collections/HomeCollection.php @@ -12,13 +12,13 @@ class HomeCollection extends Collection private $userPath; - public function __construct(AuthPlugin $authPlugin, $userPath) + public function __construct(AuthPlugin $authPlugin, string $userPath) { $this->plugin = $authPlugin; $this->userPath = $userPath; } - public function getChildren() + public function getChildren(): array { $principal = $this->plugin->getCurrentPrincipal(); $username = explode("/", $principal)[1]; @@ -31,8 +31,8 @@ class HomeCollection extends Collection return [new Directory($path.$username, $username)]; } - public function getName() + public function getName(): string { return "Home"; } -} \ No newline at end of file +} diff --git a/src/Collections/RolesCollection.php b/src/Collections/RolesCollection.php new file mode 100644 index 0000000..5a8926e --- /dev/null +++ b/src/Collections/RolesCollection.php @@ -0,0 +1,38 @@ +$dataRoot = $dataRoot; + $this->principalBackend = $principal_backend; + } + + public function getChildren() : array { + $path = $this->dataRoot; + $dirs = []; + foreach ($this->principalBackend->roles as $role) { + if (!is_dir($path . 'public/' . $role)){ + mkdir($path . 'public/' . $role, 0777, true); + } + $dirs[] = new SabreDirectory($path . 'public/' . $role, $role); + } + + return $dirs; + } + + public function getName() : string + { + return "Groups"; + } + +} diff --git a/src/Keycloak/KeycloakAuth.php b/src/Keycloak/KeycloakAuth.php index fbb378a..bbd139a 100644 --- a/src/Keycloak/KeycloakAuth.php +++ b/src/Keycloak/KeycloakAuth.php @@ -2,19 +2,21 @@ namespace Keycloak; +use Principal\RolesBackend; use Sabre\DAV\Auth\Backend\AbstractBasic; -use Sabre\DAVACL\Plugin as AclPlugin; class KeycloakAuth extends AbstractBasic { - private $aclPlugin; - private $client_id; - private $client_secret; - private $keycloakTokenUrl; - public function __construct(AclPlugin $plugin, string $client_id, string $client_secret, string $keycloakTokenUrl) + private RolesBackend $principal_backend; + private string $client_id; + private string $client_secret; + private string $keycloakTokenUrl; + + public function __construct(RolesBackend $principal_backend, string $client_id, + string $client_secret, string $keycloakTokenUrl) { - $this->aclPlugin = $plugin; + $this->principal_backend = $principal_backend; $this->client_id = $client_id; $this->client_secret = $client_secret; $this->keycloakTokenUrl = $keycloakTokenUrl; @@ -26,7 +28,7 @@ class KeycloakAuth extends AbstractBasic curl_setopt_array($curl, [ CURLOPT_URL => $this->keycloakTokenUrl, - CURLOPT_RETURNTRANSFER => true, + CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, @@ -38,17 +40,32 @@ class KeycloakAuth extends AbstractBasic ], ]); - curl_exec($curl); + $body = curl_exec($curl); $err = curl_error($curl); $data = curl_getinfo($curl); + curl_close($curl); if ($err || $data['http_code'] != 200) { return false; } else { + $x = json_decode($body); + $user_data = json_decode(base64_decode(explode(".",$x->access_token)[1]), true); + + $resource_data = $user_data["resource_access"]; + if (is_null($resource_data) || !array_key_exists($this->client_id, $resource_data)) return true; + + $client_data = $resource_data[$this->client_id]; + if (is_null($client_data)) return true; + + $roles = $client_data["roles"]; + if (is_null($client_data)) return true; + + $this->principal_backend->setPrincipals($roles); + return true; } diff --git a/src/Principal/CustomBackend.php b/src/Principal/RolesBackend.php similarity index 57% rename from src/Principal/CustomBackend.php rename to src/Principal/RolesBackend.php index 4cc5a8d..e764a71 100644 --- a/src/Principal/CustomBackend.php +++ b/src/Principal/RolesBackend.php @@ -4,17 +4,21 @@ namespace Principal; use Sabre\DAVACL\PrincipalBackend\AbstractBackend; -class CustomBackend extends AbstractBackend +class RolesBackend extends AbstractBackend { + public array $roles = []; + public array $principals = []; public function getPrincipalsByPrefix($prefixPath) { - // TODO: Implement getPrincipalsByPrefix() method. + return array_filter(array: $this->principals, callback: function($k) use($prefixPath) { + return str_starts_with($prefixPath, $k); + }); } public function getPrincipalByPath($path) { - // TODO: Implement getPrincipalByPath() method. + return $path; } public function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) @@ -34,11 +38,21 @@ class CustomBackend extends AbstractBackend public function getGroupMembership($principal) { - // TODO: Implement getGroupMembership() method. + if (!str_contains("groups")) { + return $this->principals; + } + else return [$principal]; } public function setGroupMemberSet($principal, array $members) { // TODO: Implement setGroupMemberSet() method. } -} \ No newline at end of file + + public function setPrincipals(array $roles) { + $this->roles = $roles; + $this->principals = array_map(array: $roles, callback: function($r) { + return "/principals/groups/" . $r; + }); + } +}