Move server domain pattern blocklist features to its own class

- Update tests
This commit is contained in:
Hypolite Petovan 2022-07-27 15:36:20 -04:00
parent e445975c20
commit 1810b32c26
7 changed files with 458 additions and 421 deletions

View file

@ -21,58 +21,90 @@
namespace Friendica\Module\Admin\Blocklist\Server;
use Friendica\App;
use Friendica\Content\ContactSelector;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\Worker;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\GServer;
use Friendica\Moderation\DomainPatternBlocklist;
use Friendica\Module\BaseAdmin;
use Friendica\Module\Response;
use Friendica\Navigation\SystemMessages;
use Friendica\Util\Profiler;
use GuzzleHttp\Psr7\Uri;
use Psr\Log\LoggerInterface;
class Add extends BaseAdmin
{
/** @var SystemMessages */
private $sysmsg;
/** @var DomainPatternBlocklist */
private $blocklist;
public function __construct(SystemMessages $sysmsg, DomainPatternBlocklist $blocklist, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
{
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->sysmsg = $sysmsg;
$this->blocklist = $blocklist;
}
/**
* @param array $request
* @return void
* @throws \Friendica\Network\HTTPException\ForbiddenException
* @throws \Friendica\Network\HTTPException\FoundException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \Friendica\Network\HTTPException\MovedPermanentlyException
* @throws \Friendica\Network\HTTPException\TemporaryRedirectException
* @throws \Exception
*/
protected function post(array $request = [])
{
self::checkAdminAccess();
if (empty($_POST['page_blocklist_add'])) {
if (empty($request['page_blocklist_add'])) {
return;
}
self::checkFormSecurityTokenRedirectOnError('/admin/blocklist/server/add', 'admin_blocklist_add');
$pattern = trim($request['pattern']);
// Add new item to blocklist
$domain = trim($_POST['pattern']);
$this->blocklist->addPattern($pattern, trim($request['reason']));
$blocklist = DI::config()->get('system', 'blocklist');
$blocklist[] = [
'domain' => $domain,
'reason' => trim($_POST['reason']),
];
DI::config()->set('system', 'blocklist', $blocklist);
$this->sysmsg->addInfo($this->l10n->t('Server domain pattern added to the blocklist.'));
info(DI::l10n()->t('Server domain pattern added to the blocklist.'));
if (!empty($_POST['purge'])) {
$gservers = GServer::listByDomainPattern($domain);
if (!empty($request['purge'])) {
$gservers = GServer::listByDomainPattern($pattern);
foreach (Contact::selectToArray(['id'], ['gsid' => array_column($gservers, 'id')]) as $contact) {
Worker::add(PRIORITY_LOW, 'Contact\RemoveContent', $contact['id']);
}
info(DI::l10n()->tt('%s server scheduled to be purged.', '%s servers scheduled to be purged.', count($gservers)));
$this->sysmsg->addInfo($this->l10n->tt('%s server scheduled to be purged.', '%s servers scheduled to be purged.', count($gservers)));
}
DI::baseUrl()->redirect('admin/blocklist/server');
$this->baseUrl->redirect('admin/blocklist/server');
}
/**
* @param array $request
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \Friendica\Network\HTTPException\ServiceUnavailableException
* @throws \Exception
*/
protected function content(array $request = []): string
{
parent::content();
$gservers = [];
if ($pattern = trim($_REQUEST['pattern'] ?? '')) {
if ($pattern = trim($request['pattern'] ?? '')) {
$gservers = GServer::listByDomainPattern($pattern);
}
@ -85,28 +117,28 @@ class Add extends BaseAdmin
$t = Renderer::getMarkupTemplate('admin/blocklist/server/add.tpl');
return Renderer::replaceMacros($t, [
'$l10n' => [
'return_list' => DI::l10n()->t('← Return to the list'),
'title' => DI::l10n()->t('Administration'),
'page' => DI::l10n()->t('Block A New Server Domain Pattern'),
'syntax' => DI::l10n()->t('<p>The server domain pattern syntax is case-insensitive shell wildcard, comprising the following special characters:</p>
'return_list' => $this->l10n->t('← Return to the list'),
'title' => $this->l10n->t('Administration'),
'page' => $this->l10n->t('Block A New Server Domain Pattern'),
'syntax' => $this->l10n->t('<p>The server domain pattern syntax is case-insensitive shell wildcard, comprising the following special characters:</p>
<ul>
<li><code>*</code>: Any number of characters</li>
<li><code>?</code>: Any single character</li>
</ul>'),
'submit' => DI::l10n()->t('Check pattern'),
'matching_servers' => DI::l10n()->t('Matching known servers'),
'server_name' => DI::l10n()->t('Server Name'),
'server_domain' => DI::l10n()->t('Server Domain'),
'known_contacts' => DI::l10n()->t('Known Contacts'),
'server_count' => DI::l10n()->tt('%d known server', '%d known servers', count($gservers)),
'add_pattern' => DI::l10n()->t('Add pattern to the blocklist'),
'submit' => $this->l10n->t('Check pattern'),
'matching_servers' => $this->l10n->t('Matching known servers'),
'server_name' => $this->l10n->t('Server Name'),
'server_domain' => $this->l10n->t('Server Domain'),
'known_contacts' => $this->l10n->t('Known Contacts'),
'server_count' => $this->l10n->tt('%d known server', '%d known servers', count($gservers)),
'add_pattern' => $this->l10n->t('Add pattern to the blocklist'),
],
'$newdomain' => ['pattern', DI::l10n()->t('Server Domain Pattern'), $pattern, DI::l10n()->t('The domain pattern of the new server to add to the blocklist. Do not include the protocol.'), DI::l10n()->t('Required'), '', ''],
'$newpurge' => ['purge', DI::l10n()->t('Purge server'), $_REQUEST['purge'] ?? false, DI::l10n()->tt('Also purges all the locally stored content authored by the known contacts registered on that server. Keeps the contacts and the server records. This action cannot be undone.', 'Also purges all the locally stored content authored by the known contacts registered on these servers. Keeps the contacts and the servers records. This action cannot be undone.', count($gservers))],
'$newreason' => ['reason', DI::l10n()->t('Block reason'), $_REQUEST['reason'] ?? '', DI::l10n()->t('The reason why you blocked this server domain pattern. This reason will be shown publicly in the server information page.'), DI::l10n()->t('Required'), '', ''],
'$newdomain' => ['pattern', $this->l10n->t('Server Domain Pattern'), $pattern, $this->l10n->t('The domain pattern of the new server to add to the blocklist. Do not include the protocol.'), $this->l10n->t('Required'), '', ''],
'$newpurge' => ['purge', $this->l10n->t('Purge server'), $request['purge'] ?? false, $this->l10n->tt('Also purges all the locally stored content authored by the known contacts registered on that server. Keeps the contacts and the server records. This action cannot be undone.', 'Also purges all the locally stored content authored by the known contacts registered on these servers. Keeps the contacts and the servers records. This action cannot be undone.', count($gservers))],
'$newreason' => ['reason', $this->l10n->t('Block reason'), $request['reason'] ?? '', $this->l10n->t('The reason why you blocked this server domain pattern. This reason will be shown publicly in the server information page.'), $this->l10n->t('Required'), '', ''],
'$pattern' => $pattern,
'$gservers' => $gservers,
'$baseurl' => DI::baseUrl()->get(true),
'$baseurl' => $this->baseUrl->get(true),
'$form_security_token' => self::getFormSecurityToken('admin_blocklist_add')
]);
}

View file

@ -22,9 +22,9 @@
namespace Friendica\Module\Admin\Blocklist\Server;
use Friendica\App;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Moderation\DomainPatternBlocklist;
use Friendica\Module\Response;
use Friendica\Navigation\SystemMessages;
use Friendica\Util\Profiler;
@ -32,8 +32,8 @@ use Psr\Log\LoggerInterface;
class Import extends \Friendica\Module\BaseAdmin
{
/** @var IManageConfigValues */
private $config;
/** @var DomainPatternBlocklist */
private $localBlocklist;
/** @var SystemMessages */
private $sysmsg;
@ -41,11 +41,11 @@ class Import extends \Friendica\Module\BaseAdmin
/** @var array of blocked server domain patterns */
private $blocklist = [];
public function __construct(IManageConfigValues $config, SystemMessages $sysmsg, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
public function __construct(DomainPatternBlocklist $localBlocklist, SystemMessages $sysmsg, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
{
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->config = $config;
$this->localBlocklist = $localBlocklist;
$this->sysmsg = $sysmsg;
}
@ -62,63 +62,36 @@ class Import extends \Friendica\Module\BaseAdmin
{
self::checkAdminAccess();
if (!isset($_POST['page_blocklist_upload']) && !isset($_POST['page_blocklist_import'])) {
if (!isset($request['page_blocklist_upload']) && !isset($request['page_blocklist_import'])) {
return;
}
self::checkFormSecurityTokenRedirectOnError('/admin/blocklist/server/import', 'admin_blocklist_import');
if (isset($_POST['page_blocklist_upload'])) {
if (($fp = fopen($_FILES['listfile']['tmp_name'], 'r')) !== false) {
$blocklist = [];
while (($data = fgetcsv($fp, 1000, ',')) !== false) {
$domain = $data[0];
if (count($data) == 0) {
$reason = 'blocked';
} else {
$reason = $data[1];
}
$blocklist[] = [
'domain' => $domain,
'reason' => $reason
];
}
} else {
if (isset($request['page_blocklist_upload'])) {
try {
$this->blocklist = $this->localBlocklist::extractFromCSVFile($_FILES['listfile']['tmp_name']);
} catch (\Throwable $e) {
$this->sysmsg->addNotice($this->l10n->t('Error importing pattern file'));
return;
}
$this->blocklist = $blocklist;
return;
}
if (isset($_POST['page_blocklist_import'])) {
$blocklist = json_decode($_POST['blocklist'], true);
if (isset($request['page_blocklist_import'])) {
$blocklist = json_decode($request['blocklist'], true);
if ($blocklist === null) {
$this->sysmsg->addNotice($this->l10n->t('Error importing pattern file'));
return;
}
if (($_POST['mode'] ?? 'append') == 'replace') {
$this->config->set('system', 'blocklist', $blocklist);
if (($request['mode'] ?? 'append') == 'replace') {
$this->localBlocklist->set($blocklist);
$this->sysmsg->addNotice($this->l10n->t('Local blocklist replaced with the provided file.'));
} else {
$localBlocklist = $this->config->get('system', 'blocklist', []);
$localPatterns = array_column($localBlocklist, 'domain');
$importedPatterns = array_column($blocklist, 'domain');
$patternsToAppend = array_diff($importedPatterns, $localPatterns);
if (count($patternsToAppend)) {
foreach (array_keys($patternsToAppend) as $key) {
$localBlocklist[] = $blocklist[$key];
}
$this->config->set('system', 'blocklist', $localBlocklist);
$this->sysmsg->addNotice($this->l10n->tt('%d pattern was added to the local blocklist.', '%d patterns were added to the local blocklist.', count($patternsToAppend)));
$count = $this->localBlocklist->append($blocklist);
if ($count) {
$this->sysmsg->addNotice($this->l10n->tt('%d pattern was added to the local blocklist.', '%d patterns were added to the local blocklist.', $count));
} else {
$this->sysmsg->addNotice($this->l10n->t('No pattern was added to the local blocklist.'));
}

View file

@ -21,17 +21,33 @@
namespace Friendica\Module\Admin\Blocklist\Server;
use Friendica\App;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\DI;
use Friendica\Moderation\DomainPatternBlocklist;
use Friendica\Module\BaseAdmin;
use Friendica\Module\Response;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
class Index extends BaseAdmin
{
/** @var DomainPatternBlocklist */
private $blocklist;
public function __construct(DomainPatternBlocklist $blocklist, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
{
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->blocklist = $blocklist;
}
protected function post(array $request = [])
{
self::checkAdminAccess();
if (empty($_POST['page_blocklist_edit'])) {
if (empty($request['page_blocklist_edit'])) {
return;
}
@ -39,11 +55,11 @@ class Index extends BaseAdmin
// Edit the entries from blocklist
$blocklist = [];
foreach ($_POST['domain'] as $id => $domain) {
foreach ($request['domain'] as $id => $domain) {
// Trimming whitespaces as well as any lingering slashes
$domain = trim($domain);
$reason = trim($_POST['reason'][$id]);
if (empty($_POST['delete'][$id])) {
$reason = trim($request['reason'][$id]);
if (empty($request['delete'][$id])) {
$blocklist[] = [
'domain' => $domain,
'reason' => $reason
@ -51,54 +67,53 @@ class Index extends BaseAdmin
}
}
DI::config()->set('system', 'blocklist', $blocklist);
$this->blocklist->set($blocklist);
DI::baseUrl()->redirect('admin/blocklist/server');
$
$this->baseUrl->redirect('admin/blocklist/server');
}
protected function content(array $request = []): string
{
parent::content();
$blocklist = DI::config()->get('system', 'blocklist');
$blocklistform = [];
if (is_array($blocklist)) {
foreach ($blocklist as $id => $b) {
$blocklistform[] = [
'domain' => ["domain[$id]", DI::l10n()->t('Blocked server domain pattern'), $b['domain'], '', DI::l10n()->t('Required'), '', ''],
'reason' => ["reason[$id]", DI::l10n()->t("Reason for the block"), $b['reason'], '', DI::l10n()->t('Required'), '', ''],
'delete' => ["delete[$id]", DI::l10n()->t("Delete server domain pattern") . ' (' . $b['domain'] . ')', false, DI::l10n()->t("Check to delete this entry from the blocklist")]
];
}
foreach ($this->blocklist->get() as $id => $b) {
$blocklistform[] = [
'domain' => ["domain[$id]", $this->l10n->t('Blocked server domain pattern'), $b['domain'], '', $this->l10n->t('Required'), '', ''],
'reason' => ["reason[$id]", $this->l10n->t("Reason for the block"), $b['reason'], '', $this->l10n->t('Required'), '', ''],
'delete' => ["delete[$id]", $this->l10n->t("Delete server domain pattern") . ' (' . $b['domain'] . ')', false, $this->l10n->t("Check to delete this entry from the blocklist")]
];
}
$t = Renderer::getMarkupTemplate('admin/blocklist/server/index.tpl');
return Renderer::replaceMacros($t, [
'$l10n' => [
'title' => DI::l10n()->t('Administration'),
'page' => DI::l10n()->t('Server Domain Pattern Blocklist'),
'intro' => DI::l10n()->t('This page can be used to define a blocklist of server domain patterns from the federated network that are not allowed to interact with your node. For each domain pattern you should also provide the reason why you block it.'),
'public' => DI::l10n()->t('The list of blocked server domain patterns will be made publically available on the <a href="/friendica">/friendica</a> page so that your users and people investigating communication problems can find the reason easily.'),
'syntax' => DI::l10n()->t('<p>The server domain pattern syntax is case-insensitive shell wildcard, comprising the following special characters:</p>
'title' => $this->l10n->t('Administration'),
'page' => $this->l10n->t('Server Domain Pattern Blocklist'),
'intro' => $this->l10n->t('This page can be used to define a blocklist of server domain patterns from the federated network that are not allowed to interact with your node. For each domain pattern you should also provide the reason why you block it.'),
'public' => $this->l10n->t('The list of blocked server domain patterns will be made publically available on the <a href="/friendica">/friendica</a> page so that your users and people investigating communication problems can find the reason easily.'),
'syntax' => $this->l10n->t('<p>The server domain pattern syntax is case-insensitive shell wildcard, comprising the following special characters:</p>
<ul>
<li><code>*</code>: Any number of characters</li>
<li><code>?</code>: Any single character</li>
</ul>'),
'importtitle' => DI::l10n()->t('Import server domain pattern blocklist'),
'addtitle' => DI::l10n()->t('Add new entry to the blocklist'),
'importsubmit' => DI::l10n()->t('Upload file'),
'addsubmit' => DI::l10n()->t('Check pattern'),
'savechanges' => DI::l10n()->t('Save changes to the blocklist'),
'currenttitle' => DI::l10n()->t('Current Entries in the Blocklist'),
'thurl' => DI::l10n()->t('Blocked server domain pattern'),
'threason' => DI::l10n()->t('Reason for the block'),
'delentry' => DI::l10n()->t('Delete entry from the blocklist'),
'confirm_delete' => DI::l10n()->t('Delete entry from the blocklist?'),
'importtitle' => $this->l10n->t('Import server domain pattern blocklist'),
'addtitle' => $this->l10n->t('Add new entry to the blocklist'),
'importsubmit' => $this->l10n->t('Upload file'),
'addsubmit' => $this->l10n->t('Check pattern'),
'savechanges' => $this->l10n->t('Save changes to the blocklist'),
'currenttitle' => $this->l10n->t('Current Entries in the Blocklist'),
'thurl' => $this->l10n->t('Blocked server domain pattern'),
'threason' => $this->l10n->t('Reason for the block'),
'delentry' => $this->l10n->t('Delete entry from the blocklist'),
'confirm_delete' => $this->l10n->t('Delete entry from the blocklist?'),
],
'$listfile' => ['listfile', DI::l10n()->t('Server domain pattern blocklist CSV file'), '', '', DI::l10n()->t('Required'), '', 'file'],
'$newdomain' => ['pattern', DI::l10n()->t('Server Domain Pattern'), '', DI::l10n()->t('The domain pattern of the new server to add to the blocklist. Do not include the protocol.'), DI::l10n()->t('Required'), '', ''],
'$listfile' => ['listfile', $this->l10n->t('Server domain pattern blocklist CSV file'), '', '', $this->l10n->t('Required'), '', 'file'],
'$newdomain' => ['pattern', $this->l10n->t('Server Domain Pattern'), '', $this->l10n->t('The domain pattern of the new server to add to the blocklist. Do not include the protocol.'), $this->l10n->t('Required'), '', ''],
'$entries' => $blocklistform,
'$baseurl' => DI::baseUrl()->get(true),
'$baseurl' => $this->baseUrl->get(true),
'$form_security_token' => self::getFormSecurityToken('admin_blocklist'),
'$form_security_token_import' => self::getFormSecurityToken('admin_blocklist_import'),
]);