From 446b777e81251f54f9cb5b7ef0ec824238729fce Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Fri, 7 Oct 2022 14:11:08 +0530 Subject: [PATCH 01/76] Beta user section --- appinfo/info.xml | 5 +- appinfo/routes.php | 29 ++++-- lib/Controller/UpdateBetaUserController.php | 106 ++++++++++++++++++++ lib/Service/AliasesService.php | 42 ++++++++ lib/Settings/BecomeBetaSetting.php | 96 ++++++++++++++++++ lib/Settings/BetaSection.php | 78 ++++++++++++++ templates/beta_user_setting.php | 27 +++++ 7 files changed, 372 insertions(+), 11 deletions(-) create mode 100644 lib/Controller/UpdateBetaUserController.php create mode 100644 lib/Service/AliasesService.php create mode 100644 lib/Settings/BecomeBetaSetting.php create mode 100644 lib/Settings/BetaSection.php create mode 100644 templates/beta_user_setting.php diff --git a/appinfo/info.xml b/appinfo/info.xml index da9edb47..4a1f53de 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -21,6 +21,9 @@ OCA\EcloudAccounts\Settings\Personal - + OCA\EcloudAccounts\Settings\BecomeBetaSetting + OCA\EcloudAccounts\Settings\BetaSection + + diff --git a/appinfo/routes.php b/appinfo/routes.php index 9999debd..a48e22bf 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,14 +1,23 @@ [ - ['name' => 'user#set_account_data', 'url' => '/api/set_account_data', 'verb' => 'POST'], - ['name' => 'user#user_exists', 'url' => '/api/user_exists', 'verb' => 'POST'], - ['name' => 'user#set_mail_quota_usage', 'url' => '/api/set_mail_quota_usage', 'verb' => 'POST'], - ['name' => 'shop_account#set_shop_email_post_delete', 'url' => '/shop-accounts/set_shop_email_post_delete', 'verb' => 'POST' ], - ['name' => 'shop_account#set_shop_delete_preference', 'url' => '/shop-accounts/set_shop_delete_preference', 'verb' => 'POST' ], - ['name' => 'shop_account#get_order_info', 'url' => '/shop-accounts/order_info', 'verb' => 'GET'], - [ - 'name' => 'user#preflighted_cors', 'url' => '/api/{path}', - 'verb' => 'OPTIONS', 'requirements' => array('path' => '.+') - ], + ['name' => 'user#set_account_data', 'url' => '/api/set_account_data', 'verb' => 'POST'], + ['name' => 'user#user_exists', 'url' => '/api/user_exists', 'verb' => 'POST'], + ['name' => 'user#set_mail_quota_usage', 'url' => '/api/set_mail_quota_usage', 'verb' => 'POST'], + ['name' => 'shop_account#set_shop_email_post_delete', 'url' => '/shop-accounts/set_shop_email_post_delete', 'verb' => 'POST'], + ['name' => 'shop_account#set_shop_delete_preference', 'url' => '/shop-accounts/set_shop_delete_preference', 'verb' => 'POST'], + ['name' => 'shop_account#get_order_info', 'url' => '/shop-accounts/order_info', 'verb' => 'GET'], + [ + 'name' => 'user#preflighted_cors', 'url' => '/api/{path}', + 'verb' => 'OPTIONS', 'requirements' => array('path' => '.+') + ], + [ + 'name' => 'update_beta_user#add_user_to_group', + 'url' => '/api/groups/add', 'verb' => 'POST' + ], + + [ + 'name' => 'update_beta_user#remove_user_from_group', + 'url' => '/api/groups/remove', 'verb' => 'POST' + ] ]]; diff --git a/lib/Controller/UpdateBetaUserController.php b/lib/Controller/UpdateBetaUserController.php new file mode 100644 index 00000000..d50f2fa7 --- /dev/null +++ b/lib/Controller/UpdateBetaUserController.php @@ -0,0 +1,106 @@ +appName = $AppName; + $this->request = $request; + $this->config = $config; + $this->logger = $logger; + $this->userManager = $userManager; + $this->userSession = $userSession; + $this->groupManager = $groupManager; + $this->storageService = $storageService; + } + + /** + * @CORS + * @PublicPage + * @NoCSRFRequired + */ + + public function addUserToGroup() + { + $response = new Response(); + $gid = 'beta' + $uid = $this->userSession->getUser()->getUID(); + $user = $this->userManager->get($uid); + + $group = null; + $groupExists = $this->groupManager->groupExists($gid); + + if (!$groupExists) { + $group = $this->groupManager->createGroup($gid); + } else { + $group = $this->groupManager->get($gid); + } + + $inGroup = $this->groupManager->isInGroup($uid, $gid); + $group->addUser($user); + return true; + + } + + /** + * @CORS + * @PublicPage + * @NoCSRFRequired + */ + + public function removeUserFromGroup(string $username, string $gid, string $token) + { + $response = new Response(); + $gid = 'beta' + $uid = $this->userSession->getUser()->getUID(); + $user = $this->userManager->get($uid); + + $group = null; + $groupExists = $this->groupManager->groupExists($gid); + + if (!$groupExists) { + $group = $this->groupManager->createGroup($gid); + } else { + $group = $this->groupManager->get($gid); + } + + $inGroup = $this->groupManager->isInGroup($uid, $gid); + $group->removeUser($user); + return true; + } + } diff --git a/lib/Service/AliasesService.php b/lib/Service/AliasesService.php new file mode 100644 index 00000000..a31c85f3 --- /dev/null +++ b/lib/Service/AliasesService.php @@ -0,0 +1,42 @@ +appName = $appName; + $this->userManager = $userManager; + $this->config = $config; + } + + public function userExists(string $uid): bool + { + return $this->userManager->userExists($uid); + } + + public function getUser(string $uid): ?IUser + { + return $this->userManager->get($uid); + } + + +} diff --git a/lib/Settings/BecomeBetaSetting.php b/lib/Settings/BecomeBetaSetting.php new file mode 100644 index 00000000..8015ad36 --- /dev/null +++ b/lib/Settings/BecomeBetaSetting.php @@ -0,0 +1,96 @@ +config = $config; + $this->userManager = $userManager; + $this->userSession = $userSession; + $this->accountManager = $accountManager; + $this->aliasesService = $aliasesService; + $this->l = $l; + $this->groupManager = $groupManager; + } + + public function getForm(): TemplateResponse + { + $response = new Response(); + + $uid = $this->userSession->getUser()->getUID(); + $user = $this->userManager->get($uid); + $gid = 'beta'; + $isBeta = 0; + + $group = null; + $groupExists = $this->groupManager->groupExists($gid); + + if (!$groupExists) { + $group = $this->groupManager->createGroup($gid); + } else { + $group = $this->groupManager->get($gid); + } + + $inGroup = $this->groupManager->isInGroup($uid, $gid); + + if ($inGroup) { + $isBeta = 1; + } + + $parameters = ['isBeta' => $isBeta]; + return new TemplateResponse('beta-user', 'beta_user_setting', $parameters, ''); + } + + public function getSection(): ?string + { + return 'beta-user'; + } + + public function getPriority(): int + { + return 0; + } +} diff --git a/lib/Settings/BetaSection.php b/lib/Settings/BetaSection.php new file mode 100644 index 00000000..b98caee9 --- /dev/null +++ b/lib/Settings/BetaSection.php @@ -0,0 +1,78 @@ +url = $url; + $this->l = $l; + } + + /** + * returns the ID of the section. It is supposed to be a lower case string, + * e.g. 'ldap' + * + * @returns string + */ + public function getID() + { + return 'beta-user'; + } + + /** + * returns the translated name as it should be displayed, e.g. 'LDAP / AD + * integration'. Use the L10N service to translate it. + * + * @return string + */ + public function getName() + { + return $this->l->t('Beta User'); + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the settings navigation. The sections are arranged in ascending order of + * the priority values. It is required to return a value between 0 and 99. + * + * E.g.: 70 + */ + public function getPriority() + { + return 70; + } + + /** + * {@inheritdoc} + */ + public function getIcon() + { + return $this->url->imagePath('beta-user', 'alias.svg'); + } +} diff --git a/templates/beta_user_setting.php b/templates/beta_user_setting.php new file mode 100644 index 00000000..9bff7f58 --- /dev/null +++ b/templates/beta_user_setting.php @@ -0,0 +1,27 @@ + + +
+ +
+
+ +

