]> git.mxchange.org Git - friendica.git/commitdiff
Add new purge contacts option to admin server blocklist
authorHypolite Petovan <hypolite@mrpetovan.com>
Sat, 16 Oct 2021 23:18:11 +0000 (19:18 -0400)
committerHypolite Petovan <hypolite@mrpetovan.com>
Sat, 6 Nov 2021 05:36:53 +0000 (01:36 -0400)
- Move adding a server domain pattern to the blocklist in a separate module to allow reviewing the list of known servers that would be affected

src/Model/GServer.php
src/Module/Admin/Blocklist/Server.php [deleted file]
src/Module/Admin/Blocklist/Server/Add.php [new file with mode: 0644]
src/Module/Admin/Blocklist/Server/Index.php [new file with mode: 0644]
static/routes.config.php
view/templates/admin/blocklist/server.tpl [deleted file]
view/templates/admin/blocklist/server/add.tpl [new file with mode: 0644]
view/templates/admin/blocklist/server/index.tpl [new file with mode: 0644]

index c56e7701e0bbc225555a75a9c15485c3b8d0cf25..af03041498d56cdb2ecaa36bf9afc3e5ced9a880 100644 (file)
@@ -117,6 +117,33 @@ class GServer
                return self::getID($url, true);
        }
 
