From 4b695e361c15377893f4434532ebff3eb6d97388 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 7 Mar 2024 06:03:15 +0000 Subject: [PATCH] Automatically close the registration when the admin is inactive --- src/Content/Nav.php | 2 +- src/Module/Api/GNUSocial/GNUSocial/Config.php | 2 +- src/Module/Api/Mastodon/InstanceV2.php | 6 ++-- src/Module/Bookmarklet.php | 2 +- src/Module/Friendica.php | 3 +- src/Module/Home.php | 2 +- src/Module/Invite.php | 4 +-- src/Module/NodeInfo110.php | 3 +- src/Module/NodeInfo120.php | 3 +- src/Module/NodeInfo210.php | 3 +- src/Module/Notifications/Ping.php | 3 +- src/Module/Register.php | 28 +++++++++++++++---- src/Module/Security/Login.php | 4 +-- src/Module/Security/OpenID.php | 2 +- src/Module/Statistics.php | 3 +- src/Module/User/Import.php | 4 +-- src/Object/Api/Mastodon/Instance.php | 6 ++-- static/defaults.config.php | 4 +++ 18 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/Content/Nav.php b/src/Content/Nav.php index a8f568630f..001f9fb70e 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -251,7 +251,7 @@ class Nav $nav['home'] = [$homelink, $this->l10n->t('Home'), '', $this->l10n->t('Home Page')]; } - if (intval($this->config->get('config', 'register_policy')) === \Friendica\Module\Register::OPEN && !$this->session->isAuthenticated()) { + if (\Friendica\Module\Register::getPolicy() === \Friendica\Module\Register::OPEN && !$this->session->isAuthenticated()) { $nav['register'] = ['register', $this->l10n->t('Register'), '', $this->l10n->t('Create an account')]; } diff --git a/src/Module/Api/GNUSocial/GNUSocial/Config.php b/src/Module/Api/GNUSocial/GNUSocial/Config.php index 4ea5119e17..01135f93a9 100644 --- a/src/Module/Api/GNUSocial/GNUSocial/Config.php +++ b/src/Module/Api/GNUSocial/GNUSocial/Config.php @@ -47,7 +47,7 @@ class Config extends BaseApi 'broughtby' => '', 'broughtbyurl' => '', 'timezone' => DI::config()->get('system', 'default_timezone'), - 'closed' => (DI::config()->get('config', 'register_policy') == Register::CLOSED), + 'closed' => Register::getPolicy() === Register::CLOSED, 'inviteonly' => (bool)DI::config()->get('system', 'invitation_only'), 'private' => (bool)DI::config()->get('system', 'block_public'), 'textlimit' => (string) DI::config()->get('config', 'api_import_size', DI::config()->get('config', 'max_import_size')), diff --git a/src/Module/Api/Mastodon/InstanceV2.php b/src/Module/Api/Mastodon/InstanceV2.php index a3d268311e..137a2d31c2 100644 --- a/src/Module/Api/Mastodon/InstanceV2.php +++ b/src/Module/Api/Mastodon/InstanceV2.php @@ -166,9 +166,9 @@ class InstanceV2 extends BaseApi private function buildRegistrationsInfo(): InstanceEntity\Registrations { - $register_policy = intval($this->config->get('config', 'register_policy')); - $enabled = ($register_policy != Register::CLOSED); - $approval_required = ($register_policy == Register::APPROVE); + $register_policy = Register::getPolicy(); + $enabled = $register_policy !== Register::CLOSED; + $approval_required = $register_policy === Register::APPROVE; return new InstanceEntity\Registrations($enabled, $approval_required); } diff --git a/src/Module/Bookmarklet.php b/src/Module/Bookmarklet.php index ebcd150be1..ebcbc850e0 100644 --- a/src/Module/Bookmarklet.php +++ b/src/Module/Bookmarklet.php @@ -42,7 +42,7 @@ class Bookmarklet extends BaseModule if (!DI::userSession()->getLocalUserId()) { $output = '

' . DI::l10n()->t('Login') . '

'; - $output .= Login::form(DI::args()->getQueryString(), intval($config->get('config', 'register_policy')) === Register::CLOSED ? false : true); + $output .= Login::form(DI::args()->getQueryString(), Register::getPolicy() !== Register::CLOSED); return $output; } diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 79906f937a..1ff4ffa8cb 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -30,7 +30,6 @@ use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; use Friendica\Database\PostUpdate; use Friendica\Model\User; use Friendica\Network\HTTPException; @@ -154,7 +153,7 @@ class Friendica extends BaseModule Register::OPEN => 'REGISTER_OPEN' ]; - $register_policy_int = $this->config->get('config', 'register_policy'); + $register_policy_int = Register::getPolicy(); if ($register_policy_int !== Register::CLOSED && $this->config->get('config', 'invitation_only')) { $register_policy = 'REGISTER_INVITATION'; } else { diff --git a/src/Module/Home.php b/src/Module/Home.php index c202fbfcd9..9d4f885b22 100644 --- a/src/Module/Home.php +++ b/src/Module/Home.php @@ -73,7 +73,7 @@ class Home extends BaseModule } } - $login = Login::form(DI::args()->getQueryString(), $config->get('config', 'register_policy') === Register::CLOSED ? 0 : 1); + $login = Login::form(DI::args()->getQueryString(), Register::getPolicy() !== Register::CLOSED); $content = ''; Hook::callAll('home_content', $content); diff --git a/src/Module/Invite.php b/src/Module/Invite.php index 1f750f459f..8e0cff268e 100644 --- a/src/Module/Invite.php +++ b/src/Module/Invite.php @@ -146,14 +146,14 @@ class Invite extends BaseModule $dirLocation = Search::getGlobalDirectory(); if (strlen($dirLocation)) { - if ($config->get('config', 'register_policy') === Register::CLOSED) { + if (Register::getPolicy() === Register::CLOSED) { $linkTxt = DI::l10n()->t('Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks.', $dirLocation . '/servers'); } else { $linkTxt = DI::l10n()->t('To accept this invitation, please visit and register at %s or any other public Friendica website.', DI::baseUrl() . '/register') . "\r\n" . "\r\n" . DI::l10n()->t('Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join.', $dirLocation . '/servers'); } } else { // there is no global directory URL defined - if ($config->get('config', 'register_policy') === Register::CLOSED) { + if (Register::getPolicy() === Register::CLOSED) { return DI::l10n()->t('Our apologies. This system is not currently configured to connect with other public sites or invite members.'); } else { $linkTxt = DI::l10n()->t('To accept this invitation, please visit and register at %s.', DI::baseUrl() . '/register' diff --git a/src/Module/NodeInfo110.php b/src/Module/NodeInfo110.php index cefe231205..9682ece260 100644 --- a/src/Module/NodeInfo110.php +++ b/src/Module/NodeInfo110.php @@ -24,7 +24,6 @@ namespace Friendica\Module; use Friendica\App; use Friendica\BaseModule; use Friendica\Capabilities\ICanCreateResponses; -use Friendica\Core\Addon; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; use Friendica\Model\Nodeinfo; @@ -65,7 +64,7 @@ class NodeInfo110 extends BaseModule ], 'services' => Nodeinfo::getServices(), 'usage' => Nodeinfo::getUsage(), - 'openRegistrations' => intval($this->config->get('config', 'register_policy')) !== Register::CLOSED, + 'openRegistrations' => Register::getPolicy() !== Register::CLOSED, 'metadata' => [ 'nodeName' => $this->config->get('config', 'sitename'), ], diff --git a/src/Module/NodeInfo120.php b/src/Module/NodeInfo120.php index b956faf971..efd6943f7d 100644 --- a/src/Module/NodeInfo120.php +++ b/src/Module/NodeInfo120.php @@ -24,7 +24,6 @@ namespace Friendica\Module; use Friendica\App; use Friendica\BaseModule; use Friendica\Capabilities\ICanCreateResponses; -use Friendica\Core\Addon; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; use Friendica\Model\Nodeinfo; @@ -58,7 +57,7 @@ class NodeInfo120 extends BaseModule 'protocols' => ['dfrn', 'activitypub'], 'services' => Nodeinfo::getServices(), 'usage' => Nodeinfo::getUsage(), - 'openRegistrations' => intval($this->config->get('config', 'register_policy')) !== Register::CLOSED, + 'openRegistrations' => Register::getPolicy() !== Register::CLOSED, 'metadata' => [ 'nodeName' => $this->config->get('config', 'sitename'), ], diff --git a/src/Module/NodeInfo210.php b/src/Module/NodeInfo210.php index 19e6cf1c9e..ff22adf398 100644 --- a/src/Module/NodeInfo210.php +++ b/src/Module/NodeInfo210.php @@ -24,7 +24,6 @@ namespace Friendica\Module; use Friendica\App; use Friendica\BaseModule; use Friendica\Capabilities\ICanCreateResponses; -use Friendica\Core\Addon; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; use Friendica\Model\Nodeinfo; @@ -59,7 +58,7 @@ class NodeInfo210 extends BaseModule 'organization' => Nodeinfo::getOrganization($this->config), 'protocols' => ['dfrn', 'activitypub'], 'services' => Nodeinfo::getServices(), - 'openRegistrations' => intval($this->config->get('config', 'register_policy')) !== Register::CLOSED, + 'openRegistrations' => Register::getPolicy() !== Register::CLOSED, 'usage' => Nodeinfo::getUsage(true), ]; diff --git a/src/Module/Notifications/Ping.php b/src/Module/Notifications/Ping.php index dd68961373..c16e5064f8 100644 --- a/src/Module/Notifications/Ping.php +++ b/src/Module/Notifications/Ping.php @@ -32,7 +32,6 @@ use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\Model\Circle; @@ -175,7 +174,7 @@ class Ping extends BaseModule $myurl = $this->session->getMyUrl(); $mail_count = $this->database->count('mail', ["`uid` = ? AND NOT `seen` AND `from-url` != ?", $this->session->getLocalUserId(), $myurl]); - if (intval($this->config->get('config', 'register_policy')) === Register::APPROVE && $this->session->isSiteAdmin()) { + if (Register::getPolicy() === Register::APPROVE && $this->session->isSiteAdmin()) { $registrations = \Friendica\Model\Register::getPending(); $register_count = count($registrations); } diff --git a/src/Module/Register.php b/src/Module/Register.php index b47c20e6a0..0b488f6cc6 100644 --- a/src/Module/Register.php +++ b/src/Module/Register.php @@ -34,6 +34,7 @@ use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model; use Friendica\Model\User; +use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; use Friendica\Util\Proxy; use Psr\Log\LoggerInterface; @@ -86,7 +87,7 @@ class Register extends BaseModule } } - if (!DI::userSession()->getLocalUserId() && (intval(DI::config()->get('config', 'register_policy')) === self::CLOSED)) { + if (!DI::userSession()->getLocalUserId() && self::getPolicy() === self::CLOSED) { DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.')); return ''; } @@ -144,7 +145,7 @@ class Register extends BaseModule $o = Renderer::replaceMacros($tpl, [ '$invitations' => DI::config()->get('system', 'invitation_only'), - '$permonly' => intval(DI::config()->get('config', 'register_policy')) === self::APPROVE, + '$permonly' => self::getPolicy() === self::APPROVE, '$permonlybox' => ['permonlybox', DI::l10n()->t('Note for the admin'), '', DI::l10n()->t('Leave a message for the admin, why you want to join this node'), DI::l10n()->t('Required')], '$invite_desc' => DI::l10n()->t('Membership on this site is by invitation only.'), '$invite_label' => DI::l10n()->t('Your invitation code: '), @@ -228,7 +229,7 @@ class Register extends BaseModule } } - switch (DI::config()->get('config', 'register_policy')) { + switch (self::getPolicy()) { case self::OPEN: $blocked = 0; $verified = 1; @@ -312,7 +313,7 @@ class Register extends BaseModule $base_url = (string)DI::baseUrl(); - if ($netpublish && intval(DI::config()->get('config', 'register_policy')) !== self::APPROVE) { + if ($netpublish && self::getPolicy() !== self::APPROVE) { $url = $base_url . '/profile/' . $user['nickname']; Worker::add(Worker::PRIORITY_LOW, 'Directory', $url); } @@ -327,7 +328,7 @@ class Register extends BaseModule $num_invites = DI::config()->get('system', 'number_invites'); $invite_id = (!empty($_POST['invite_id']) ? trim($_POST['invite_id']) : ''); - if (intval(DI::config()->get('config', 'register_policy')) === self::OPEN) { + if (self::getPolicy() === self::OPEN) { if ($using_invites && $invite_id) { Model\Register::deleteByHash($invite_id); DI::pConfig()->set($user['uid'], 'system', 'invites_remaining', $num_invites); @@ -363,7 +364,7 @@ class Register extends BaseModule } DI::baseUrl()->redirect(); } - } elseif (intval(DI::config()->get('config', 'register_policy')) === self::APPROVE) { + } elseif (self::getPolicy() === self::APPROVE) { if (!User::getAdminEmailList()) { $this->logger->critical('Registration policy is set to APPROVE but no admin email address has been set in config.admin_email'); DI::sysmsg()->addNotice(DI::l10n()->t('Your registration can not be processed.')); @@ -426,4 +427,19 @@ class Register extends BaseModule ]); } } + public static function getPolicy(): int + { + $days = DI::config()->get('system', 'admin_inactivity_limit'); + if ($days == 0) { + return intval(DI::config()->get('config', 'register_policy')); + } + + $inactive_since = DateTimeFormat::utc('now - ' . $days . ' day'); + foreach (User::getAdminList(['login_date']) as $admin) { + if (strtotime($admin['login_date']) > strtotime($inactive_since)) { + return intval(DI::config()->get('config', 'register_policy')); + } + } + return self::CLOSED; + } } diff --git a/src/Module/Security/Login.php b/src/Module/Security/Login.php index 3f89a56fdd..b73ffd41d3 100644 --- a/src/Module/Security/Login.php +++ b/src/Module/Security/Login.php @@ -66,7 +66,7 @@ class Login extends BaseModule $this->baseUrl->redirect($return_path); } - return self::form($return_path, intval($this->config->get('config', 'register_policy')) !== \Friendica\Module\Register::CLOSED); + return self::form($return_path, \Friendica\Module\Register::getPolicy() !== \Friendica\Module\Register::CLOSED); } protected function post(array $request = []) @@ -118,7 +118,7 @@ class Login extends BaseModule } $reg = false; - if ($register && intval(DI::config()->get('config', 'register_policy')) !== Register::CLOSED) { + if ($register && Register::getPolicy() !== Register::CLOSED) { $reg = [ 'title' => DI::l10n()->t('Create a New Account'), 'desc' => DI::l10n()->t('Register'), diff --git a/src/Module/Security/OpenID.php b/src/Module/Security/OpenID.php index c76b1b109b..89ed9ae34e 100644 --- a/src/Module/Security/OpenID.php +++ b/src/Module/Security/OpenID.php @@ -86,7 +86,7 @@ class OpenID extends BaseModule $open_id_obj->identity = $authId; $session->set('openid_server', $open_id_obj->discover($open_id_obj->identity)); - if (intval(DI::config()->get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED) { + if (\Friendica\Module\Register::getPolicy() === \Friendica\Module\Register::CLOSED) { DI::sysmsg()->addNotice($l10n->t('Account not found. Please login to your existing account to add the OpenID to it.')); } else { DI::sysmsg()->addNotice($l10n->t('Account not found. Please register a new account or login to your existing account to add the OpenID to it.')); diff --git a/src/Module/Statistics.php b/src/Module/Statistics.php index a3f8a08c30..2ce2e53de5 100644 --- a/src/Module/Statistics.php +++ b/src/Module/Statistics.php @@ -27,7 +27,6 @@ use Friendica\Core\Addon; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs; use Friendica\Core\L10n; -use Friendica\Core\System; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; @@ -53,7 +52,7 @@ class Statistics extends BaseModule protected function rawContent(array $request = []) { $registration_open = - intval($this->config->get('config', 'register_policy')) !== Register::CLOSED + Register::getPolicy() !== Register::CLOSED && !$this->config->get('config', 'invitation_only'); /// @todo mark the "service" addons and load them dynamically here diff --git a/src/Module/User/Import.php b/src/Module/User/Import.php index 4d03e3996d..d6c54a08ae 100644 --- a/src/Module/User/Import.php +++ b/src/Module/User/Import.php @@ -80,7 +80,7 @@ class Import extends \Friendica\BaseModule protected function post(array $request = []) { - if ($this->config->get('config', 'register_policy') != \Friendica\Module\Register::OPEN && !$this->app->isSiteAdmin()) { + if (\Friendica\Module\Register::getPolicy() !== \Friendica\Module\Register::OPEN && !$this->app->isSiteAdmin()) { throw new HttpException\ForbiddenException($this->t('Permission denied.')); } @@ -99,7 +99,7 @@ class Import extends \Friendica\BaseModule protected function content(array $request = []): string { - if (($this->config->get('config', 'register_policy') != \Friendica\Module\Register::OPEN) && !$this->app->isSiteAdmin()) { + if ((\Friendica\Module\Register::getPolicy() !== \Friendica\Module\Register::OPEN) && !$this->app->isSiteAdmin()) { $this->systemMessages->addNotice($this->t('User imports on closed servers can only be done by an administrator.')); } diff --git a/src/Object/Api/Mastodon/Instance.php b/src/Object/Api/Mastodon/Instance.php index ea740791f6..02053aad01 100644 --- a/src/Object/Api/Mastodon/Instance.php +++ b/src/Object/Api/Mastodon/Instance.php @@ -75,7 +75,7 @@ class Instance extends BaseDataTransferObject public function __construct(IManageConfigValues $config, BaseURL $baseUrl, Database $database, Configuration $configuration, ?Account $contact_account, array $rules) { - $register_policy = intval($config->get('config', 'register_policy')); + $register_policy = Register::getPolicy(); $this->uri = $baseUrl->getHost(); $this->title = $config->get('config', 'sitename'); @@ -87,8 +87,8 @@ class Instance extends BaseDataTransferObject $this->thumbnail = $baseUrl . (new Header($config))->getMastodonBannerPath(); $this->languages = [$config->get('system', 'language')]; $this->max_toot_chars = (int)$config->get('config', 'api_import_size', $config->get('config', 'max_import_size')); - $this->registrations = ($register_policy != Register::CLOSED); - $this->approval_required = ($register_policy == Register::APPROVE); + $this->registrations = ($register_policy !== Register::CLOSED); + $this->approval_required = ($register_policy === Register::APPROVE); $this->invites_enabled = false; $this->configuration = $configuration; $this->contact_account = $contact_account ?? []; diff --git a/static/defaults.config.php b/static/defaults.config.php index 431d5770d3..3988e753c2 100644 --- a/static/defaults.config.php +++ b/static/defaults.config.php @@ -97,6 +97,10 @@ return [ // Checks for missing entries in "post", "post-thread" or "post-thread-user" and creates them 'add_missing_posts' => false, + // admin_inactivity_limit (Integer) + // Days of inactivity after which an admin is considered inactive. "0" means that there will be no check for inactivity. + 'admin_inactivity_limit' => 30, + // allowed_link_protocols (Array) // Allowed protocols in links URLs, add at your own risk. http(s) is always allowed. 'allowed_link_protocols' => ['ftp://', 'ftps://', 'mailto:', 'cid:', 'gopher://'],