diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6119917f226a5a16fd4103165beb5861724de6a1..ba1be46b0f6ed5bbeb5ca9ccc27b5f36d3149345 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,92 @@ +#include: +# - project: "e/infra/ecloud/nextcloud-apps/ci-templates" +# ref: main +# file: "nc-apps-lint-build-frontend.yml" +# - project: "e/infra/ecloud/nextcloud-apps/ci-templates" +# ref: main +# file: "nc-apps-deploy.yml" + variables: - TO_PACKAGE: 'appinfo l10n lib templates js img' -include: - - project: "e/infra/ecloud/nextcloud-apps/ci-templates" - ref: main - file: "nc-apps-lint-build-frontend.yml" - - project: "e/infra/ecloud/nextcloud-apps/ci-templates" - ref: main - file: "nc-apps-deploy.yml" + APP_NAME: $CI_PROJECT_NAME + TO_PACKAGE: 'appinfo js css l10n lib img templates' + CONTAINER_IMAGE: ubuntu + CONTAINER_TAG: focal + CONTAINER_NAME: nextcloud + APP_ENABLE_ARGS: '' + +.frontend:base: + image: node:15.14.0-stretch + before_script: + - npm set cache .npm + - npm install --prefer-offline --no-audit + cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - .npm/ + - node_modules/ + +install-node-deps: + extends: .frontend:base + stage: .pre + before_script: + - node --version + - npm --version + script: + - npm ci --cache .npm --prefer-offline + only: + changes: + - package*.json + +build-frontend: + extends: .frontend:base + stage: build + script: + - npm run build + - mkdir -p dist/${APP_NAME} + - rm -f dist/js/*.map + - echo "packaging ${TO_PACKAGE}" && cp -a ${TO_PACKAGE} dist/${APP_NAME} && rm -rf dist/js + - find dist/${APP_NAME} -type d -exec chmod 755 {} \; + - find dist/${APP_NAME} -type f -exec chmod 644 {} \; + artifacts: + paths: + - dist/ + +.deploy:nextcloud-app: + stage: deploy + # assuming all deployment will happen with sames image + image: $CONTAINER_IMAGE:$CONTAINER_TAG + # assuming we will need to add SSH for all deployment + before_script: + - echo "FAIL" > .job_status + - mkdir $HOME/.ssh + - chmod 700 ~/.ssh + - echo "$SSH_PRIVATE_KEY_ED" > $HOME/.ssh/id_ed25519 + - echo "$SSH_PUBKEY_ED" > $HOME/.ssh/id_ed25519.pub + - echo "$SSH_KNOWN_HOSTS" > $HOME/.ssh/known_hosts + - chmod 600 ~/.ssh/id_ed25519 + - chmod 644 ~/.ssh/known_hosts ~/.ssh/id_ed25519.pub + - apt-get update && apt-get install -y openssh-client rsync + script: + - echo "Deploying ${APP_NAME} to $CI_ENVIRONMENT_NAME ($DEPLOYMENT_HOST)" + - rsync -avzh dist/ $SSH_USER@$DEPLOYMENT_HOST:/tmp/${CI_JOB_ID} + - ssh $SSH_USER@$DEPLOYMENT_HOST "sudo docker exec -u www-data $CONTAINER_NAME /usr/local/bin/php /var/www/html/occ app:disable ${APP_NAME} && + sudo rsync -avzh --chown www-data:www-data --delete /tmp/${CI_JOB_ID}/${APP_NAME} ${DEPLOYMENT_PATH}/html/custom_apps/ && + sudo docker exec -u www-data $CONTAINER_NAME /usr/local/bin/php /var/www/html/occ app:enable ${APP_ENABLE_ARGS} ${APP_NAME}" + - echo "SUCCESS" > .job_status + after_script: + # reading job status, checking it and implementing additional steps + # are not handled here as rm -rf /tmp/${CI_JOB_ID} will always execute + - ssh $SSH_USER@$DEPLOYMENT_HOST "rm -rf /tmp/${CI_JOB_ID}" + +deploy:staging: + extends: .deploy:nextcloud-app + when: manual + only: + - main + - murena-main + - production + - tags + - dev/post-login-for-oidc + environment: + name: staging/01 + url: https://eeo.one diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 47cc7b6b743c69af62ee461abc476494fb2a99a0..5b1d6dffe31610d3241a964f01463fa6416dbc07 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -35,11 +35,11 @@ use OCA\EcloudAccounts\Service\LDAPConnectionService; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\UserChangedEvent; use OCA\EcloudAccounts\Listeners\UserChangedListener; -use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; -use OCA\EcloudAccounts\Listeners\BeforeTemplateRenderedListener; use OCA\EcloudAccounts\Listeners\TwoFactorStateChangedListener; use OCA\TwoFactorTOTP\Event\StateChanged; use OCP\IUserManager; +use OCA\OIDCLogin\Events\AccessTokenUpdatedEvent; +use OCA\EcloudAccounts\Listeners\AccessTokenUpdatedListener; class Application extends App implements IBootstrap { public const APP_ID = 'ecloud-accounts'; @@ -52,7 +52,7 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class); $context->registerEventListener(UserChangedEvent::class, UserChangedListener::class); $context->registerEventListener(StateChanged::class, TwoFactorStateChangedListener::class); - // $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); + $context->registerEventListener(AccessTokenUpdatedEvent::class, AccessTokenUpdatedListener::class); } public function boot(IBootContext $context): void { diff --git a/lib/Listeners/AccessTokenUpdatedListener.php b/lib/Listeners/AccessTokenUpdatedListener.php new file mode 100644 index 0000000000000000000000000000000000000000..52e87c529503d75f4c1c2e266557a4db5a5b1f6f --- /dev/null +++ b/lib/Listeners/AccessTokenUpdatedListener.php @@ -0,0 +1,49 @@ +userSession = $userSession; + $this->session = $session; + $this->appManager = $appManager; + } + + public function handle(Event $event): void { + if (!($event instanceof AccessTokenUpdatedEvent) || !$this->userSession->isLoggedIn() || !$this->session->exists('is_oidc')) { + return; + } + + // just-in-case checks(also maybe useful for selfhosters) + if (!$this->appManager->isEnabledForUser(self::SNAPPYMAIL_APP_ID) || !$this->appManager->isEnabledForUser(self::OIDC_LOGIN_APP_ID)) { + return; + } + + $accessToken = $event->getAccessToken(); + if (!$accessToken) { + return; + } + + $username = $this->userSession->getUser()->getUID(); + + $this->session->set('snappymail-password', SnappyMailHelper::encodePassword($accessToken, $username)); + } +} diff --git a/lib/Listeners/BeforeTemplateRenderedListener.php b/lib/Listeners/BeforeTemplateRenderedListener.php deleted file mode 100644 index 9c6369c362a2514df3aeeb43b41917997e2354b0..0000000000000000000000000000000000000000 --- a/lib/Listeners/BeforeTemplateRenderedListener.php +++ /dev/null @@ -1,77 +0,0 @@ -appName = $appName; - $this->userSession = $userSession; - $this->request = $request; - $this->session = $session; - $this->config = $config; - $this->appManager = $appManager; - } - - public function handle(Event $event): void { - if (!($event instanceof BeforeTemplateRenderedEvent)) { - return; - } - if ($this->userSession->isLoggedIn() && $this->appManager->isEnabledForUser(self::SNAPPYMAIL_APP_ID) && strpos($this->request->getPathInfo(), self::SNAPPYMAIL_URL) !== false) { - $this->autoLoginWebmail(); - } - } - - - private function autoLoginWebmail() { - $isOidcLogin = $this->session->get('is_oidc'); - if (!$isOidcLogin) { - return; - } - $accountId = $this->getAccountId(); - $actions = \RainLoop\Api::Actions(); - - if (empty($accountId) || $actions->getMainAccountFromToken(false)) { - return; - } - - // Just send over '1' as password to trigger login as the plugin will set the correct access token - $password = self::SNAPPYMAIL_AUTOLOGIN_PWD; // As we cannot pass by reference to LoginProcess - $account = $actions->LoginProcess($accountId, $password, false); - if ($account) { - $actions->Plugins()->RunHook('login.success', array($account)); - $actions->SetAuthToken($account); - } - } - - private function getAccountId() : string { - $username = $this->userSession->getUser()->getUID(); - if ($this->config->getAppValue('snappymail', 'snappymail-autologin', false)) { - return $username; - } - if ($this->config->getAppValue('snappymail', 'snappymail-autologin-with-email', false)) { - return $this->config->getUserValue($username, 'settings', 'email', ''); - } - } -}