+       /**
+        * Retrieves all the servers which base domain are matching the provided domain pattern
+        *
+        * The pattern is a simple fnmatch() pattern with ? for single wildcard and * for multiple wildcard
+        *
+        * @param string $pattern
+        * @return array
+        * @throws Exception
+        */
+       public static function listByDomainPattern(string $pattern): array
+       {
+               $likePattern = 'http://' . strtr($pattern, ['_' => '\_', '%' => '\%', '?' => '_', '*' => '%']);
+
+               // The SUBSTRING_INDEX returns everything before the eventual third /, which effectively trims an
+               // eventual server path and keep only the server domain which we're matching against the pattern.
+               $sql = "SELECT `gserver`.*, COUNT(*) AS `contacts`
+                       FROM `gserver`
+                       LEFT JOIN `contact` ON `gserver`.`id` = `contact`.`gsid`
+                       WHERE SUBSTRING_INDEX(`gserver`.`nurl`, '/', 3) LIKE ?
+                       AND NOT `gserver`.`failed`
+                       GROUP BY `gserver`.`id`";
+
+               $stmt = DI::dba()->p($sql, $likePattern);
+
+               return DI::dba()->toArray($stmt);
+       }
+
        /**
         * Checks if the given server is reachable
         *
diff --git a/src/Module/Admin/Blocklist/Server.php b/src/Module/Admin/Blocklist/Server.php
deleted file mode 100644 (file)
index 0bd1953..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Module\Admin\Blocklist;
-
-use Friendica\Core\Renderer;
-use Friendica\DI;
-use Friendica\Module\BaseAdmin;
-use Friendica\Util\Strings;
-
-class Server extends BaseAdmin
-{
-       public static function post(array $parameters = [])
-       {
-               self::checkAdminAccess();
-
-               if (empty($_POST['page_blocklist_save']) && empty($_POST['page_blocklist_edit'])) {
-                       return;
-               }
-
-               self::checkFormSecurityTokenRedirectOnError('/admin/blocklist/server', 'admin_blocklist');
-
-               if (!empty($_POST['page_blocklist_save'])) {
-                       //  Add new item to blocklist
-                       $domain = trim($_POST['newentry_domain']);
-
-                       $blocklist = DI::config()->get('system', 'blocklist');
-                       $blocklist[] = [
-                               'domain' => $domain,
-                               'reason' => trim($_POST['newentry_reason']),
-                       ];
-                       DI::config()->set('system', 'blocklist', $blocklist);
-
-                       info(DI::l10n()->t('Server domain pattern added to blocklist.'));
-               } else {
-                       // Edit the entries from blocklist
-                       $blocklist = [];
-                       foreach ($_POST['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])) {
-                                       $blocklist[] = [
-                                               'domain' => $domain,
-                                               'reason' => $reason
-                                       ];
-                               }
-                       }
-                       DI::config()->set('system', 'blocklist', $blocklist);
-               }
-
-               DI::baseUrl()->redirect('admin/blocklist/server');
-       }
-
-       public static function content(array $parameters = [])
-       {
-               parent::content($parameters);
-
-               $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")]
-                               ];
-                       }
-               }
-
-               $t = Renderer::getMarkupTemplate('admin/blocklist/server.tpl');
-               return Renderer::replaceMacros($t, [
-                       '$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>
-<ul>
-       <li><code>*</code>: Any number of characters</li>
-       <li><code>?</code>: Any single character</li>
-       <li><code>[&lt;char1&gt;&lt;char2&gt;...]</code>: char1 or char2</li>
-</ul>'),
-                       '$addtitle' => DI::l10n()->t('Add new entry to block list'),
-                       '$newdomain' => ['newentry_domain', DI::l10n()->t('Server Domain Pattern'), '', DI::l10n()->t('The domain pattern of the new server to add to the block list. Do not include the protocol.'), DI::l10n()->t('Required'), '', ''],
-                       '$newreason' => ['newentry_reason', DI::l10n()->t('Block 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'), '', ''],
-                       '$submit' => DI::l10n()->t('Add Entry'),
-                       '$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 blocklist'),
-                       '$entries' => $blocklistform,
-                       '$baseurl' => DI::baseUrl()->get(true),
-                       '$confirm_delete' => DI::l10n()->t('Delete entry from blocklist?'),
-                       '$form_security_token' => self::getFormSecurityToken("admin_blocklist")
-               ]);
-       }
-}
diff --git a/src/Module/Admin/Blocklist/Server/Add.php b/src/Module/Admin/Blocklist/Server/Add.php
new file mode 100644 (file)
index 0000000..03f1026
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Module\Admin\Blocklist\Server;
+
+use Friendica\Content\ContactSelector;
+use Friendica\Core\Renderer;
+use Friendica\Core\Worker;
+use Friendica\DI;
+use Friendica\Model\Contact;
+use Friendica\Model\GServer;
+use Friendica\Module\BaseAdmin;
+use GuzzleHttp\Psr7\Uri;
+
+class Add extends BaseAdmin
+{
+       public static function post(array $parameters = [])
+       {
+               self::checkAdminAccess();
+
+               if (empty($_POST['page_blocklist_add'])) {
+                       return;
+               }
+
+               self::checkFormSecurityTokenRedirectOnError('/admin/blocklist/server/add', 'admin_blocklist_add');
+
+               //  Add new item to blocklist
+               $domain = trim($_POST['pattern']);
+
+               $blocklist   = DI::config()->get('system', 'blocklist');
+               $blocklist[] = [
+                       'domain' => $domain,
+                       'reason' => trim($_POST['reason']),
+               ];
+               DI::config()->set('system', 'blocklist', $blocklist);
+
+               info(DI::l10n()->t('Server domain pattern added to the blocklist.'));
+
+               if (!empty($_POST['purge'])) {
+                       $gservers = GServer::listByDomainPattern($domain);
+                       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)));
+               }
+
+               DI::baseUrl()->redirect('admin/blocklist/server');
+       }
+
+       public static function content(array $parameters = [])
+       {
+               parent::content($parameters);
+
+               $gservers = [];
+
+               if ($pattern = trim($_REQUEST['pattern'] ?? '')) {
+                       $gservers = GServer::listByDomainPattern($pattern);
+               }
+
+               array_walk($gservers, function (array &$gserver) {
+                       $gserver['domain'] = (new Uri($gserver['url']))->getHost();
+                       $gserver['network_icon'] = ContactSelector::networkToIcon($gserver['network']);
+                       $gserver['network_name'] = ContactSelector::networkToName($gserver['network']);
+               });
+
+               $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>
+<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'),
+                       ],
+                       '$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'), '', ''],
+                       '$pattern'             => $pattern,
+                       '$gservers'            => $gservers,
+                       '$baseurl'             => DI::baseUrl()->get(true),
+                       '$form_security_token' => self::getFormSecurityToken('admin_blocklist_add')
+               ]);
+       }
+}
diff --git a/src/Module/Admin/Blocklist/Server/Index.php b/src/Module/Admin/Blocklist/Server/Index.php
new file mode 100644 (file)
index 0000000..7dd5967
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license   GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Module\Admin\Blocklist\Server;
+
+use Friendica\Core\Renderer;
+use Friendica\DI;
+use Friendica\Module\BaseAdmin;
+
+class Index extends BaseAdmin
+{
+       public static function post(array $parameters = [])
+       {
+               self::checkAdminAccess();
+
+               if (empty($_POST['page_blocklist_edit'])) {
+                       return;
+               }
+
+               self::checkFormSecurityTokenRedirectOnError('/admin/blocklist/server', 'admin_blocklist');
+
+               // Edit the entries from blocklist
+               $blocklist = [];
+               foreach ($_POST['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])) {
+                               $blocklist[] = [
+                                       'domain' => $domain,
+                                       'reason' => $reason
+                               ];
+                       }
+               }
+
+               DI::config()->set('system', 'blocklist', $blocklist);
+
+               DI::baseUrl()->redirect('admin/blocklist/server');
+       }
+
+       public static function content(array $parameters = [])
+       {
+               parent::content($parameters);
+
+               $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")]
+                               ];
+                       }
+               }
+
+               $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>
+<ul>
+       <li><code>*</code>: Any number of characters</li>
+       <li><code>?</code>: Any single character</li>
+</ul>'),
+                               'addtitle'       => DI::l10n()->t('Add new entry to the blocklist'),
+                               'submit'         => 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?'),
+                       ],
+                       '$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'), '', ''],
+                       '$entries'             => $blocklistform,
+                       '$baseurl'             => DI::baseUrl()->get(true),
+                       '$form_security_token' => self::getFormSecurityToken('admin_blocklist')
+               ]);
+       }
+}
index 24fa016179fe45a269012c8037e377c85481c496..d1f11567a2a2932c91208cc11318b8345505f746 100644 (file)
@@ -180,8 +180,9 @@ return [
                '/addons/{addon}' => [Module\Admin\Addons\Details::class, [R::GET, R::POST]],
 
 
-               '/blocklist/contact' => [Module\Admin\Blocklist\Contact::class, [R::GET, R::POST]],
-               '/blocklist/server'  => [Module\Admin\Blocklist\Server::class,  [R::GET, R::POST]],
+               '/blocklist/contact'    => [Module\Admin\Blocklist\Contact::class,      [R::GET, R::POST]],
+               '/blocklist/server'     => [Module\Admin\Blocklist\Server\Index::class, [R::GET, R::POST]],
+               '/blocklist/server/add' => [Module\Admin\Blocklist\Server\Add::class,   [R::GET, R::POST]],
 
                '/dbsync[/{action}[/{update:\d+}]]' => [Module\Admin\DBSync::class, [R::GET]],
 
diff --git a/view/templates/admin/blocklist/server.tpl b/view/templates/admin/blocklist/server.tpl
deleted file mode 100644 (file)
index 43d006e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-<script>
-       function confirm_delete(uname){
-               return confirm("{{$confirm_delete}}".format(uname));
-       }
-</script>
-<div id="adminpage">
-       <h1>{{$title}} - {{$page}}</h1>
-       <p>{{$intro}}</p>
-       <p>{{$public nofilter}}</p>
-       {{$syntax nofilter}}
-
-       <h2>{{$addtitle}}</h2>
-       <form action="{{$baseurl}}/admin/blocklist/server" method="post">
-               <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
-               {{include file="field_input.tpl" field=$newdomain}}
-               {{include file="field_input.tpl" field=$newreason}}
-               <div class="submit">
-                       <button type="submit" class="btn btn-primary" name="page_blocklist_save" value="{{$submit}}">{{$submit}}</button>
-               </div>
-       </form>
-
-       {{if $entries}}
-       <h2>{{$currenttitle}}</h2>
-       <p>{{$currentintro}}</p>
-       <form action="{{$baseurl}}/admin/blocklist/server" method="post">
-               <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
-               {{foreach $entries as $e}}
-                       {{include file="field_input.tpl" field=$e.domain}}
-                       {{include file="field_input.tpl" field=$e.reason}}
-                       {{include file="field_checkbox.tpl" field=$e.delete}}
-               {{/foreach}}
-               <div class="submit">
-                       <button type="submit" class="btn btn-primary" name="page_blocklist_edit" value="{{$savechanges}}">{{$savechanges}}</button>
-               </div>
-               {{/if}}
-       </form>
-</div>
diff --git a/view/templates/admin/blocklist/server/add.tpl b/view/templates/admin/blocklist/server/add.tpl
new file mode 100644 (file)
index 0000000..999965d
--- /dev/null
@@ -0,0 +1,56 @@
+<div id="adminpage">
+       <p><a href="{{$baseurl}}/admin/blocklist/server">{{$l10n.return_list}}</a></p>
+       <h1>{{$l10n.title}} - {{$l10n.page}}</h1>
+       {{$l10n.syntax nofilter}}
+
+       <form action="{{$baseurl}}/admin/blocklist/server/add" method="get">
+               {{include file="field_input.tpl" field=$newdomain}}
+               <div class="submit">
+                       <button type="submit" class="btn btn-primary">{{$l10n.submit}}</button>
+               </div>
+       </form>
+{{if $pattern}}
+       <h2>{{$l10n.matching_servers}}</h2>
+       <form action="{{$baseurl}}/admin/blocklist/server/add" method="post">
+               <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
+        <input type="hidden" name="pattern" value="{{$pattern}}">
+               <table class="table table-condensed table-striped table-bordered">
+                       <thead>
+                               <tr>
+                                       <th></th>
+                                       <th>{{$l10n.server_name}}</th>
+                                       <th>{{$l10n.server_domain}}</th>
+                                       <th>{{$l10n.known_contacts}}</th>
+                               </tr>
+                       </thead>
+                       <tfoot>
+                               <tr>
+                                       <td colspan="4">{{$l10n.server_count}}</td>
+                               </tr>
+                       </tfoot>
+                       <tbody>
+            {{foreach $gservers as $gserver}}
+                               <tr>
+                                       <td class="text-center">
+                                               <span class="network-label icon" alt="{{$gserver.network_name}}" title="{{$gserver.network_name}}">
+                                                       <i class="fa fa-{{$gserver.network_icon}}"></i>
+                                               </span>
+                                       </td>
+                                       <th>{{$gserver.site_name|default:$gserver.domain}}</th>
+                                       <td>
+                                               <a href="{{$gserver.url}}" target="_blank" rel="noreferrer noopener">{{$gserver.domain}} <i class="fa fa-external-link"></i></a>
+                                       </td>
+                                       <td class="text-right">{{$gserver.contacts}} <i class="fa fa-user"></i></td>
+                               </tr>
+            {{/foreach}}
+                       </tbody>
+               </table>
+
+               {{include file="field_checkbox.tpl" field=$newpurge}}
+               {{include file="field_input.tpl" field=$newreason}}
+               <div class="submit">
+                       <button type="submit" class="btn btn-primary" name="page_blocklist_add" value="{{$l10n.add_pattern}}">{{$l10n.add_pattern}}</button>
+               </div>
+       </form>
+{{/if}}
+</div>
diff --git a/view/templates/admin/blocklist/server/index.tpl b/view/templates/admin/blocklist/server/index.tpl
new file mode 100644 (file)
index 0000000..00df4da
--- /dev/null
@@ -0,0 +1,34 @@
+<script>
+       function confirm_delete(uname){
+               return confirm("{{$l10n.confirm_delete}}".format(uname));
+       }
+</script>
+<div id="adminpage">
+       <h1>{{$l10n.title}} - {{$l10n.page}}</h1>
+       <p>{{$l10n.intro}}</p>
+       <p>{{$l10n.public nofilter}}</p>
+       {{$l10n.syntax nofilter}}
+
+       <h2>{{$l10n.addtitle}}</h2>
+       <form action="{{$baseurl}}/admin/blocklist/server/add" method="get">
+               {{include file="field_input.tpl" field=$newdomain}}
+               <div class="submit">
+                       <button type="submit" class="btn btn-primary">{{$l10n.submit}}</button>
+               </div>
+       </form>
+
+       {{if $entries}}
+       <h2>{{$l10n.currenttitle}}</h2>
+       <form action="{{$baseurl}}/admin/blocklist/server" method="post">
+               <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
+               {{foreach $entries as $e}}
+                       {{include file="field_input.tpl" field=$e.domain}}
+                       {{include file="field_input.tpl" field=$e.reason}}
+                       {{include file="field_checkbox.tpl" field=$e.delete}}
+               {{/foreach}}
+               <div class="submit">
+                       <button type="submit" class="btn btn-primary" name="page_blocklist_edit" value="{{$l10n.savechanges}}">{{$l10n.savechanges}}</button>
+               </div>
+               {{/if}}
+       </form>
+</div>