Merge pull request #12169 from MrPetovan/bug/7574-notifications-deleted-users
Centralize config.admin_email management in Model\User
This commit is contained in:
commit
8dfd560b52
|
@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS `user` (
|
||||||
`pwdreset` varchar(255) COMMENT 'Password reset request token',
|
`pwdreset` varchar(255) COMMENT 'Password reset request token',
|
||||||
`pwdreset_time` datetime COMMENT 'Timestamp of the last password reset request',
|
`pwdreset_time` datetime COMMENT 'Timestamp of the last password reset request',
|
||||||
`maxreq` int unsigned NOT NULL DEFAULT 10 COMMENT '',
|
`maxreq` int unsigned NOT NULL DEFAULT 10 COMMENT '',
|
||||||
`expire` int unsigned NOT NULL DEFAULT 0 COMMENT '',
|
`expire` int unsigned NOT NULL DEFAULT 0 COMMENT 'Delay in days before deleting user-related posts. Scope is controlled by pConfig.',
|
||||||
`account_removed` boolean NOT NULL DEFAULT '0' COMMENT 'if 1 the account is removed',
|
`account_removed` boolean NOT NULL DEFAULT '0' COMMENT 'if 1 the account is removed',
|
||||||
`account_expired` boolean NOT NULL DEFAULT '0' COMMENT '',
|
`account_expired` boolean NOT NULL DEFAULT '0' COMMENT '',
|
||||||
`account_expires_on` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'timestamp when account expires and will be deleted',
|
`account_expires_on` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'timestamp when account expires and will be deleted',
|
||||||
|
|
|
@ -6,53 +6,53 @@ The local users
|
||||||
Fields
|
Fields
|
||||||
------
|
------
|
||||||
|
|
||||||
| Field | Description | Type | Null | Key | Default | Extra |
|
| Field | Description | Type | Null | Key | Default | Extra |
|
||||||
| ------------------------ | --------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- |
|
| ------------------------ | --------------------------------------------------------------------------------- | ------------------ | ---- | --- | ------------------- | -------------- |
|
||||||
| uid | sequential ID | mediumint unsigned | NO | PRI | NULL | auto_increment |
|
| uid | sequential ID | mediumint unsigned | NO | PRI | NULL | auto_increment |
|
||||||
| parent-uid | The parent user that has full control about this user | mediumint unsigned | YES | | NULL | |
|
| parent-uid | The parent user that has full control about this user | mediumint unsigned | YES | | NULL | |
|
||||||
| guid | A unique identifier for this user | varchar(64) | NO | | | |
|
| guid | A unique identifier for this user | varchar(64) | NO | | | |
|
||||||
| username | Name that this user is known by | varchar(255) | NO | | | |
|
| username | Name that this user is known by | varchar(255) | NO | | | |
|
||||||
| password | encrypted password | varchar(255) | NO | | | |
|
| password | encrypted password | varchar(255) | NO | | | |
|
||||||
| legacy_password | Is the password hash double-hashed? | boolean | NO | | 0 | |
|
| legacy_password | Is the password hash double-hashed? | boolean | NO | | 0 | |
|
||||||
| nickname | nick- and user name | varchar(255) | NO | | | |
|
| nickname | nick- and user name | varchar(255) | NO | | | |
|
||||||
| email | the users email address | varchar(255) | NO | | | |
|
| email | the users email address | varchar(255) | NO | | | |
|
||||||
| openid | | varchar(255) | NO | | | |
|
| openid | | varchar(255) | NO | | | |
|
||||||
| timezone | PHP-legal timezone | varchar(128) | NO | | | |
|
| timezone | PHP-legal timezone | varchar(128) | NO | | | |
|
||||||
| language | default language | varchar(32) | NO | | en | |
|
| language | default language | varchar(32) | NO | | en | |
|
||||||
| register_date | timestamp of registration | datetime | NO | | 0001-01-01 00:00:00 | |
|
| register_date | timestamp of registration | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||||
| login_date | timestamp of last login | datetime | NO | | 0001-01-01 00:00:00 | |
|
| login_date | timestamp of last login | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||||
| default-location | Default for item.location | varchar(255) | NO | | | |
|
| default-location | Default for item.location | varchar(255) | NO | | | |
|
||||||
| allow_location | 1 allows to display the location | boolean | NO | | 0 | |
|
| allow_location | 1 allows to display the location | boolean | NO | | 0 | |
|
||||||
| theme | user theme preference | varchar(255) | NO | | | |
|
| theme | user theme preference | varchar(255) | NO | | | |
|
||||||
| pubkey | RSA public key 4096 bit | text | YES | | NULL | |
|
| pubkey | RSA public key 4096 bit | text | YES | | NULL | |
|
||||||
| prvkey | RSA private key 4096 bit | text | YES | | NULL | |
|
| prvkey | RSA private key 4096 bit | text | YES | | NULL | |
|
||||||
| spubkey | | text | YES | | NULL | |
|
| spubkey | | text | YES | | NULL | |
|
||||||
| sprvkey | | text | YES | | NULL | |
|
| sprvkey | | text | YES | | NULL | |
|
||||||
| verified | user is verified through email | boolean | NO | | 0 | |
|
| verified | user is verified through email | boolean | NO | | 0 | |
|
||||||
| blocked | 1 for user is blocked | boolean | NO | | 0 | |
|
| blocked | 1 for user is blocked | boolean | NO | | 0 | |
|
||||||
| blockwall | Prohibit contacts to post to the profile page of the user | boolean | NO | | 0 | |
|
| blockwall | Prohibit contacts to post to the profile page of the user | boolean | NO | | 0 | |
|
||||||
| hidewall | Hide profile details from unkown viewers | boolean | NO | | 0 | |
|
| hidewall | Hide profile details from unkown viewers | boolean | NO | | 0 | |
|
||||||
| blocktags | Prohibit contacts to tag the post of this user | boolean | NO | | 0 | |
|
| blocktags | Prohibit contacts to tag the post of this user | boolean | NO | | 0 | |
|
||||||
| unkmail | Permit unknown people to send private mails to this user | boolean | NO | | 0 | |
|
| unkmail | Permit unknown people to send private mails to this user | boolean | NO | | 0 | |
|
||||||
| cntunkmail | | int unsigned | NO | | 10 | |
|
| cntunkmail | | int unsigned | NO | | 10 | |
|
||||||
| notify-flags | email notification options | smallint unsigned | NO | | 65535 | |
|
| notify-flags | email notification options | smallint unsigned | NO | | 65535 | |
|
||||||
| page-flags | page/profile type | tinyint unsigned | NO | | 0 | |
|
| page-flags | page/profile type | tinyint unsigned | NO | | 0 | |
|
||||||
| account-type | | tinyint unsigned | NO | | 0 | |
|
| account-type | | tinyint unsigned | NO | | 0 | |
|
||||||
| prvnets | | boolean | NO | | 0 | |
|
| prvnets | | boolean | NO | | 0 | |
|
||||||
| pwdreset | Password reset request token | varchar(255) | YES | | NULL | |
|
| pwdreset | Password reset request token | varchar(255) | YES | | NULL | |
|
||||||
| pwdreset_time | Timestamp of the last password reset request | datetime | YES | | NULL | |
|
| pwdreset_time | Timestamp of the last password reset request | datetime | YES | | NULL | |
|
||||||
| maxreq | | int unsigned | NO | | 10 | |
|
| maxreq | | int unsigned | NO | | 10 | |
|
||||||
| expire | | int unsigned | NO | | 0 | |
|
| expire | Delay in days before deleting user-related posts. Scope is controlled by pConfig. | int unsigned | NO | | 0 | |
|
||||||
| account_removed | if 1 the account is removed | boolean | NO | | 0 | |
|
| account_removed | if 1 the account is removed | boolean | NO | | 0 | |
|
||||||
| account_expired | | boolean | NO | | 0 | |
|
| account_expired | | boolean | NO | | 0 | |
|
||||||
| account_expires_on | timestamp when account expires and will be deleted | datetime | NO | | 0001-01-01 00:00:00 | |
|
| account_expires_on | timestamp when account expires and will be deleted | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||||
| expire_notification_sent | timestamp of last warning of account expiration | datetime | NO | | 0001-01-01 00:00:00 | |
|
| expire_notification_sent | timestamp of last warning of account expiration | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||||
| def_gid | | int unsigned | NO | | 0 | |
|
| def_gid | | int unsigned | NO | | 0 | |
|
||||||
| allow_cid | default permission for this user | mediumtext | YES | | NULL | |
|
| allow_cid | default permission for this user | mediumtext | YES | | NULL | |
|
||||||
| allow_gid | default permission for this user | mediumtext | YES | | NULL | |
|
| allow_gid | default permission for this user | mediumtext | YES | | NULL | |
|
||||||
| deny_cid | default permission for this user | mediumtext | YES | | NULL | |
|
| deny_cid | default permission for this user | mediumtext | YES | | NULL | |
|
||||||
| deny_gid | default permission for this user | mediumtext | YES | | NULL | |
|
| deny_gid | default permission for this user | mediumtext | YES | | NULL | |
|
||||||
| openidserver | | text | YES | | NULL | |
|
| openidserver | | text | YES | | NULL | |
|
||||||
|
|
||||||
Indexes
|
Indexes
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -34,7 +34,7 @@ function lostpass_post(App $a)
|
||||||
DI::baseUrl()->redirect();
|
DI::baseUrl()->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
$condition = ['(`email` = ? OR `nickname` = ?) AND `verified` = 1 AND `blocked` = 0', $loginame, $loginame];
|
$condition = ['(`email` = ? OR `nickname` = ?) AND `verified` = 1 AND `blocked` = 0 AND `account_removed` = 0 AND `account_expired` = 0', $loginame, $loginame];
|
||||||
$user = DBA::selectFirst('user', ['uid', 'username', 'nickname', 'email', 'language'], $condition);
|
$user = DBA::selectFirst('user', ['uid', 'username', 'nickname', 'email', 'language'], $condition);
|
||||||
if (!DBA::isResult($user)) {
|
if (!DBA::isResult($user)) {
|
||||||
DI::sysmsg()->addNotice(DI::l10n()->t('No valid account found.'));
|
DI::sysmsg()->addNotice(DI::l10n()->t('No valid account found.'));
|
||||||
|
|
17
src/App.php
17
src/App.php
|
@ -27,6 +27,7 @@ use Friendica\App\BaseURL;
|
||||||
use Friendica\Capabilities\ICanCreateResponses;
|
use Friendica\Capabilities\ICanCreateResponses;
|
||||||
use Friendica\Core\Config\Factory\Config;
|
use Friendica\Core\Config\Factory\Config;
|
||||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||||
|
use Friendica\Model\User;
|
||||||
use Friendica\Module\Maintenance;
|
use Friendica\Module\Maintenance;
|
||||||
use Friendica\Security\Authentication;
|
use Friendica\Security\Authentication;
|
||||||
use Friendica\Core\Config\ValueObject\Cache;
|
use Friendica\Core\Config\ValueObject\Cache;
|
||||||
|
@ -164,14 +165,16 @@ class App
|
||||||
* Check if current user has admin role.
|
* Check if current user has admin role.
|
||||||
*
|
*
|
||||||
* @return bool true if user is an admin
|
* @return bool true if user is an admin
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function isSiteAdmin(): bool
|
public function isSiteAdmin(): bool
|
||||||
{
|
{
|
||||||
$admin_email = $this->config->get('config', 'admin_email');
|
return
|
||||||
|
$this->session->getLocalUserId()
|
||||||
$adminlist = explode(',', str_replace(' ', '', $admin_email));
|
&& $this->database->exists('user', [
|
||||||
|
'uid' => $this->getLoggedInUserId(),
|
||||||
return $this->session->getLocalUserId() && $admin_email && $this->database->exists('user', ['uid' => $this->getLoggedInUserId(), 'email' => $adminlist]);
|
'email' => User::getAdminEmailList()
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -259,8 +262,8 @@ class App
|
||||||
/**
|
/**
|
||||||
* Set workerqueue information
|
* Set workerqueue information
|
||||||
*
|
*
|
||||||
* @param array $queue
|
* @param array $queue
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setQueue(array $queue)
|
public function setQueue(array $queue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@ use Friendica\App\Mode;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Database\DBStructure;
|
use Friendica\Database\DBStructure;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
@ -148,7 +149,7 @@ class Update
|
||||||
}
|
}
|
||||||
|
|
||||||
DI::config()->set('system', 'maintenance', 1);
|
DI::config()->set('system', 'maintenance', 1);
|
||||||
|
|
||||||
// run the pre_update_nnnn functions in update.php
|
// run the pre_update_nnnn functions in update.php
|
||||||
for ($version = $stored + 1; $version <= $current; $version++) {
|
for ($version = $stored + 1; $version <= $current; $version++) {
|
||||||
Logger::notice('Execute pre update.', ['version' => $version]);
|
Logger::notice('Execute pre update.', ['version' => $version]);
|
||||||
|
@ -289,30 +290,16 @@ class Update
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
private static function updateFailed(int $update_id, string $error_message) {
|
private static function updateFailed(int $update_id, string $error_message)
|
||||||
//send the administrators an e-mail
|
{
|
||||||
$condition = ['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0];
|
$adminEmails = User::getAdminListForEmailing(['uid', 'language', 'email']);
|
||||||
$adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]);
|
if (!$adminEmails) {
|
||||||
|
|
||||||
// No valid result?
|
|
||||||
if (!DBA::isResult($adminlist)) {
|
|
||||||
Logger::warning('Cannot notify administrators .', ['update' => $update_id, 'message' => $error_message]);
|
Logger::warning('Cannot notify administrators .', ['update' => $update_id, 'message' => $error_message]);
|
||||||
|
|
||||||
// Don't continue
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sent = [];
|
foreach($adminEmails as $admin) {
|
||||||
|
$l10n = DI::l10n()->withLang($admin['language'] ?: 'en');
|
||||||
// every admin could had different language
|
|
||||||
while ($admin = DBA::fetch($adminlist)) {
|
|
||||||
if (in_array($admin['email'], $sent)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$sent[] = $admin['email'];
|
|
||||||
|
|
||||||
$lang = $admin['language'] ?? 'en';
|
|
||||||
$l10n = DI::l10n()->withLang($lang);
|
|
||||||
|
|
||||||
$preamble = Strings::deindent($l10n->t("
|
$preamble = Strings::deindent($l10n->t("
|
||||||
The friendica developers released update %s recently,
|
The friendica developers released update %s recently,
|
||||||
|
@ -343,35 +330,20 @@ class Update
|
||||||
*/
|
*/
|
||||||
private static function updateSuccessful(int $from_build, int $to_build)
|
private static function updateSuccessful(int $from_build, int $to_build)
|
||||||
{
|
{
|
||||||
//send the administrators an e-mail
|
foreach(User::getAdminListForEmailing(['uid', 'language', 'email']) as $admin) {
|
||||||
$condition = ['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0];
|
$l10n = DI::l10n()->withLang($admin['language'] ?: 'en');
|
||||||
$adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]);
|
|
||||||
|
|
||||||
if (DBA::isResult($adminlist)) {
|
$preamble = Strings::deindent($l10n->t('
|
||||||
$sent = [];
|
The friendica database was successfully updated from %s to %s.',
|
||||||
|
$from_build, $to_build));
|
||||||
|
|
||||||
// every admin could had different language
|
$email = DI::emailer()
|
||||||
while ($admin = DBA::fetch($adminlist)) {
|
->newSystemMail()
|
||||||
if (in_array($admin['email'], $sent)) {
|
->withMessage($l10n->t('[Friendica Notify] Database update'), $preamble)
|
||||||
continue;
|
->forUser($admin)
|
||||||
}
|
->withRecipient($admin['email'])
|
||||||
$sent[] = $admin['email'];
|
->build();
|
||||||
|
DI::emailer()->send($email);
|
||||||
$lang = (($admin['language']) ? $admin['language'] : 'en');
|
|
||||||
$l10n = DI::l10n()->withLang($lang);
|
|
||||||
|
|
||||||
$preamble = Strings::deindent($l10n->t('
|
|
||||||
The friendica database was successfully updated from %s to %s.',
|
|
||||||
$from_build, $to_build));
|
|
||||||
|
|
||||||
$email = DI::emailer()
|
|
||||||
->newSystemMail()
|
|
||||||
->withMessage($l10n->t('[Friendica Notify] Database update'), $preamble)
|
|
||||||
->forUser($admin)
|
|
||||||
->withRecipient($admin['email'])
|
|
||||||
->build();
|
|
||||||
DI::emailer()->send($email);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::debug('Database structure update successful.');
|
Logger::debug('Database structure update successful.');
|
||||||
|
|
|
@ -164,25 +164,16 @@ class Nodeinfo
|
||||||
*
|
*
|
||||||
* @param IManageConfigValues $config Configuration instance
|
* @param IManageConfigValues $config Configuration instance
|
||||||
* @return array Organization information
|
* @return array Organization information
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function getOrganization(IManageConfigValues $config): array
|
public static function getOrganization(IManageConfigValues $config): array
|
||||||
{
|
{
|
||||||
$organization = [
|
$administrator = User::getFirstAdmin(['username', 'email', 'nickname']);
|
||||||
'name' => null,
|
|
||||||
'contact' => null,
|
return [
|
||||||
'account' => null
|
'name' => $administrator['username'] ?? null,
|
||||||
|
'contact' => $administrator['email'] ?? null,
|
||||||
|
'account' => $administrator['nickname'] ?? '' ? DI::baseUrl()->get() . '/profile/' . $administrator['nickname'] : null,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!empty($config->get('config', 'admin_email'))) {
|
|
||||||
$adminList = explode(',', str_replace(' ', '', $config->get('config', 'admin_email')));
|
|
||||||
$organization['contact'] = $adminList[0];
|
|
||||||
$administrator = User::getByEmail($adminList[0], ['username', 'nickname']);
|
|
||||||
if (!empty($administrator)) {
|
|
||||||
$organization['name'] = $administrator['username'];
|
|
||||||
$organization['account'] = DI::baseUrl()->get() . '/profile/' . $administrator['nickname'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $organization;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,11 +178,15 @@ class UserNotification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::getById($uid, ['account-type']);
|
$user = User::getById($uid, ['account-type', 'account_removed', 'account_expired']);
|
||||||
if (in_array($user['account-type'], [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) {
|
if (in_array($user['account-type'], [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($user['account_removed'] || $user['account_expired']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$author = Contact::getById($item['author-id'], ['contact-type']);
|
$author = Contact::getById($item['author-id'], ['contact-type']);
|
||||||
if (empty($author)) {
|
if (empty($author)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -265,7 +265,7 @@ class User
|
||||||
// List of possible actor names
|
// List of possible actor names
|
||||||
$possible_accounts = ['friendica', 'actor', 'system', 'internal'];
|
$possible_accounts = ['friendica', 'actor', 'system', 'internal'];
|
||||||
foreach ($possible_accounts as $name) {
|
foreach ($possible_accounts as $name) {
|
||||||
if (!DBA::exists('user', ['nickname' => $name, 'account_removed' => false, 'expire' => false]) &&
|
if (!DBA::exists('user', ['nickname' => $name, 'account_removed' => false, 'account_expired' => false]) &&
|
||||||
!DBA::exists('userd', ['username' => $name])) {
|
!DBA::exists('userd', ['username' => $name])) {
|
||||||
DI::config()->set('system', 'actor_name', $name);
|
DI::config()->set('system', 'actor_name', $name);
|
||||||
return $name;
|
return $name;
|
||||||
|
@ -381,17 +381,15 @@ class User
|
||||||
*
|
*
|
||||||
* @param array $fields
|
* @param array $fields
|
||||||
* @return array user
|
* @return array user
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static function getFirstAdmin(array $fields = []) : array
|
public static function getFirstAdmin(array $fields = []) : array
|
||||||
{
|
{
|
||||||
if (!empty(DI::config()->get('config', 'admin_nickname'))) {
|
if (!empty(DI::config()->get('config', 'admin_nickname'))) {
|
||||||
return self::getByNickname(DI::config()->get('config', 'admin_nickname'), $fields);
|
return self::getByNickname(DI::config()->get('config', 'admin_nickname'), $fields);
|
||||||
} elseif (!empty(DI::config()->get('config', 'admin_email'))) {
|
|
||||||
$adminList = explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email')));
|
|
||||||
return self::getByEmail($adminList[0], $fields);
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return self::getAdminList()[0] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1054,11 +1052,8 @@ class User
|
||||||
|
|
||||||
// Disallow somebody creating an account using openid that uses the admin email address,
|
// Disallow somebody creating an account using openid that uses the admin email address,
|
||||||
// since openid bypasses email verification. We'll allow it if there is not yet an admin account.
|
// since openid bypasses email verification. We'll allow it if there is not yet an admin account.
|
||||||
if (DI::config()->get('config', 'admin_email') && strlen($openid_url)) {
|
if (strlen($openid_url) && in_array(strtolower($email), self::getAdminEmailList())) {
|
||||||
$adminlist = explode(',', str_replace(' ', '', strtolower(DI::config()->get('config', 'admin_email'))));
|
throw new Exception(DI::l10n()->t('Cannot use that email.'));
|
||||||
if (in_array(strtolower($email), $adminlist)) {
|
|
||||||
throw new Exception(DI::l10n()->t('Cannot use that email.'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$nickname = $data['nickname'] = strtolower($nickname);
|
$nickname = $data['nickname'] = strtolower($nickname);
|
||||||
|
@ -1783,4 +1778,64 @@ class User
|
||||||
|
|
||||||
return DBA::selectToArray('owner-view', [], $condition, $param);
|
return DBA::selectToArray('owner-view', [], $condition, $param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of lowercase admin email addresses from the comma-separated list in the config
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getAdminEmailList(): array
|
||||||
|
{
|
||||||
|
$adminEmails = strtolower(str_replace(' ', '', DI::config()->get('config', 'admin_email')));
|
||||||
|
if (!$adminEmails) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return explode(',', $adminEmails);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the complete list of admin user accounts
|
||||||
|
*
|
||||||
|
* @param array $fields
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getAdminList(array $fields = []): array
|
||||||
|
{
|
||||||
|
$condition = [
|
||||||
|
'email' => self::getAdminEmailList(),
|
||||||
|
'parent-uid' => 0,
|
||||||
|
'blocked' => 0,
|
||||||
|
'verified' => true,
|
||||||
|
'account_removed' => false,
|
||||||
|
'account_expired' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
return DBA::selectToArray('user', $fields, $condition, ['order' => ['uid']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of admin user accounts where each unique email address appears only once.
|
||||||
|
*
|
||||||
|
* This method is meant for admin notifications that do not need to be sent multiple times to the same email address.
|
||||||
|
*
|
||||||
|
* @param array $fields
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getAdminListForEmailing(array $fields = []): array
|
||||||
|
{
|
||||||
|
return array_filter(self::getAdminList($fields), function ($user) {
|
||||||
|
static $emails = [];
|
||||||
|
|
||||||
|
if (in_array($user['email'], $emails)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$emails[] = $user['email'];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace Friendica\Module\Api\GNUSocial\GNUSocial;
|
||||||
|
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
use Friendica\Model\User;
|
||||||
use Friendica\Module\BaseApi;
|
use Friendica\Module\BaseApi;
|
||||||
use Friendica\Module\Register;
|
use Friendica\Module\Register;
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ class Config extends BaseApi
|
||||||
'logo' => DI::baseUrl() . '/images/friendica-64.png',
|
'logo' => DI::baseUrl() . '/images/friendica-64.png',
|
||||||
'fancy' => true,
|
'fancy' => true,
|
||||||
'language' => DI::config()->get('system', 'language'),
|
'language' => DI::config()->get('system', 'language'),
|
||||||
'email' => DI::config()->get('config', 'admin_email'),
|
'email' => implode(',', User::getAdminEmailList()),
|
||||||
'broughtby' => '',
|
'broughtby' => '',
|
||||||
'broughtbyurl' => '',
|
'broughtbyurl' => '',
|
||||||
'timezone' => DI::config()->get('system', 'default_timezone'),
|
'timezone' => DI::config()->get('system', 'default_timezone'),
|
||||||
|
|
|
@ -113,7 +113,7 @@ abstract class BaseUsers extends BaseModeration
|
||||||
|
|
||||||
protected function setupUserCallback(): \Closure
|
protected function setupUserCallback(): \Closure
|
||||||
{
|
{
|
||||||
$adminlist = explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email')));
|
$adminlist = User::getAdminEmailList();
|
||||||
return function ($user) use ($adminlist) {
|
return function ($user) use ($adminlist) {
|
||||||
$page_types = [
|
$page_types = [
|
||||||
User::PAGE_FLAGS_NORMAL => $this->t('Normal Account Page'),
|
User::PAGE_FLAGS_NORMAL => $this->t('Normal Account Page'),
|
||||||
|
|
|
@ -352,7 +352,7 @@ class Register extends BaseModule
|
||||||
DI::baseUrl()->redirect();
|
DI::baseUrl()->redirect();
|
||||||
}
|
}
|
||||||
} elseif (intval(DI::config()->get('config', 'register_policy')) === self::APPROVE) {
|
} elseif (intval(DI::config()->get('config', 'register_policy')) === self::APPROVE) {
|
||||||
if (!strlen(DI::config()->get('config', 'admin_email'))) {
|
if (!User::getAdminEmailList()) {
|
||||||
DI::sysmsg()->addNotice(DI::l10n()->t('Your registration can not be processed.'));
|
DI::sysmsg()->addNotice(DI::l10n()->t('Your registration can not be processed.'));
|
||||||
DI::baseUrl()->redirect();
|
DI::baseUrl()->redirect();
|
||||||
}
|
}
|
||||||
|
@ -387,34 +387,23 @@ class Register extends BaseModule
|
||||||
DI::sysmsg()->addInfo(DI::l10n()->t('Your registration is pending approval by the site owner.'));
|
DI::sysmsg()->addInfo(DI::l10n()->t('Your registration is pending approval by the site owner.'));
|
||||||
DI::baseUrl()->redirect();
|
DI::baseUrl()->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendNotification(array $user, string $event)
|
private function sendNotification(array $user, string $event)
|
||||||
{
|
{
|
||||||
// send email to admins
|
foreach (User::getAdminListForEmailing(['uid', 'language', 'email']) as $admin) {
|
||||||
$admins_stmt = DBA::select(
|
|
||||||
'user',
|
|
||||||
['uid', 'language', 'email'],
|
|
||||||
['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email')))]
|
|
||||||
);
|
|
||||||
|
|
||||||
// send notification to admins
|
|
||||||
while ($admin = DBA::fetch($admins_stmt)) {
|
|
||||||
DI::notify()->createFromArray([
|
DI::notify()->createFromArray([
|
||||||
'type' => Model\Notification\Type::SYSTEM,
|
'type' => Model\Notification\Type::SYSTEM,
|
||||||
'event' => $event,
|
'event' => $event,
|
||||||
'uid' => $admin['uid'],
|
'uid' => $admin['uid'],
|
||||||
'link' => DI::baseUrl()->get(true) . '/moderation/users/',
|
'link' => DI::baseUrl()->get(true) . '/moderation/users/',
|
||||||
'source_name' => $user['username'],
|
'source_name' => $user['username'],
|
||||||
'source_mail' => $user['email'],
|
'source_mail' => $user['email'],
|
||||||
'source_nick' => $user['nickname'],
|
'source_nick' => $user['nickname'],
|
||||||
'source_link' => DI::baseUrl()->get(true) . '/moderation/users/',
|
'source_link' => DI::baseUrl()->get(true) . '/moderation/users/',
|
||||||
'source_photo' => User::getAvatarUrl($user, Proxy::SIZE_THUMB),
|
'source_photo' => User::getAvatarUrl($user, Proxy::SIZE_THUMB),
|
||||||
'show_in_notification_page' => false
|
'show_in_notification_page' => false
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
DBA::close($admins_stmt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,12 +113,9 @@ class Account extends BaseSettings
|
||||||
$err .= DI::l10n()->t('Invalid email.');
|
$err .= DI::l10n()->t('Invalid email.');
|
||||||
}
|
}
|
||||||
// ensure new email is not the admin mail
|
// ensure new email is not the admin mail
|
||||||
if (DI::config()->get('config', 'admin_email')) {
|
if (in_array(strtolower($email), User::getAdminEmailList())) {
|
||||||
$adminlist = explode(",", str_replace(" ", "", strtolower(DI::config()->get('config', 'admin_email'))));
|
$err .= DI::l10n()->t('Cannot change to that email.');
|
||||||
if (in_array(strtolower($email), $adminlist)) {
|
$email = $user['email'];
|
||||||
$err .= DI::l10n()->t('Cannot change to that email.');
|
|
||||||
$email = $user['email'];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,14 +85,8 @@ class RemoveMe extends BaseSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
// send notification to admins so that they can clean up the backups
|
// send notification to admins so that they can clean up the backups
|
||||||
$admin_mails = explode(',', $this->config->get('config', 'admin_email'));
|
foreach (User::getAdminListForEmailing(['uid', 'language', 'email']) as $admin) {
|
||||||
foreach ($admin_mails as $mail) {
|
$l10n = $this->l10n->withLang($admin['language'] ?: 'en');
|
||||||
$admin = $this->database->selectFirst('user', ['uid', 'language', 'email', 'username'], ['email' => trim($mail)]);
|
|
||||||
if (!$admin) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$l10n = $this->l10n->withLang($admin['language']);
|
|
||||||
|
|
||||||
$email = $this->emailer
|
$email = $this->emailer
|
||||||
->newSystemMail()
|
->newSystemMail()
|
||||||
|
|
|
@ -230,7 +230,7 @@ class Notify extends BaseRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the important fields are set at any time
|
// Ensure that the important fields are set at any time
|
||||||
$fields = ['nickname', 'account-type', 'notify-flags', 'language', 'username', 'email'];
|
$fields = ['nickname', 'account-type', 'notify-flags', 'language', 'username', 'email', 'account_removed', 'account_expired'];
|
||||||
$user = DBA::selectFirst('user', $fields, ['uid' => $params['uid']]);
|
$user = DBA::selectFirst('user', $fields, ['uid' => $params['uid']]);
|
||||||
|
|
||||||
if (!DBA::isResult($user)) {
|
if (!DBA::isResult($user)) {
|
||||||
|
@ -238,6 +238,10 @@ class Notify extends BaseRepository
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($user['account_removed'] || $user['account_expired']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// There is no need to create notifications for forum accounts
|
// There is no need to create notifications for forum accounts
|
||||||
if ($user['account-type'] == Model\User::ACCOUNT_TYPE_COMMUNITY) {
|
if ($user['account-type'] == Model\User::ACCOUNT_TYPE_COMMUNITY) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -503,7 +507,7 @@ class Notify extends BaseRepository
|
||||||
$tsitelink = sprintf($sitelink, $params['link']);
|
$tsitelink = sprintf($sitelink, $params['link']);
|
||||||
$hsitelink = sprintf($sitelink, '<a href="' . $params['link'] . '">' . $sitename . '</a><br><br>');
|
$hsitelink = sprintf($sitelink, '<a href="' . $params['link'] . '">' . $sitename . '</a><br><br>');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'SYSTEM_DB_UPDATE_FAIL': // @TODO Unused (only here)
|
case 'SYSTEM_DB_UPDATE_FAIL': // @TODO Unused (only here)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -525,8 +529,11 @@ class Notify extends BaseRepository
|
||||||
$parent_uri_id = $params['item']['parent-uri-id'] ?? null;
|
$parent_uri_id = $params['item']['parent-uri-id'] ?? null;
|
||||||
|
|
||||||
// Ensure that the important fields are set at any time
|
// Ensure that the important fields are set at any time
|
||||||
$fields = ['nickname'];
|
$fields = ['nickname', 'account_removed', 'account_expired'];
|
||||||
$user = Model\User::getById($params['uid'], $fields);
|
$user = Model\User::getById($params['uid'], $fields);
|
||||||
|
if ($user['account_removed'] || $user['user_expired']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$sitename = $this->config->get('config', 'sitename');
|
$sitename = $this->config->get('config', 'sitename');
|
||||||
|
|
||||||
|
@ -711,6 +718,9 @@ class Notify extends BaseRepository
|
||||||
$params['otype'] = Model\Notification\ObjectType::ITEM;
|
$params['otype'] = Model\Notification\ObjectType::ITEM;
|
||||||
|
|
||||||
$user = Model\User::getById($Notification->uid);
|
$user = Model\User::getById($Notification->uid);
|
||||||
|
if ($user['account_removed'] || $user['account_expired']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$params['notify_flags'] = $user['notify-flags'];
|
$params['notify_flags'] = $user['notify-flags'];
|
||||||
$params['language'] = $user['language'];
|
$params['language'] = $user['language'];
|
||||||
|
|
|
@ -86,7 +86,7 @@ class Instance extends BaseDataTransferObject
|
||||||
$this->uri = $baseUrl->get();
|
$this->uri = $baseUrl->get();
|
||||||
$this->title = $config->get('config', 'sitename');
|
$this->title = $config->get('config', 'sitename');
|
||||||
$this->short_description = $this->description = $config->get('config', 'info');
|
$this->short_description = $this->description = $config->get('config', 'info');
|
||||||
$this->email = $config->get('config', 'admin_email');
|
$this->email = implode(',', User::getAdminEmailList());
|
||||||
$this->version = '2.8.0 (compatible; Friendica ' . App::VERSION . ')';
|
$this->version = '2.8.0 (compatible; Friendica ' . App::VERSION . ')';
|
||||||
$this->urls = null; // Not supported
|
$this->urls = null; // Not supported
|
||||||
$this->stats = new Stats($config, $database);
|
$this->stats = new Stats($config, $database);
|
||||||
|
@ -98,13 +98,10 @@ class Instance extends BaseDataTransferObject
|
||||||
$this->invites_enabled = false;
|
$this->invites_enabled = false;
|
||||||
$this->contact_account = [];
|
$this->contact_account = [];
|
||||||
|
|
||||||
if (!empty($config->get('config', 'admin_email'))) {
|
$administrator = User::getFirstAdmin(['nickname']);
|
||||||
$adminList = explode(',', str_replace(' ', '', $config->get('config', 'admin_email')));
|
if ($administrator) {
|
||||||
$administrator = User::getByEmail($adminList[0], ['nickname']);
|
$adminContact = $database->selectFirst('contact', ['uri-id'], ['nick' => $administrator['nickname'], 'self' => true]);
|
||||||
if (!empty($administrator)) {
|
$this->contact_account = DI::mstdnAccount()->createFromUriId($adminContact['uri-id']);
|
||||||
$adminContact = $database->selectFirst('contact', ['id'], ['nick' => $administrator['nickname'], 'self' => true]);
|
|
||||||
$this->contact_account = DI::mstdnAccount()->createFromContactId($adminContact['id']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1710,7 +1710,7 @@ class Transmitter
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['attachment'] = self::createAttachmentList($item);
|
$data['attachment'] = self::createAttachmentList($item);
|
||||||
$data['tag'] = self::createTagList($item, $data['quoteUrl'] ?? '');
|
$data['tag'] = self::createTagList($item, $data['quoteUrl'] ?? '');
|
||||||
|
|
||||||
if (empty($data['location']) && (!empty($item['coord']) || !empty($item['location']))) {
|
if (empty($data['location']) && (!empty($item['coord']) || !empty($item['location']))) {
|
||||||
$data['location'] = self::createLocation($item);
|
$data['location'] = self::createLocation($item);
|
||||||
|
@ -2073,13 +2073,14 @@ class Transmitter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($uid)) {
|
if (empty($uid)) {
|
||||||
// Fetch the list of administrators
|
|
||||||
$admin_mail = explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email')));
|
|
||||||
|
|
||||||
// We need to use some user as a sender. It doesn't care who it will send. We will use an administrator account.
|
// We need to use some user as a sender. It doesn't care who it will send. We will use an administrator account.
|
||||||
$condition = ['verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false, 'email' => $admin_mail];
|
$admin = User::getFirstAdmin(['uid']);
|
||||||
$first_user = DBA::selectFirst('user', ['uid'], $condition);
|
if (!$admin) {
|
||||||
$uid = $first_user['uid'];
|
Logger::warning('No available admin user for transmission', ['target' => $target]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uid = $admin['uid'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$condition = ['verb' => Activity::FOLLOW, 'uid' => 0, 'parent-uri' => $object,
|
$condition = ['verb' => Activity::FOLLOW, 'uid' => 0, 'parent-uri' => $object,
|
||||||
|
|
|
@ -136,7 +136,7 @@ return [
|
||||||
"pwdreset" => ["type" => "varchar(255)", "comment" => "Password reset request token"],
|
"pwdreset" => ["type" => "varchar(255)", "comment" => "Password reset request token"],
|
||||||
"pwdreset_time" => ["type" => "datetime", "comment" => "Timestamp of the last password reset request"],
|
"pwdreset_time" => ["type" => "datetime", "comment" => "Timestamp of the last password reset request"],
|
||||||
"maxreq" => ["type" => "int unsigned", "not null" => "1", "default" => "10", "comment" => ""],
|
"maxreq" => ["type" => "int unsigned", "not null" => "1", "default" => "10", "comment" => ""],
|
||||||
"expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
|
"expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Delay in days before deleting user-related posts. Scope is controlled by pConfig."],
|
||||||
"account_removed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if 1 the account is removed"],
|
"account_removed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if 1 the account is removed"],
|
||||||
"account_expired" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
|
"account_expired" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
|
||||||
"account_expires_on" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp when account expires and will be deleted"],
|
"account_expires_on" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "timestamp when account expires and will be deleted"],
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue