From 62ebb5d43ea6c2df713232de7c5b8d168184cefe Mon Sep 17 00:00:00 2001 From: Pierre Ozoux Date: Mon, 2 May 2022 10:21:25 +0000 Subject: [PATCH] Still work in progress.. --- README.md | 12 +++- lib/AppInfo/Application.php | 67 --------------------- lib/Controller/ASCIMUser.php | 20 ++++--- lib/Controller/UserController.php | 40 ++++++------- lib/Exceptions/SCIMErrorType.php | 17 ------ lib/Exceptions/SCIMException.php | 47 --------------- lib/Middleware/SCIMApiMiddleware.php | 80 -------------------------- lib/Responses/SCIMErrorResponse.php | 43 ++++++++++++++ lib/Responses/SCIMJSONResponse.php | 49 ++++++++++++++++ lib/Responses/SCIMListResponse.php | 25 +++++++- lib/Responses/SCIMResourceResponse.php | 30 ---------- 11 files changed, 156 insertions(+), 274 deletions(-) delete mode 100644 lib/AppInfo/Application.php delete mode 100644 lib/Exceptions/SCIMErrorType.php delete mode 100644 lib/Exceptions/SCIMException.php delete mode 100644 lib/Middleware/SCIMApiMiddleware.php create mode 100644 lib/Responses/SCIMErrorResponse.php create mode 100644 lib/Responses/SCIMJSONResponse.php delete mode 100644 lib/Responses/SCIMResourceResponse.php diff --git a/README.md b/README.md index 5de0ae3..a9e73d3 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ for integration tests # TODO - - attribute active + - [x]attribute active - group mgmt - list user - add/remove user from groups @@ -61,4 +61,12 @@ for integration tests - Erreur/Exception - [x] json - [x] status code - - [x] escaped location - JSON_UNESCAPED_SLASHES \ No newline at end of file + - [x] escaped location - JSON_UNESCAPED_SLASHES + + + cd apps +wget https://lab.libreho.st/libre.sh/scim/nextcloud-scim/-/archive/test-branch/nextcloud-scim-main.zip +unzip nextcloud-scim-main.zip +rm nextcloud-scim-main.zip +rm -rf scimserviceprovider +mv nextcloud-scim-test-branchxxx scimserviceprovider \ No newline at end of file diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php deleted file mode 100644 index ced1f8f..0000000 --- a/lib/AppInfo/Application.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * @author Christoph Wurst - * @author Daniel Kesselberg - * @author Joas Schilling - * @author Lukas Reschke - * @author Morris Jobke - * @author Roeland Jago Douma - * @author Vincent Petry - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ -namespace OCA\SCIMServiceProvider\AppInfo; - -use OC\Group\Manager as GroupManager; -use OCA\Provisioning_API\Capabilities; -use OCA\Provisioning_API\Listener\UserDeletedListener; -use OCA\SCIMServiceProvider\Middleware\SCIMApiMiddleware; -use OCA\Settings\Mailer\NewUserMailHelper; -use OCP\AppFramework\App; -use OCP\AppFramework\Bootstrap\IBootContext; -use OCP\AppFramework\Bootstrap\IBootstrap; -use OCP\AppFramework\Bootstrap\IRegistrationContext; -use OCP\AppFramework\Utility\IControllerMethodReflector; -use OCP\AppFramework\Utility\ITimeFactory; -use OCP\Defaults; -use OCP\IConfig; -use OCP\IGroupManager; -use OCP\IURLGenerator; -use OCP\IUser; -use OCP\IUserManager; -use OCP\L10N\IFactory; -use OCP\Mail\IMailer; -use OCP\Security\ICrypto; -use OCP\Security\ISecureRandom; -use OCP\User\Events\UserDeletedEvent; -use OCP\Util; -use Psr\Container\ContainerInterface; - -class Application extends App implements IBootstrap { - public function __construct(array $urlParams = []) { - parent::__construct('scimserviceprovider', $urlParams); - } - - public function register(IRegistrationContext $context): void { - $context->registerMiddleware(SCIMApiMiddleware::class); - } - - public function boot(IBootContext $context): void { - } -} diff --git a/lib/Controller/ASCIMUser.php b/lib/Controller/ASCIMUser.php index 434256d..7c60bf5 100644 --- a/lib/Controller/ASCIMUser.php +++ b/lib/Controller/ASCIMUser.php @@ -43,7 +43,7 @@ use OCP\IRequest; use OCP\IUserManager; use OCP\IUserSession; use OCP\L10N\IFactory; -use OCA\SCIMServiceProvider\Exceptions\SCIMException; +use OCA\SCIMServiceProvider\Responses\SCIMErrorResponse; abstract class ASCIMUser extends ApiController { /** @var IUserManager */ @@ -74,18 +74,18 @@ abstract class ASCIMUser extends ApiController { } /** - * creates a array with all user data + * creates an object with all user data * * @param string $userId * @param bool $includeScopes * @return array - * @throws SCIMException + * @throws Exception */ protected function getSCIMUser(string $userId): array { // Check if the target user exists $targetUserObject = $this->userManager->get($userId); if ($targetUserObject === null) { - throw new SCIMException('User not found', 404); + return []; } $enabled = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true') === 'true'; @@ -93,23 +93,25 @@ abstract class ASCIMUser extends ApiController { return [ 'schemas' => ["urn:ietf:params:scim:schemas:core:2.0:User"], 'id' => $userId, - //'externalId' => $this->externalId, + 'name' => [ + 'formatted' => $targetUserObject->getDisplayName() + ], 'meta' => [ 'resourceType' => 'User', 'location' => '/Users/' . $userId, - //'created' => Helper::dateTime2string($this->created_at), + 'created' => '2022-04-28T18:27:17.783Z', // todo + 'lastModified' => '2022-04-28T18:27:17.783Z' // todo ], 'userName' => $userId, 'displayName' => $targetUserObject->getDisplayName(), - 'emails' => [ + 'emails' => [ // todo if no emails [ 'primary' => true, 'value' => $targetUserObject->getSystemEMailAddress() ] ], - //'groups' => [], + 'externalId' => '1234', // todo 'active' => $enabled ]; } - } diff --git a/lib/Controller/UserController.php b/lib/Controller/UserController.php index d9708e5..69498a4 100644 --- a/lib/Controller/UserController.php +++ b/lib/Controller/UserController.php @@ -45,7 +45,6 @@ namespace OCA\SCIMServiceProvider\Controller; use InvalidArgumentException; use OC\HintException; use OC\KnownUser\KnownUserService; -use OCA\Settings\Mailer\NewUserMailHelper; use OCP\Accounts\IAccountManager; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCSController; @@ -60,7 +59,9 @@ use OCP\Security\ISecureRandom; use OCP\EventDispatcher\IEventDispatcher; use Psr\Log\LoggerInterface; use OCA\SCIMServiceProvider\Responses\SCIMListResponse; -use OCA\SCIMServiceProvider\Responses\SCIMResourceResponse; +use OCA\SCIMServiceProvider\Responses\SCIMJSONResponse; +use OCA\SCIMServiceProvider\Responses\SCIMErrorResponse; + class UserController extends ASCIMUser { @@ -135,16 +136,16 @@ class UserController extends ASCIMUser { * gets user info * * @param string $id - * @return SCIMResourceResponse - * @throws SCIMException + * @return SCIMJSONResponse + * @throws Exception */ - public function show(string $id): SCIMResourceResponse { + public function show(string $id): SCIMJSONResponse { $user = $this->getSCIMUser($id); // getUserData returns empty array if not enough permissions if (empty($user)) { - throw new SCIMException('User not found', 404); + return new SCIMErrorResponse(['message' => 'User not found'], 404); } - return new SCIMResourceResponse($user); + return new SCIMJSONResponse($user); } /** @@ -154,16 +155,16 @@ class UserController extends ASCIMUser { * @param string $displayName * @param array $emails * @param string $userName - * @return SCIMResourceResponse - * @throws SCIMException + * @return SCIMJSONResponse + * @throws Exception */ public function create( bool $active = true, string $displayName = '', array $emails = [], - string $userName = ''): SCIMResourceResponse { + string $userName = ''): SCIMJSONResponse { if ($this->userManager->userExists($userName)) { $this->logger->error('Failed createUser attempt: User already exists.', ['app' => 'SCIMServiceProvider']); - throw new SCIMException('User already exists', 409, 'uniqueness'); + return new SCIMErrorResponse(['message' => 'User already exists'], 409); } try { @@ -176,8 +177,8 @@ class UserController extends ASCIMUser { } } $newUser->setEnabled($active); - return new SCIMResourceResponse($this->getSCIMUser($userName)); - } catch (SCIMException $e) { + return new SCIMJSONResponse($this->getSCIMUser($userName)); + } catch (Exception $e) { $this->logger->warning('Failed createUser attempt with SCIMException exeption.', ['app' => 'SCIMServiceProvider']); throw $e; } @@ -193,15 +194,15 @@ class UserController extends ASCIMUser { * @param string $displayName * @param array $emails * @return DataResponse - * @throws SCIMException + * @throws Exception */ public function update( string $id, bool $active, string $displayName = '', - array $emails = []): SCIMResourceResponse { + array $emails = []): SCIMJSONResponse { $targetUser = $this->userManager->get($id); if ($targetUser === null) { - throw new SCIMException('User not found', 404); + return new SCIMErrorResponse(['message' => 'User not found'], 404); } foreach ($emails as $email) { if ($email['primary'] === true) { @@ -211,7 +212,7 @@ class UserController extends ASCIMUser { if (isset($active)) { $targetUser->setEnabled($active); } - return new SCIMResourceResponse($this->getSCIMUser($id)); + return new SCIMJSONResponse($this->getSCIMUser($id)); } @@ -220,13 +221,12 @@ class UserController extends ASCIMUser { * * @param string $id * @return DataResponse - * @throws SCIMException */ public function destroy(string $id): Response { $targetUser = $this->userManager->get($id); if ($targetUser === null) { - throw new SCIMException('User not found', 404); + return new SCIMErrorResponse(['message' => 'User not found'], 404); } // Go ahead with the delete @@ -235,7 +235,7 @@ class UserController extends ASCIMUser { $response->setStatus(204); return $response; } else { - throw new SCIMException(''); + return new SCIMErrorResponse(['message' => 'Couldn\'t delete user'], 503); } } diff --git a/lib/Exceptions/SCIMErrorType.php b/lib/Exceptions/SCIMErrorType.php deleted file mode 100644 index bd27f36..0000000 --- a/lib/Exceptions/SCIMErrorType.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * @author Christoph Wurst - * @author Roeland Jago Douma - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ -namespace OCA\SCIMServiceProvider\Exceptions; - -use Exception; - -/** - * Class SCIMException - * - * @since 9.1.0 - */ -class SCIMException extends Exception { - public function __construct(string $detail, - int $status = 500, - string $scimType='') { - $message = [ - "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"], - "detail" => $detail, - "scimType" => $scimType, - "status" => $status - ]; - - parent::__construct(json_encode($message), $status); - } - -} \ No newline at end of file diff --git a/lib/Middleware/SCIMApiMiddleware.php b/lib/Middleware/SCIMApiMiddleware.php deleted file mode 100644 index f4d8bcc..0000000 --- a/lib/Middleware/SCIMApiMiddleware.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * @author Joas Schilling - * @author Lukas Reschke - * @author Morris Jobke - * @author Roeland Jago Douma - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ -namespace OCA\SCIMServiceProvider\Middleware; - -use OCP\AppFramework\Controller; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\JSONResponse; -use OCP\AppFramework\Middleware; -use OCP\AppFramework\Utility\IControllerMethodReflector; -use OCA\SCIMServiceProvider\Responses\SCIMResourceResponse; - -class SCIMApiMiddleware extends Middleware { - - /** @var IControllerMethodReflector */ - private $reflector; - - /** @var bool */ - private $isAdmin; - - /** @var bool */ - private $isSubAdmin; - - /** - * ProvisioningApiMiddleware constructor. - * - * @param IControllerMethodReflector $reflector - * @param bool $isAdmin - * @param bool $isSubAdmin - */ - public function __construct( - IControllerMethodReflector $reflector, - bool $isAdmin, - bool $isSubAdmin) { - $this->reflector = $reflector; - $this->isAdmin = $isAdmin; - $this->isSubAdmin = $isSubAdmin; - } - - /** - * @param Controller $controller - * @param string $methodName - * @param \Exception $exception - * @throws \Exception - * @return SCIMResourceResponse - */ - public function afterException($controller, $methodName, \Exception $exception) { - if ($exception instanceof SCIMException) { - return SCIMResourceResponse($exception->getMessage(), 500); - } - return SCIMResourceResponse([ - "schema" => "error" - ],500); - } -} diff --git a/lib/Responses/SCIMErrorResponse.php b/lib/Responses/SCIMErrorResponse.php new file mode 100644 index 0000000..0614be5 --- /dev/null +++ b/lib/Responses/SCIMErrorResponse.php @@ -0,0 +1,43 @@ + ['urn:ietf:params:scim:api:messages:2.0:Error'], + 'detail' => $this->data['message'], + 'scimType' => '', + 'status' => $this->getStatus() + ]; + $response = json_encode($message, JSON_UNESCAPED_SLASHES); + + if ($response === false) { + throw new Exception(sprintf('Could not json_encode due to invalid ' . + 'non UTF-8 characters in the array: %s', var_export($this->data, true))); + } + + return $response; + } +} \ No newline at end of file diff --git a/lib/Responses/SCIMJSONResponse.php b/lib/Responses/SCIMJSONResponse.php new file mode 100644 index 0000000..62878f4 --- /dev/null +++ b/lib/Responses/SCIMJSONResponse.php @@ -0,0 +1,49 @@ +data = $data; + $this->setStatus($statusCode); + $this->addHeader('Content-Type', 'application/scim+json; charset=utf-8'); + } + + /** + * Returns the rendered json + * @return string the rendered json + * @since 6.0.0 + * @throws \Exception If data could not get encoded + */ + public function render() { + $response = json_encode($this->data, JSON_UNESCAPED_SLASHES); + + if ($response === false) { + throw new Exception(sprintf('Could not json_encode due to invalid ' . + 'non UTF-8 characters in the array: %s', var_export($this->data, true))); + } + + return $response; + } +} \ No newline at end of file diff --git a/lib/Responses/SCIMListResponse.php b/lib/Responses/SCIMListResponse.php index 8c89107..9cc4aa2 100644 --- a/lib/Responses/SCIMListResponse.php +++ b/lib/Responses/SCIMListResponse.php @@ -2,7 +2,7 @@ namespace OCA\SCIMServiceProvider\Responses; -use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\Response; use OCA\SCIMServiceProvider\Exceptions\SCIMException; @@ -10,7 +10,28 @@ use OCA\SCIMServiceProvider\Exceptions\SCIMException; * Class SCIMListResponse * */ -class SCIMListResponse extends JSONResponse { +class SCIMListResponse extends Response { + /** + * response data + * @var array|object + */ + protected $data; + + + /** + * constructor of SCIMListResponse + * @param array|object $data the object or array that should be transformed + * @param int $statusCode the Http status code, defaults to 200 + * @since 6.0.0 + */ + public function __construct($data = [], $statusCode = 200) { + parent::__construct(); + + $this->data = $data; + $this->setStatus($statusCode); + $this->addHeader('Content-Type', 'application/scim+json; charset=utf-8'); + } + /** * Returns the rendered json * @return string the rendered json diff --git a/lib/Responses/SCIMResourceResponse.php b/lib/Responses/SCIMResourceResponse.php deleted file mode 100644 index b213b0b..0000000 --- a/lib/Responses/SCIMResourceResponse.php +++ /dev/null @@ -1,30 +0,0 @@ -data, JSON_UNESCAPED_SLASHES); - - if ($response === false) { - throw new SCIMException(sprintf('Could not json_encode due to invalid ' . - 'non UTF-8 characters in the array: %s', var_export($this->data, true))); - } - - return $response; - } -} \ No newline at end of file