mirror of
https://github.com/humhub/humhub.git
synced 2025-01-17 14:18:27 +01:00
Display confirmation message before display embedded content (#5490)
* Display confirmation message before display embedded content * Fix confirmation of embedded content * Optimize loading of embedded content * New setting "Show Oembed content only after consent" * Small fix * Change wording * Fix wording
This commit is contained in:
parent
154266f188
commit
3894b250a6
@ -6,3 +6,4 @@
|
||||
- Enh #5472: New interface `TabbedFormModel` for activate first tab with error input
|
||||
- Enh #5224: Add reply-to email in the settings
|
||||
- Enh #5471: On the pending approval page, add grouped actions and custom columns
|
||||
- Enh #5490: Display confirmation message before display embedded content
|
||||
|
@ -12,6 +12,7 @@ namespace humhub\controllers;
|
||||
use humhub\components\Controller;
|
||||
use humhub\models\UrlOembed;
|
||||
use Yii;
|
||||
use yii\web\HttpException;
|
||||
|
||||
/**
|
||||
* @since 1.3
|
||||
@ -44,4 +45,33 @@ class OembedController extends Controller
|
||||
|
||||
return $this->asJson($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the hidden embedded content
|
||||
*/
|
||||
public function actionDisplay()
|
||||
{
|
||||
$this->forcePostRequest();
|
||||
|
||||
$url = Yii::$app->request->post('url');
|
||||
if (empty($url)) {
|
||||
throw new HttpException(400, 'URL is not provided!');
|
||||
}
|
||||
|
||||
$urlData = parse_url($url);
|
||||
if (!isset($urlData['host'])) {
|
||||
throw new HttpException(400, 'Wrong URL!');
|
||||
}
|
||||
|
||||
if (Yii::$app->request->post('alwaysShow', false)) {
|
||||
UrlOembed::saveAllowedDomain($urlData['host']);
|
||||
}
|
||||
|
||||
$urlOembed = UrlOembed::findExistingOembed($url);
|
||||
|
||||
return $this->asJson([
|
||||
'success' => true,
|
||||
'content' => $urlOembed ? $urlOembed->preview : UrlOembed::loadUrl($url)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,10 @@
|
||||
|
||||
namespace humhub\models;
|
||||
|
||||
use yii\base\InvalidArgumentException;
|
||||
use humhub\modules\admin\models\forms\OEmbedSettingsForm;
|
||||
use humhub\modules\ui\icon\widgets\Icon;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\widgets\Button;
|
||||
use humhub\events\OembedFetchEvent;
|
||||
use humhub\libs\RestrictedCallException;
|
||||
use humhub\libs\UrlOembedClient;
|
||||
@ -154,10 +157,15 @@ class UrlOembed extends ActiveRecord
|
||||
$url = trim($url);
|
||||
|
||||
if (static::hasOEmbedSupport($url)) {
|
||||
$urlOembed = static::findExistingOembed($url);
|
||||
$result = $urlOembed ? $urlOembed->preview : self::loadUrl($url);
|
||||
if (!self::isAllowedDomain($url)) {
|
||||
$result = self::confirmationContent($url);
|
||||
} else {
|
||||
$urlOembed = static::findExistingOembed($url);
|
||||
$result = $urlOembed ? $urlOembed->preview : self::loadUrl($url);
|
||||
}
|
||||
|
||||
if (!empty($result)) {
|
||||
|
||||
return trim(preg_replace('/\s+/', ' ', $result));
|
||||
}
|
||||
}
|
||||
@ -208,7 +216,7 @@ class UrlOembed extends ActiveRecord
|
||||
* @return UrlOembed|null
|
||||
* @throws RestrictedCallException
|
||||
*/
|
||||
protected static function findExistingOembed($url)
|
||||
public static function findExistingOembed($url)
|
||||
{
|
||||
if (array_key_exists($url, static::$cache)) {
|
||||
return static::$cache[$url];
|
||||
@ -292,6 +300,35 @@ class UrlOembed extends ActiveRecord
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the embedded content with confirmation before display it
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
protected static function confirmationContent(string $url): string
|
||||
{
|
||||
$urlData = parse_url($url);
|
||||
$urlPrefix = $urlData['host'] ?? $url;
|
||||
|
||||
$html = Html::tag('strong', Yii::t('base', 'Allow content from external source')) .
|
||||
Html::tag('br') .
|
||||
Yii::t('base', 'Do you want to enable content from \'{urlPrefix}\'?', ['urlPrefix' => Html::tag('strong', $urlPrefix)]) .
|
||||
Html::tag('br') .
|
||||
Html::tag('label', '<input type="checkbox">' . Yii::t('base', 'Always allow content from this provider!')) .
|
||||
Html::tag('br') .
|
||||
Button::info(Yii::t('base', 'Confirm'))->action('oembed.display')->sm();
|
||||
|
||||
$html = Icon::get('info-circle') .
|
||||
Html::tag('div', $html) .
|
||||
Html::tag('div', '', ['class' => 'clearfix']);
|
||||
|
||||
return Html::tag('div', $html, [
|
||||
'data-url' => $url,
|
||||
'class' => 'oembed_confirmation',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given $data array.
|
||||
*
|
||||
@ -399,4 +436,77 @@ class UrlOembed extends ActiveRecord
|
||||
Yii::$app->settings->set('oembedProviders', Json::encode($providers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the domain is always allowed to display for current User
|
||||
*
|
||||
* @param string $url Domain or full URL
|
||||
* @return array
|
||||
*/
|
||||
public static function isAllowedDomain(string $url): bool
|
||||
{
|
||||
$oembedSettings = new OEmbedSettingsForm();
|
||||
if (!$oembedSettings->requestConfirmation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preg_match('#^(https?:)?//#i',$url)) {
|
||||
$url = parse_url($url);
|
||||
if (!isset($url['host'])) {
|
||||
return false;
|
||||
}
|
||||
$url = $url['host'];
|
||||
}
|
||||
|
||||
return array_search($url, self::getAllowedDomains()) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get domains always allowed to be displayed for current User
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllowedDomains(): array
|
||||
{
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/* @var User $user */
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
|
||||
$allowedUrls = $user->settings->get('allowedOembedUrls');
|
||||
|
||||
return empty($allowedUrls) ? [] : explode(',', $allowedUrls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new allowed domain for oembed URLs to the current User settings
|
||||
*
|
||||
* @param string $domain
|
||||
* @return bool
|
||||
*/
|
||||
public static function saveAllowedDomain(string $domain): bool
|
||||
{
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self::isAllowedDomain($domain)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$allowedUrls = self::getAllowedDomains();
|
||||
$allowedUrls[] = $domain;
|
||||
|
||||
/* @var User $user */
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
$user->settings->set('allowedOembedUrls', implode(',', $allowedUrls));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ use humhub\modules\admin\models\forms\FileSettingsForm;
|
||||
use humhub\modules\admin\models\forms\LogsSettingsForm;
|
||||
use humhub\modules\admin\models\forms\MailingSettingsForm;
|
||||
use humhub\modules\admin\models\forms\OEmbedProviderForm;
|
||||
use humhub\modules\admin\models\forms\OEmbedSettingsForm;
|
||||
use humhub\modules\admin\models\forms\ProxySettingsForm;
|
||||
use humhub\modules\admin\models\forms\StatisticSettingsForm;
|
||||
use humhub\modules\admin\permissions\ManageSettings;
|
||||
@ -301,9 +302,17 @@ class SettingController extends Controller
|
||||
public function actionOembed()
|
||||
{
|
||||
$providers = UrlOembed::getProviders();
|
||||
return $this->render('oembed',
|
||||
[
|
||||
'providers' => $providers
|
||||
$settings = new OEmbedSettingsForm();
|
||||
|
||||
|
||||
if ($settings->load(Yii::$app->request->post()) && $settings->save()) {
|
||||
$this->view->saved();
|
||||
return $this->redirect(['/admin/setting/oembed']);
|
||||
}
|
||||
|
||||
return $this->render('oembed', [
|
||||
'providers' => $providers,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2021 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\admin\models\forms;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* OEmbed settings form
|
||||
*
|
||||
* @package humhub.modules_core.admin.forms
|
||||
* @since 1.11
|
||||
*/
|
||||
class OEmbedSettingsForm extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $requestConfirmation;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
$this->requestConfirmation = (bool) Yii::$app->settings->get('oembed.requestConfirmation', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['requestConfirmation', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'requestConfirmation' => Yii::t('AdminModule.settings', 'Embedded content requires the user\'s consent to be loaded'),
|
||||
];
|
||||
}
|
||||
|
||||
public function save(): bool
|
||||
{
|
||||
if (!$this->validate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Yii::$app->settings->set('oembed.requestConfirmation', $this->requestConfirmation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,13 @@
|
||||
<?php
|
||||
|
||||
use humhub\modules\admin\models\forms\OEmbedSettingsForm;
|
||||
use humhub\modules\ui\form\widgets\ActiveForm;
|
||||
use humhub\widgets\Button;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/* @var array $providers */
|
||||
/* @var OEmbedSettingsForm $settings */
|
||||
?>
|
||||
|
||||
<?php $this->beginContent('@admin/views/setting/_advancedLayout.php') ?>
|
||||
@ -22,4 +28,12 @@ use yii\helpers\Url;
|
||||
<p><strong><?= Yii::t('AdminModule.settings', 'Currently no provider active!'); ?></strong></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php $form = ActiveForm::begin() ?>
|
||||
|
||||
<?= $form->field($settings, 'requestConfirmation')->checkbox() ?>
|
||||
|
||||
<?= Button::primary(Yii::t('AdminModule.settings', 'Save'))->submit() ?>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
|
||||
<?php $this->endContent(); ?>
|
||||
|
@ -162,7 +162,8 @@ class CoreJsConfig extends Widget
|
||||
]
|
||||
],
|
||||
'oembed' => [
|
||||
'loadUrl' => Url::to(['/oembed'])
|
||||
'loadUrl' => Url::to(['/oembed']),
|
||||
'displayUrl' => Url::to(['/oembed/display']),
|
||||
],
|
||||
'ui.markdown', [
|
||||
'text' => [
|
||||
|
@ -28,28 +28,58 @@ humhub.module('oembed', function(module, require, $) {
|
||||
});
|
||||
};
|
||||
|
||||
var get = function(url) {
|
||||
var $result = null;
|
||||
const get = function(url) {
|
||||
const $result = cache[url] ? $(cache[url]) : findSnippetByUrl(url);
|
||||
|
||||
if (cache[url]) {
|
||||
$result = $(cache[url]);
|
||||
} else {
|
||||
var $dom = $('[data-oembed="' + $.escapeSelector(util.string.escapeHtml(url, true)) + '"]:first');
|
||||
if ($dom.length && $dom.is('[data-oembed]')) {
|
||||
$result = $dom.find('.oembed_snippet').clone().show();
|
||||
}
|
||||
}
|
||||
|
||||
if($result && $result.is('.oembed_snippet')) {
|
||||
if ($result && $result.is('.oembed_snippet,.oembed_confirmation')) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const findSnippetByUrl = function(url) {
|
||||
const $dom = $('[data-oembed="' + $.escapeSelector(util.string.escapeHtml(url, true)) + '"]:first')
|
||||
if (!$dom.length || !$dom.is('[data-oembed]')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const confirmation = $dom.find('.oembed_confirmation');
|
||||
if (confirmation.length) {
|
||||
return confirmation.clone().show();
|
||||
}
|
||||
|
||||
return $dom.find('.oembed_snippet').clone().show();
|
||||
}
|
||||
|
||||
const display = function(evt) {
|
||||
const confirmation = evt.$trigger.closest('.oembed_confirmation');
|
||||
if (!confirmation.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
url: confirmation.data('url'),
|
||||
alwaysShow: confirmation.find('input[type=checkbox]:checked').length ? 1 : 0,
|
||||
}
|
||||
|
||||
client.post(module.config.displayUrl, {data}).then(function(response) {
|
||||
if (response.success) {
|
||||
confirmation.after(response.content).remove();
|
||||
} else {
|
||||
module.log.error(response, true);
|
||||
evt.finish();
|
||||
}
|
||||
}).catch(function(e) {
|
||||
module.log.error(e, true);
|
||||
evt.finish();
|
||||
});
|
||||
};
|
||||
|
||||
module.export({
|
||||
load: load,
|
||||
get: get
|
||||
load,
|
||||
get,
|
||||
display,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -20,3 +20,33 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.oembed_confirmation {
|
||||
background: #feebb4;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
line-height: 30px;
|
||||
i.fa {
|
||||
float: left;
|
||||
color: #02a0b0;
|
||||
background: #FFF;
|
||||
border-radius: 50%;
|
||||
font-size: 30px;
|
||||
line-height: 25px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
> div:not(.clearfix) {
|
||||
float: left;
|
||||
}
|
||||
.regular-checkbox-box {
|
||||
top: 6px;
|
||||
}
|
||||
.regular-checkbox {
|
||||
&:not(:checked) + .regular-checkbox-box {
|
||||
background: #FFF;
|
||||
}
|
||||
&:checked + .regular-checkbox-box:after {
|
||||
top: -8px;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user