Skip to content

Commit

Permalink
Don't store well-known files on a disk
Browse files Browse the repository at this point in the history
  • Loading branch information
yurabakhtin committed Jun 19, 2024
1 parent 82bde3a commit 921d0cb
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 59 deletions.
40 changes: 40 additions & 0 deletions components/UrlRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/

namespace humhub\modules\fcmPush\components;

use humhub\modules\fcmPush\services\WellKnownService;
use yii\base\Component;
use yii\web\UrlRuleInterface;

class UrlRule extends Component implements UrlRuleInterface
{
/**
* @inheritdoc
*/
public function createUrl($manager, $route, $params)
{
if ($route === trim(WellKnownService::URL_ROUTE, '/') && isset($params['file'])) {
return WellKnownService::URL_PREFIX . $params['file'];
}

return false;
}

/**
* @inheritdoc
*/
public function parseRequest($manager, $request)
{
$path = $request->getPathInfo();
if (str_starts_with($path, WellKnownService::URL_PREFIX)) {
return WellKnownService::instance($path)->getRuleRoute() ?? false;
}

return false;
}
}
6 changes: 4 additions & 2 deletions config.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
],
];
?>
19 changes: 19 additions & 0 deletions controllers/WellKnownController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/

namespace humhub\modules\fcmPush\controllers;

use humhub\components\Controller;
use humhub\modules\fcmPush\services\WellKnownService;

class WellKnownController extends Controller
{
public function actionIndex(string $file)
{
return WellKnownService::instance($file)->renderFile();
}
}
78 changes: 27 additions & 51 deletions models/ConfigureForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,9 +26,9 @@ class ConfigureForm extends Model

public $disableAuthChoicesIos;

public $fileAssetlinksJson;
public $fileAssetLinks;

public $fileAppleAppSiteAssociation;
public $fileAppleAssociation;

/**
* Validate JSON field params
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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') . '"',
]),
];
}

Expand All @@ -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'),
]),
];
}

Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
}
83 changes: 83 additions & 0 deletions services/WellKnownService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/

namespace humhub\modules\fcmPush\services;

use Exception;
use humhub\modules\fcmPush\Module;
use Yii;
use yii\helpers\Json;
use yii\web\Response;

class WellKnownService
{
public const URL_ROUTE = '/fcm-push/well-known';
public const URL_PREFIX = '.well-known/';
public const ALLOWED_FILES = [
'fileAssetLinks' => '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;
}
}
22 changes: 16 additions & 6 deletions views/admin/index.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php
/* @var $this \humhub\modules\ui\view\components\View */

/* @var $model \humhub\modules\fcmPush\models\ConfigureForm */

use humhub\modules\fcmPush\models\ConfigureForm;
use humhub\modules\ui\icon\widgets\Icon;
use humhub\widgets\Button;
use humhub\modules\ui\form\widgets\ActiveForm;
use yii\helpers\Html;

/* @var $model ConfigureForm */
?>
<div class="panel panel-default">
<div class="panel-heading"><?= Yii::t('FcmPushModule.base', '<strong>FireBase Messaging</strong> Configuration'); ?></div>
Expand All @@ -16,7 +16,7 @@
<h3><?= Yii::t('FcmPushModule.base', 'Link Redirection Service') ?></h3>
<?= $form->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 // <a href="{url}">Privacy Policy</a>)', [
'url' => 'https://www.humhub.com/en/privacy/'
'url' => 'https://www.humhub.com/en/privacy/',
])) ?>

<hr>
Expand Down Expand Up @@ -49,8 +49,18 @@
<?= $form->beginCollapsibleFields('Advanced Settings'); ?>
<?= $form->field($model, 'disableAuthChoicesIos')->checkbox()
->label(Yii::t('FcmPushModule.base', 'Hide third-party login options for app users with iOS.')) ?>
<?= $form->field($model, 'fileAssetlinksJson')->textarea(['rows' => 10]) ?>
<?= $form->field($model, 'fileAppleAppSiteAssociation')->textarea(['rows' => 10]) ?>

<?php if (!Yii::$app->urlManager->enablePrettyUrl) : ?>
<div class="alert alert-warning">
<?= Icon::get('warning') ?>
<?= Yii::t('FcmPushModule.base', 'Please enable <a {attrs}>Pretty URLs</a> for proper working of the well-known files.', [
'attrs' => 'href="https://docs.humhub.org/docs/admin/installation/#pretty-urls" target="_blank"',
]) ?>
</div>
<?php endif; ?>

<?= $form->field($model, 'fileAssetLinks')->textarea(['rows' => 10]) ?>
<?= $form->field($model, 'fileAppleAssociation')->textarea(['rows' => 10]) ?>
<?= $form->endCollapsibleFields(); ?>
<br/>

Expand Down

0 comments on commit 921d0cb

Please sign in to comment.