From 921d0cb279119f93871caae81279e2f3054e2e21 Mon Sep 17 00:00:00 2001 From: Yuriy Bakhtin Date: Wed, 19 Jun 2024 11:21:45 +0200 Subject: [PATCH] Don't store well-known files on a disk --- components/UrlRule.php | 40 ++++++++++++++ config.php | 6 ++- controllers/WellKnownController.php | 19 +++++++ models/ConfigureForm.php | 78 ++++++++++----------------- services/WellKnownService.php | 83 +++++++++++++++++++++++++++++ views/admin/index.php | 22 +++++--- 6 files changed, 189 insertions(+), 59 deletions(-) create mode 100644 components/UrlRule.php create mode 100644 controllers/WellKnownController.php create mode 100644 services/WellKnownService.php diff --git a/components/UrlRule.php b/components/UrlRule.php new file mode 100644 index 0000000..ef774ef --- /dev/null +++ b/components/UrlRule.php @@ -0,0 +1,40 @@ +getPathInfo(); + if (str_starts_with($path, WellKnownService::URL_PREFIX)) { + return WellKnownService::instance($path)->getRuleRoute() ?? false; + } + + return false; + } +} diff --git a/config.php b/config.php index faefe29..20353ef 100644 --- a/config.php +++ b/config.php @@ -27,7 +27,9 @@ //[NotificationInfoWidget::class, \humhub\widgets\BaseStack::EVENT_RUN, [Events::class, 'onNotificationInfoWidget']] ], 'consoleControllerMap' => [ - 'firebase' => 'humhub\modules\fcmPush\commands\SendController' + 'firebase' => 'humhub\modules\fcmPush\commands\SendController', + ], + 'urlManagerRules' => [ + ['class' => 'humhub\modules\fcmPush\components\UrlRule'], ], ]; -?> \ No newline at end of file diff --git a/controllers/WellKnownController.php b/controllers/WellKnownController.php new file mode 100644 index 0000000..281c91e --- /dev/null +++ b/controllers/WellKnownController.php @@ -0,0 +1,19 @@ +renderFile(); + } +} diff --git a/models/ConfigureForm.php b/models/ConfigureForm.php index 1dcf0c3..b6b5c1d 100644 --- a/models/ConfigureForm.php +++ b/models/ConfigureForm.php @@ -2,19 +2,16 @@ namespace humhub\modules\fcmPush\models; -use Exception; use humhub\modules\fcmPush\Module; +use humhub\modules\fcmPush\services\WellKnownService; +use humhub\widgets\Link; use Yii; use yii\base\InvalidArgumentException; use yii\base\Model; -use yii\helpers\FileHelper; use yii\helpers\Json; class ConfigureForm extends Model { - public const FILE_ASSET_LINKS = 'assetlinks.json'; - public const FILE_APPLE_ASSOCIATION = 'apple-app-site-association'; - public $enableEmailGoService; public $humhubInstallId; @@ -29,9 +26,9 @@ class ConfigureForm extends Model public $disableAuthChoicesIos; - public $fileAssetlinksJson; + public $fileAssetLinks; - public $fileAppleAppSiteAssociation; + public $fileAppleAssociation; /** * Validate JSON field params @@ -93,7 +90,7 @@ public function rules() [['enableEmailGoService', 'disableAuthChoicesIos'], 'boolean'], [['senderId'], 'number'], [['serverKey', 'json', 'humhubApiKey'], 'safe'], - [['fileAssetlinksJson', 'fileAppleAppSiteAssociation'], 'string'], + [['fileAssetLinks', 'fileAppleAssociation'], 'string'], ['json', function ($attribute, $params, $validator) { if (empty($this->$attribute)) { return; @@ -150,8 +147,12 @@ public function attributeLabels() 'json' => Yii::t('FcmPushModule.base', 'Service Account (JSON file)'), 'serverKey' => Yii::t('FcmPushModule.base', 'Cloud Messaging API (Legacy)'), 'disableAuthChoicesIos' => Yii::t('FcmPushModule.base', 'Disable AuthChoices on iOS App'), - 'fileAssetlinksJson' => Yii::t('FcmPushModule.base', 'Well-known file {fileName}', ['fileName' => '"' . self::FILE_ASSET_LINKS . '"']), - 'fileAppleAppSiteAssociation' => Yii::t('FcmPushModule.base', 'Well-known file {fileName}', ['fileName' => '"' . self::FILE_APPLE_ASSOCIATION . '"']), + 'fileAssetLinks' => Yii::t('FcmPushModule.base', 'Well-known file {fileName}', [ + 'fileName' => '"' . WellKnownService::getFileName('fileAssetLinks') . '"', + ]), + 'fileAppleAssociation' => Yii::t('FcmPushModule.base', 'Well-known file {fileName}', [ + 'fileName' => '"' . WellKnownService::getFileName('fileAppleAssociation') . '"', + ]), ]; } @@ -161,6 +162,18 @@ public function attributeHints() 'humhubInstallId' => Yii::t('FcmPushModule.base', 'Use this ID to register your API Key.'), 'serverKey' => Yii::t('FcmPushModule.base', 'Please switch to the new "Firebase Cloud Messaging API (V1)" and enter a JSON file in the field above. The old legacy API is only temporarily available for existing installations and is no longer supported or maintained.'), 'json' => Yii::t('FcmPushModule.base', 'Paste the content of the service account JSON files here. You can find more information in the module instructions.'), + 'fileAssetLinks' => Yii::t('FcmPushModule.base', 'URL to the file {fileNameLink}', [ + 'fileNameLink' => Link::to( + WellKnownService::getFileName('fileAssetLinks'), + WellKnownService::getFileRoute('fileAssetLinks'), + )->target('_blank'), + ]), + 'fileAppleAssociation' => Yii::t('FcmPushModule.base', 'URL to the file {fileNameLink}', [ + 'fileNameLink' => Link::to( + WellKnownService::getFileName('fileAppleAssociation'), + WellKnownService::getFileRoute('fileAppleAssociation'), + )->target('_blank'), + ]), ]; } @@ -181,8 +194,8 @@ public function loadSettings() $this->serverKey = $settings->get('serverKey'); $this->humhubApiKey = $settings->get('humhubApiKey'); $this->disableAuthChoicesIos = $settings->get('disableAuthChoicesIos'); - $this->fileAssetlinksJson = $this->getFileContent(self::FILE_ASSET_LINKS); - $this->fileAppleAppSiteAssociation = $this->getFileContent(self::FILE_APPLE_ASSOCIATION); + $this->fileAssetLinks = $settings->get('fileAssetLinks'); + $this->fileAppleAssociation = $settings->get('fileAppleAssociation'); return true; } @@ -198,8 +211,8 @@ public function saveSettings() $module->settings->set('serverKey', $this->serverKey); $module->settings->set('humhubApiKey', $this->humhubApiKey); $module->settings->set('disableAuthChoicesIos', $this->disableAuthChoicesIos); - $this->saveFile(self::FILE_ASSET_LINKS, $this->fileAssetlinksJson); - $this->saveFile(self::FILE_APPLE_ASSOCIATION, $this->fileAppleAppSiteAssociation); + $module->settings->set('fileAssetLinks', $this->fileAssetLinks); + $module->settings->set('fileAppleAssociation', $this->fileAppleAssociation); return true; } @@ -216,41 +229,4 @@ public static function getInstance() return $config; } - - protected function getFilePath(string $fileName): string - { - return Yii::getAlias('@webroot') . DIRECTORY_SEPARATOR . '.well-known' . DIRECTORY_SEPARATOR . $fileName; - } - - protected function getFileContent(string $fileName): string - { - $filePath = $this->getFilePath($fileName); - return is_file($filePath) ? file_get_contents($filePath) : ''; - } - - protected function saveFile(string $fileName, ?string $content): bool - { - $filePath = $this->getFilePath($fileName); - if (!file_exists($filePath)) { - if (empty($content) && $content !== '0') { - // Don't create a file with empty content - return true; - } - - $dirPath = dirname($filePath); - try { - FileHelper::createDirectory($dirPath); - } catch (Exception $ex) { - Yii::error('Cannot create the dir ' . $dirPath . ' Error: ' . $ex->getMessage(), 'fcm-push'); - } - } - - try { - return (bool) file_put_contents($filePath, $content); - } catch (Exception $ex) { - Yii::error('Cannot update the file ' . $filePath . ' Error: ' . $ex->getMessage(), 'fcm-push'); - } - - return false; - } } diff --git a/services/WellKnownService.php b/services/WellKnownService.php new file mode 100644 index 0000000..96c3d3e --- /dev/null +++ b/services/WellKnownService.php @@ -0,0 +1,83 @@ + 'assetlinks.json', + 'fileAppleAssociation' => 'apple-app-site-association', + ]; + + private ?string $file; + + public function __construct(string $path) + { + $this->file = preg_replace('#^' . preg_quote(self::URL_PREFIX) . '#', '', $path); + } + + public static function instance(string $path): self + { + return new self($path); + } + + public static function getFileName(string $settingName): string + { + return self::ALLOWED_FILES[$settingName] ?? ''; + } + + public static function getFileRoute(string $settingName): array + { + return [self::URL_ROUTE, 'file' => self::getFileName($settingName)]; + } + + public function isAllowed(): bool + { + return in_array($this->file, self::ALLOWED_FILES); + } + + public function getRuleRoute(): ?array + { + return $this->isAllowed() ? [self::URL_ROUTE, ['file' => $this->file]] : null; + } + + public function getFileContent(): string + { + $settingName = array_search($this->file, self::ALLOWED_FILES); + if ($settingName === false) { + return ''; + } + + /* @var Module $module */ + $module = Yii::$app->getModule('fcm-push'); + + return $module->settings->get($settingName, ''); + } + + public function renderFile(): Response + { + Yii::$app->response->format = Response::FORMAT_JSON; + + try { + Yii::$app->response->data = Json::decode($this->getFileContent()); + } catch (Exception $ex) { + Yii::$app->response->data = ''; + Yii::error('Wrong file format "' . $this->file . '". Error: ' . $ex->getMessage(), 'fcm-push'); + } + + return Yii::$app->response; + } +} diff --git a/views/admin/index.php b/views/admin/index.php index 51d7ccf..e809321 100644 --- a/views/admin/index.php +++ b/views/admin/index.php @@ -1,12 +1,12 @@
FireBase Messaging Configuration'); ?>
@@ -16,7 +16,7 @@

field($model, 'enableEmailGoService')->checkbox() ->label(Yii::t('FcmPushModule.base', 'Enable Link Redirection Service. In order for links to open in the app on mobile devices, rather than in the mobile browser, all links (e.g. notification emails) need to be routed through the HumHub proxy server. (Experimental Features // Privacy Policy)', [ - 'url' => 'https://www.humhub.com/en/privacy/' + 'url' => 'https://www.humhub.com/en/privacy/', ])) ?>
@@ -49,8 +49,18 @@ beginCollapsibleFields('Advanced Settings'); ?> field($model, 'disableAuthChoicesIos')->checkbox() ->label(Yii::t('FcmPushModule.base', 'Hide third-party login options for app users with iOS.')) ?> - field($model, 'fileAssetlinksJson')->textarea(['rows' => 10]) ?> - field($model, 'fileAppleAppSiteAssociation')->textarea(['rows' => 10]) ?> + + urlManager->enablePrettyUrl) : ?> +
+ + Pretty URLs for proper working of the well-known files.', [ + 'attrs' => 'href="https://docs.humhub.org/docs/admin/installation/#pretty-urls" target="_blank"', + ]) ?> +
+ + + field($model, 'fileAssetLinks')->textarea(['rows' => 10]) ?> + field($model, 'fileAppleAssociation')->textarea(['rows' => 10]) ?> endCollapsibleFields(); ?>