t('You are part of the beta users.'));?>

+

t('Do you want to opt out from the Beta testing program.')) ?>

+ +

t('Do you want to become the beta user?'));?>

+

t('Want to take a break from novelties? Just click on the button below. You can become a beta user again anytime!')) ?>

+ +
+
+
+ +
+ + +
+
+
+
+
-- GitLab From cd891e37e79d9590884ba35c9657dc83b72257c9 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Fri, 7 Oct 2022 14:17:11 +0530 Subject: [PATCH 02/76] hide personal --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index 4a1f53de..5802cd61 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -21,7 +21,7 @@ OCA\EcloudAccounts\Settings\Personal - OCA\EcloudAccounts\Settings\BecomeBetaSetting + OCA\EcloudAccounts\Settings\BetaSection -- GitLab From 56b66e9be9b9cf4a6997edd9a0e1ee488771aab2 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Fri, 7 Oct 2022 14:22:40 +0530 Subject: [PATCH 03/76] hide personal --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index 5802cd61..57493f27 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -22,7 +22,7 @@ OCA\EcloudAccounts\Settings\Personal - OCA\EcloudAccounts\Settings\BetaSection + -- GitLab From bfa549c280ae588aad1e34c3448196e4f40eaf90 Mon Sep 17 00:00:00 2001 From: Ronak Patel Date: Wed, 19 Oct 2022 12:05:45 +0530 Subject: [PATCH 04/76] change in route --- appinfo/routes.php | 3 +- lib/Controller/ShopAccountController.php | 79 +++++++++++++----------- lib/Service/CurlService.php | 1 + lib/Service/ShopAccountService.php | 45 +++++++++----- lib/Settings/Personal.php | 30 +-------- src/PersonalSettings.vue | 68 +++++++++++++++----- src/personal.js | 21 ------- 7 files changed, 133 insertions(+), 114 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index a48e22bf..f6d5c3c7 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -7,6 +7,8 @@ return ['routes' => [ ['name' => 'shop_account#set_shop_email_post_delete', 'url' => '/shop-accounts/set_shop_email_post_delete', 'verb' => 'POST'], ['name' => 'shop_account#set_shop_delete_preference', 'url' => '/shop-accounts/set_shop_delete_preference', 'verb' => 'POST'], ['name' => 'shop_account#get_order_info', 'url' => '/shop-accounts/order_info', 'verb' => 'GET'], + ['name' => 'shop_account#get_shop_user', 'url' => '/shop-accounts/user', 'verb' => 'GET'], + ['name' => 'shop_account#check_shop_email_post_delete', 'url' => '/shop-accounts/check_shop_email_post_delete', 'verb' => 'GET'], [ 'name' => 'user#preflighted_cors', 'url' => '/api/{path}', 'verb' => 'OPTIONS', 'requirements' => array('path' => '.+') @@ -15,7 +17,6 @@ return ['routes' => [ 'name' => 'update_beta_user#add_user_to_group', 'url' => '/api/groups/add', 'verb' => 'POST' ], - [ 'name' => 'update_beta_user#remove_user_from_group', 'url' => '/api/groups/remove', 'verb' => 'POST' diff --git a/lib/Controller/ShopAccountController.php b/lib/Controller/ShopAccountController.php index 7a4c7c09..c62b56c5 100644 --- a/lib/Controller/ShopAccountController.php +++ b/lib/Controller/ShopAccountController.php @@ -3,66 +3,66 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\Controller; +use Exception; use OCA\EcloudAccounts\Service\ShopAccountService; use OCP\IUserSession; use OCP\IRequest; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; -use OCP\IL10N; class ShopAccountController extends Controller { private $shopAccountService; private $userSession; - private $l10n; - private $shopOrdersUrl; - public function __construct($appName, IRequest $request, IUserSession $userSession, ShopAccountService $shopAccountService, IL10N $l10n) + public function __construct($appName, IRequest $request, IUserSession $userSession, ShopAccountService $shopAccountService) { parent::__construct($appName, $request); $this->shopAccountService = $shopAccountService; $this->userSession = $userSession; - $this->l10n = $l10n; - $this->shopOrdersUrl = getenv("WP_SHOP_URL") . '/my-account/orders'; } /** * @NoAdminRequired */ - - public function setShopEmailPostDelete(string $shopEmailPostDelete) { + public function checkShopEmailPostDelete(string $shopEmailPostDelete) { $user = $this->userSession->getUser(); - $userId = $user->getUID(); $email = $user->getEMailAddress(); $response = new DataResponse(); - $data = ['message' => '']; - - if(!filter_var($shopEmailPostDelete, FILTER_VALIDATE_EMAIL)) { + try { + $this->shopAccountService->validateShopEmailPostDelete($shopEmailPostDelete, $email); + } + catch(Exception $e) { $response->setStatus(400); - $data['message'] = 'Invalid Email Format.'; - $response->setData($data); + $response->setData(['message' => $e->getMessage()]); return $response; } + } + /** + * @NoAdminRequired + */ - if($shopEmailPostDelete === $email) { - $response->setStatus(400); - $data['message'] = 'Murena.com email cannot be same as this account\'s email.'; - $response->setData($data); - return $response; + public function setShopEmailPostDelete(string $shopEmailPostDelete) { + $user = $this->userSession->getUser(); + $userId = $user->getUID(); + $email = $user->getEMailAddress(); + $response = new DataResponse(); + + try { + $this->shopAccountService->validateShopEmailPostDelete($shopEmailPostDelete, $email); } - if($this->shopAccountService->shopEmailExists($shopEmailPostDelete, $email)) { + catch(Exception $e) { $response->setStatus(400); - $data['message'] = 'A Murena.com account already uses this e-mail address.'; - $response->setData($data); + $response->setData(['message' => $e->getMessage()]); return $response; } $this->shopAccountService->setShopEmailPostDeletePreference($userId, $shopEmailPostDelete); } - + /** * @NoAdminRequired */ @@ -76,27 +76,34 @@ class ShopAccountController extends Controller { /** * @NoAdminRequired */ - public function getOrderInfo() { + public function getOrderInfo(int $userId) { + $response = new DataResponse(); + $data = ['count' => 0, 'my_orders_url' => $this->shopAccountService->getShopUrl() . '/my-account/orders']; + $orders = $this->shopAccountService->getOrders($userId); + + if($orders) { + $data['count'] = count($orders); + } + + $response->setData($data); + return $response; + } + + /** + * @NoAdminRequired + */ + public function getShopUser() { $response = new DataResponse(); $user = $this->userSession->getUser(); $email = $user->getEMailAddress(); $shopUser = $this->shopAccountService->getUser($email); - $data = ['count' => 0, 'my_orders_url' => $this->shopOrdersUrl]; - if(!$shopUser) { - $response->setData($data); - return $response; - } - - $orders = $this->shopAccountService->getOrders($shopUser['id']); - if(!$orders) { - $response->setData($data); + if(!$shopUser || !$this->shopAccountService->isUserOIDC($shopUser)) { + $response->setStatus(404); return $response; } - - $data['count'] = count($orders); - $response->setData($data); + $response->setData($shopUser); return $response; } } \ No newline at end of file diff --git a/lib/Service/CurlService.php b/lib/Service/CurlService.php index 859e3ef9..1faebc0d 100644 --- a/lib/Service/CurlService.php +++ b/lib/Service/CurlService.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\Service; +use Exception; class CurlService { diff --git a/lib/Service/ShopAccountService.php b/lib/Service/ShopAccountService.php index 97288422..4595ef57 100644 --- a/lib/Service/ShopAccountService.php +++ b/lib/Service/ShopAccountService.php @@ -19,28 +19,45 @@ class ShopAccountService { public function __construct($appName, IConfig $config, CurlService $curlService, ILogger $logger) { - $shopUsername = getenv("WP_SHOP_USERNAME"); - $shopPassword = getenv("WP_SHOP_PASS"); - $shopUrl = getenv("WP_SHOP_URL"); - + $this->config = $config; + $shopUsername = $this->config->getSystemValue('murena_shop_username'); + $shopPassword = $this->config->getSystemValue('murena_shop_password'); + + $this->shopUrl = $this->config->getSystemValue('murena_shop_url'); $this->appName = $appName; - $this->shopUserUrl = $shopUrl . "/wp-json/wp/v2/users"; - $this->shopOrdersUrl = $shopUrl . "/wp-json/wc/v3/orders"; + + $this->shopUserUrl = $this->shopUrl . "/wp-json/wp/v2/users"; + $this->shopOrdersUrl = $this->shopUrl . "/wp-json/wc/v3/orders"; $this->shopCredentials = base64_encode($shopUsername . ":" . $shopPassword); $this->shopReassignUserId = getenv('WP_REASSIGN_USER_ID'); - $this->config = $config; $this->curl = $curlService; $this->logger = $logger; } + public function getShopUrl() { + return $this->shopUrl; + } + public function setShopDeletePreference($userId, bool $delete) { $this->config->setUserValue($userId, $this->appName, 'delete_shop_account', intval($delete)); } - public function shopEmailExists(string $shopEmail, string $ncUserEmail) : bool { + public function shopEmailExists(string $shopEmail) : bool { return !empty($this->getUser($shopEmail)); } + public function validateShopEmailPostDelete(string $shopEmailPostDelete, string $cloudEmail) : void { + if(!filter_var($shopEmailPostDelete, FILTER_VALIDATE_EMAIL)) { + throw new Exception('Invalid Email Format.'); + } + if($shopEmailPostDelete === $cloudEmail) { + throw new Exception('Murena.com email cannot be same as this account\'s email.'); + } + if($this->shopEmailExists($shopEmailPostDelete)) { + throw new Exception('A Murena.com account already uses this e-mail address.'); + } + } + public function setShopEmailPostDeletePreference($userId, string $shopEmailPostDelete) { $this->config->setUserValue($userId, $this->appName, 'shop_email_post_delete', $shopEmailPostDelete); } @@ -52,7 +69,7 @@ class ShopAccountService { public function getShopEmailPostDeletePreference($userId) { $recoveryEmail = $this->config->getUserValue($userId, 'email-recovery', 'recovery-email'); - return $this->config->getUserValue($userId, $this->appName, 'shop_email_post_delete', $recoveryEmail); + return $this->config->getUserValue($userId, $this->appName, 'shop_email_post_delete', $recoveryEmail); } public function getOrders(int $userId): ?array { @@ -86,7 +103,7 @@ class ShopAccountService { return $users[0]; } - public function deleteUser(int $userId) : void { + public function deleteUser(int $userId) : void { $params = [ 'force' => true, 'reassign' => $this->shopReassignUserId @@ -104,8 +121,8 @@ class ShopAccountService { $this->logger->error('Error deleting user at WP with ID ' . $userId); $this->logger->logException($e, ['app' => Application::APP_ID]); } - - } + + } public function updateUserEmail(int $userId, string $email) : void { $updateUrl = $this->shopUserUrl . '/' . strval($userId); @@ -116,7 +133,7 @@ class ShopAccountService { try { $answer = $this->callShopAPI($updateUrl, 'POST', $params); - + if($answer['email'] !== $email) { throw new Exception('Unknown error while updating!'); } @@ -128,7 +145,7 @@ class ShopAccountService { } private function callShopAPI(string $url, string $method, array $data = []) { - + $headers = [ "cache-control: no-cache", "content-type: application/json", diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php index 9faa8a19..f981db68 100644 --- a/lib/Settings/Personal.php +++ b/lib/Settings/Personal.php @@ -1,25 +1,4 @@ - * - * @author Thomas Citharel - * - * @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\EcloudAccounts\Settings; @@ -68,7 +47,7 @@ class Personal implements ISettings { * @since 9.1 */ public function getForm(): TemplateResponse { - + $user = $this->userSession->getUser(); if ($user) { $onlyUser = $this->userManager->countUsers() < 2; @@ -85,7 +64,7 @@ class Personal implements ISettings { $this->initialState->provideInitialState('only_user', $onlyUser); $this->initialState->provideInitialState('only_admin', $onlyAdmin); } - + return new TemplateResponse($this->appName, 'personal'); } @@ -95,11 +74,8 @@ class Personal implements ISettings { * @psalm-return 'drop_account' */ public function getSection(): ?string { - $user = $this->userSession->getUser(); - $shopUser = $this->shopAccountService->getUser($user->getEMailAddress()); $dropAccountEnabled = $this->appManager->isEnabledForUser(self::DROP_ACCOUNT_APP_ID); - - if($dropAccountEnabled && $shopUser && $this->shopAccountService->isUserOIDC($shopUser)) { + if($dropAccountEnabled) { return self::DROP_ACCOUNT_APP_ID; } return null; diff --git a/src/PersonalSettings.vue b/src/PersonalSettings.vue index 9f2a1067..bff823bb 100644 --- a/src/PersonalSettings.vue +++ b/src/PersonalSettings.vue @@ -1,5 +1,5 @@