3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Module\Admin;
24 use Friendica\Content\Pager;
25 use Friendica\Core\Renderer;
26 use Friendica\Database\DBA;
28 use Friendica\Model\Register;
29 use Friendica\Model\User;
30 use Friendica\Module\BaseAdmin;
31 use Friendica\Util\Strings;
32 use Friendica\Util\Temporal;
34 class Users extends BaseAdmin
36 public static function post(array $parameters = [])
38 parent::post($parameters);
40 $pending = $_POST['pending'] ?? [];
41 $users = $_POST['user'] ?? [];
42 $nu_name = $_POST['new_user_name'] ?? '';
43 $nu_nickname = $_POST['new_user_nickname'] ?? '';
44 $nu_email = $_POST['new_user_email'] ?? '';
45 $nu_language = DI::config()->get('system', 'language');
47 parent::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users');
49 if ($nu_name !== '' && $nu_email !== '' && $nu_nickname !== '') {
51 $result = User::create([
52 'username' => $nu_name,
54 'nickname' => $nu_nickname,
56 'language' => $nu_language
58 } catch (\Exception $ex) {
59 notice($ex->getMessage());
63 $user = $result['user'];
64 $preamble = Strings::deindent(DI::l10n()->t('
66 the administrator of %2$s has set up an account for you.'));
67 $body = Strings::deindent(DI::l10n()->t('
68 The login details are as follows:
74 You may change your password from your account "Settings" page after logging
77 Please take a few moments to review the other account settings on that page.
79 You may also wish to add some basic information to your default profile
80 (on the "Profiles" page) so that other people can easily find you.
82 We recommend setting your full name, adding a profile photo,
83 adding some profile "keywords" (very useful in making new friends) - and
84 perhaps what country you live in; if you do not wish to be more specific
87 We fully respect your right to privacy, and none of these items are necessary.
88 If you are new and do not know anybody here, they may help
89 you to make some new and interesting friends.
91 If you ever want to delete your account, you can do so at %1$s/removeme
93 Thank you and welcome to %4$s.'));
95 $preamble = sprintf($preamble, $user['username'], DI::config()->get('config', 'sitename'));
96 $body = sprintf($body, DI::baseUrl()->get(), $user['nickname'], $result['password'], DI::config()->get('config', 'sitename'));
98 $email = DI::emailer()
100 ->withMessage(DI::l10n()->t('Registration details for %s', DI::config()->get('config', 'sitename')), $preamble, $body)
102 ->withRecipient($user['email'])
104 return DI::emailer()->send($email);
107 if (!empty($_POST['page_users_block'])) {
108 // @TODO Move this to Model\User:block($users);
109 DBA::update('user', ['blocked' => 1], ['uid' => $users]);
110 notice(DI::l10n()->tt('%s user blocked', '%s users blocked', count($users)));
113 if (!empty($_POST['page_users_unblock'])) {
114 // @TODO Move this to Model\User:unblock($users);
115 DBA::update('user', ['blocked' => 0], ['uid' => $users]);
116 notice(DI::l10n()->tt('%s user unblocked', '%s users unblocked', count($users)));
119 if (!empty($_POST['page_users_delete'])) {
120 foreach ($users as $uid) {
121 if (local_user() != $uid) {
124 notice(DI::l10n()->t('You can\'t remove yourself'));
128 notice(DI::l10n()->tt('%s user deleted', '%s users deleted', count($users)));
131 if (!empty($_POST['page_users_approve'])) {
132 require_once 'mod/regmod.php';
133 foreach ($pending as $hash) {
138 if (!empty($_POST['page_users_deny'])) {
139 require_once 'mod/regmod.php';
140 foreach ($pending as $hash) {
145 DI::baseUrl()->redirect('admin/users');
148 public static function content(array $parameters = [])
150 parent::content($parameters);
155 // @TODO: Replace with parameter from router
156 $action = $a->argv[2];
158 $user = User::getById($uid, ['username', 'blocked']);
159 if (!DBA::isResult($user)) {
160 notice('User not found' . EOL);
161 DI::baseUrl()->redirect('admin/users');
162 return ''; // NOTREACHED
167 if (local_user() != $uid) {
168 parent::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users', 't');
172 notice(DI::l10n()->t('User "%s" deleted', $user['username']));
174 notice(DI::l10n()->t('You can\'t remove yourself'));
178 parent::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users', 't');
179 // @TODO Move this to Model\User:block([$uid]);
180 DBA::update('user', ['blocked' => 1], ['uid' => $uid]);
181 notice(DI::l10n()->t('User "%s" blocked', $user['username']));
184 parent::checkFormSecurityTokenRedirectOnError('/admin/users', 'admin_users', 't');
185 // @TODO Move this to Model\User:unblock([$uid]);
186 DBA::update('user', ['blocked' => 0], ['uid' => $uid]);
187 notice(DI::l10n()->t('User "%s" unblocked', $user['username']));
191 DI::baseUrl()->redirect('admin/users');
195 $pending = Register::getPending();
197 $pager = new Pager(DI::args()->getQueryString(), 100);
199 // @TODO Move below block to Model\User::getUsers($start, $count, $order = 'contact.name', $order_direction = '+')
203 'user.register_date',
209 $order = 'contact.name';
210 $order_direction = '+';
211 if (!empty($_GET['o'])) {
212 $new_order = $_GET['o'];
213 if ($new_order[0] === '-') {
214 $order_direction = '-';
215 $new_order = substr($new_order, 1);
218 if (in_array($new_order, $valid_orders)) {
222 $sql_order = '`' . str_replace('.', '`.`', $order) . '`';
223 $sql_order_direction = ($order_direction === '+') ? 'ASC' : 'DESC';
225 $usersStmt = DBA::p("SELECT `user`.*, `contact`.`name`, `contact`.`url`, `contact`.`micro`, `user`.`account_expired`, `contact`.`last-item` AS `lastitem_date`
227 INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self`
228 WHERE `user`.`verified`
229 ORDER BY $sql_order $sql_order_direction LIMIT ?, ?", $pager->getStart(), $pager->getItemsPerPage()
231 $users = DBA::toArray($usersStmt);
233 $adminlist = explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email')));
234 $_setup_users = function ($e) use ($adminlist) {
236 User::PAGE_FLAGS_NORMAL => DI::l10n()->t('Normal Account Page'),
237 User::PAGE_FLAGS_SOAPBOX => DI::l10n()->t('Soapbox Page'),
238 User::PAGE_FLAGS_COMMUNITY => DI::l10n()->t('Public Forum'),
239 User::PAGE_FLAGS_FREELOVE => DI::l10n()->t('Automatic Friend Page'),
240 User::PAGE_FLAGS_PRVGROUP => DI::l10n()->t('Private Forum')
243 User::ACCOUNT_TYPE_PERSON => DI::l10n()->t('Personal Page'),
244 User::ACCOUNT_TYPE_ORGANISATION => DI::l10n()->t('Organisation Page'),
245 User::ACCOUNT_TYPE_NEWS => DI::l10n()->t('News Page'),
246 User::ACCOUNT_TYPE_COMMUNITY => DI::l10n()->t('Community Forum'),
247 User::ACCOUNT_TYPE_RELAY => DI::l10n()->t('Relay'),
250 $e['page_flags_raw'] = $e['page-flags'];
251 $e['page-flags'] = $page_types[$e['page-flags']];
253 $e['account_type_raw'] = ($e['page_flags_raw'] == 0) ? $e['account-type'] : -1;
254 $e['account-type'] = ($e['page_flags_raw'] == 0) ? $account_types[$e['account-type']] : '';
256 $e['register_date'] = Temporal::getRelativeDate($e['register_date']);
257 $e['login_date'] = Temporal::getRelativeDate($e['login_date']);
258 $e['lastitem_date'] = Temporal::getRelativeDate($e['lastitem_date']);
259 $e['is_admin'] = in_array($e['email'], $adminlist);
260 $e['is_deletable'] = (intval($e['uid']) != local_user());
261 $e['deleted'] = ($e['account_removed'] ? Temporal::getRelativeDate($e['account_expires_on']) : False);
266 $tmp_users = array_map($_setup_users, $users);
268 // Get rid of dashes in key names, Smarty3 can't handle them
269 // and extracting deleted users
273 foreach ($tmp_users as $user) {
274 foreach ($user as $k => $v) {
275 $newkey = str_replace('-', '_', $k);
279 if ($user['deleted']) {
286 $th_users = array_map(null, [DI::l10n()->t('Name'), DI::l10n()->t('Email'), DI::l10n()->t('Register date'), DI::l10n()->t('Last login'), DI::l10n()->t('Last item'), DI::l10n()->t('Type')], $valid_orders);
288 $t = Renderer::getMarkupTemplate('admin/users.tpl');
289 $o = Renderer::replaceMacros($t, [
291 '$title' => DI::l10n()->t('Administration'),
292 '$page' => DI::l10n()->t('Users'),
293 '$submit' => DI::l10n()->t('Add User'),
294 '$select_all' => DI::l10n()->t('select all'),
295 '$h_pending' => DI::l10n()->t('User registrations waiting for confirm'),
296 '$h_deleted' => DI::l10n()->t('User waiting for permanent deletion'),
297 '$th_pending' => [DI::l10n()->t('Request date'), DI::l10n()->t('Name'), DI::l10n()->t('Email')],
298 '$no_pending' => DI::l10n()->t('No registrations.'),
299 '$pendingnotetext' => DI::l10n()->t('Note from the user'),
300 '$approve' => DI::l10n()->t('Approve'),
301 '$deny' => DI::l10n()->t('Deny'),
302 '$delete' => DI::l10n()->t('Delete'),
303 '$block' => DI::l10n()->t('Block'),
304 '$blocked' => DI::l10n()->t('User blocked'),
305 '$unblock' => DI::l10n()->t('Unblock'),
306 '$siteadmin' => DI::l10n()->t('Site admin'),
307 '$accountexpired' => DI::l10n()->t('Account expired'),
309 '$h_users' => DI::l10n()->t('Users'),
310 '$h_newuser' => DI::l10n()->t('New User'),
311 '$th_deleted' => [DI::l10n()->t('Name'), DI::l10n()->t('Email'), DI::l10n()->t('Register date'), DI::l10n()->t('Last login'), DI::l10n()->t('Last item'), DI::l10n()->t('Permanent deletion')],
312 '$th_users' => $th_users,
313 '$order_users' => $order,
314 '$order_direction_users' => $order_direction,
316 '$confirm_delete_multi' => DI::l10n()->t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'),
317 '$confirm_delete' => DI::l10n()->t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'),
319 '$form_security_token' => parent::getFormSecurityToken('admin_users'),
322 '$baseurl' => DI::baseUrl()->get(true),
324 '$pending' => $pending,
325 'deleted' => $deleted,
327 '$newusername' => ['new_user_name', DI::l10n()->t('Name'), '', DI::l10n()->t('Name of the new user.')],
328 '$newusernickname' => ['new_user_nickname', DI::l10n()->t('Nickname'), '', DI::l10n()->t('Nickname of the new user.')],
329 '$newuseremail' => ['new_user_email', DI::l10n()->t('Email'), '', DI::l10n()->t('Email address of the new user.'), '', '', 'email'],
332 $o .= $pager->renderFull(DBA::count('user'));