]> git.mxchange.org Git - friendica.git/blob - src/Console/User.php
3fdeac1c5631a02ed3ccbed7c5e98a3d9924aa6d
[friendica.git] / src / Console / User.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2020, Friendica
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
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.
11  *
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.
16  *
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/>.
19  *
20  */
21
22 namespace Friendica\Console;
23
24 use Console_Table;
25 use Friendica\App;
26 use Friendica\Content\Pager;
27 use Friendica\Core\L10n;
28 use Friendica\Database\Database;
29 use Friendica\Model\Register;
30 use Friendica\Model\User as UserModel;
31 use RuntimeException;
32 use Seld\CliPrompt\CliPrompt;
33
34 /**
35  * tool to manage users of the current node
36  */
37 class User extends \Asika\SimpleConsole\Console
38 {
39         protected $helpOptions = ['h', 'help', '?'];
40
41         /**
42          * @var App\Mode
43          */
44         private $appMode;
45         /**
46          * @var L10n
47          */
48         private $l10n;
49         /**
50          * @var Database
51          */
52         private $dba;
53
54         protected function getHelp()
55         {
56                 $help = <<<HELP
57 console user - Modify user settings per console commands.
58 Usage
59         bin/console user password <nickname> [<password>] [-h|--help|-?] [-v]
60         bin/console user add [<name> [<nickname> [<email> [<language>]]]] [-h|--help|-?] [-v]
61         bin/console user delete [<nickname>] [-q] [-h|--help|-?] [-v]
62         bin/console user allow [<nickname>] [-h|--help|-?] [-v]
63         bin/console user deny [<nickname>] [-h|--help|-?] [-v]
64         bin/console user block [<nickname>] [-h|--help|-?] [-v]
65         bin/console user unblock [<nickname>] [-h|--help|-?] [-v]
66         bin/console user list pending [start=0 [count=50]] [-h|--help|-?] [-v]
67         bin/console user list all [start=0 [count=50]] [-h|--help|-?] [-v]
68
69 Description
70         Modify user settings per console commands.
71
72 Options
73     -h|--help|-? Show help information
74     -v           Show more debug information.
75     -q           Quiet mode (don't ask for a command).
76 HELP;
77                 return $help;
78         }
79
80         public function __construct(App\Mode $appMode, L10n $l10n, Database $dba, array $argv = null)
81         {
82                 parent::__construct($argv);
83
84                 $this->appMode     = $appMode;
85                 $this->l10n        = $l10n;
86                 $this->dba         = $dba;
87         }
88
89         protected function doExecute()
90         {
91                 if ($this->getOption('v')) {
92                         $this->out('Class: ' . __CLASS__);
93                         $this->out('Arguments: ' . var_export($this->args, true));
94                         $this->out('Options: ' . var_export($this->options, true));
95                 }
96
97                 if (count($this->args) == 0) {
98                         $this->out($this->getHelp());
99                         return 0;
100                 }
101
102                 if ($this->appMode->isInstall()) {
103                         throw new RuntimeException('Database isn\'t ready or populated yet');
104                 }
105
106                 $command = $this->getArgument(0);
107
108                 switch ($command) {
109                         case 'password':
110                                 return $this->password();
111                         case 'add':
112                                 return $this->addUser();
113                         case 'allow':
114                                 return $this->pendingUser(true);
115                         case 'deny':
116                                 return $this->pendingUser(false);
117                         case 'block':
118                                 return $this->blockUser(true);
119                         case 'unblock':
120                                 return $this->blockUser(false);
121                         case 'delete':
122                                 return $this->deleteUser();
123                         case 'list':
124                                 return $this->listUser();
125                         default:
126                                 throw new \Asika\SimpleConsole\CommandArgsException('Wrong command.');
127                 }
128         }
129
130         /**
131          * Sets a new password
132          *
133          * @return int Return code of this command
134          *
135          * @throws \Exception
136          */
137         private function password()
138         {
139                 $nick = $this->getArgument(1);
140
141                 $user = $this->dba->selectFirst('user', ['uid'], ['nickname' => $nick]);
142                 if (!$this->dba->isResult($user)) {
143                         throw new RuntimeException($this->l10n->t('User not found'));
144                 }
145
146                 $password = $this->getArgument(2);
147
148                 if (is_null($password)) {
149                         $this->out($this->l10n->t('Enter new password: '), false);
150                         $password = CliPrompt::hiddenPrompt(true);
151                 }
152
153                 try {
154                         $result = UserModel::updatePassword($user['uid'], $password);
155
156                         if (!$this->dba->isResult($result)) {
157                                 throw new \Exception($this->l10n->t('Password update failed. Please try again.'));
158                         }
159
160                         $this->out($this->l10n->t('Password changed.'));
161                 } catch (\Exception $e) {
162                         throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
163                 }
164
165                 return 0;
166         }
167
168         /**
169          * Adds a new user based on given console arguments
170          *
171          * @return bool True, if the command was successful
172          * @throws \ErrorException
173          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
174          * @throws \ImagickException
175          */
176         private function addUser()
177         {
178                 $name  = $this->getArgument(1);
179                 $nick  = $this->getArgument(2);
180                 $email = $this->getArgument(3);
181                 $lang  = $this->getArgument(4);
182
183                 if (empty($name)) {
184                         $this->out($this->l10n->t('Enter user name: '));
185                         $name = CliPrompt::prompt();
186                         if (empty($name)) {
187                                 throw new RuntimeException('A name must be set.');
188                         }
189                 }
190
191                 if (empty($nick)) {
192                         $this->out($this->l10n->t('Enter user nickname: '));
193                         $nick = CliPrompt::prompt();
194                         if (empty($nick)) {
195                                 throw new RuntimeException('A nick name must be set.');
196                         }
197                 }
198
199                 if (empty($email)) {
200                         $this->out($this->l10n->t('Enter user email address: '));
201                         $email = CliPrompt::prompt();
202                         if (empty($email)) {
203                                 throw new RuntimeException('A email address must be set.');
204                         }
205                 }
206
207                 if (empty($lang)) {
208                         $this->out($this->l10n->t('Enter a language (optional): '));
209                         $lang = CliPrompt::prompt();
210                 }
211
212                 if (empty($lang)) {
213                         return UserModel::createMinimal($name, $email, $nick);
214                 } else {
215                         return UserModel::createMinimal($name, $email, $nick, $lang);
216                 }
217         }
218
219         /**
220          * Allows or denys a user based on it's nickname
221          *
222          * @param bool $allow True, if the pending user is allowed, false if denies
223          *
224          * @return bool True, if allow was successful
225          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
226          */
227         private function pendingUser(bool $allow = true)
228         {
229                 $nick = $this->getArgument(1);
230
231                 if (!$nick) {
232                         $this->out($this->l10n->t('Enter user nickname: '));
233                         $nick = CliPrompt::prompt();
234                         if (empty($nick)) {
235                                 throw new RuntimeException('A nick name must be set.');
236                         }
237                 }
238
239                 $user = $this->dba->selectFirst('user', ['uid'], ['nickname' => $nick]);
240                 if (empty($user)) {
241                         throw new RuntimeException($this->l10n->t('User not found'));
242                 }
243
244                 $pending = Register::getPendingForUser($user['uid'] ?? 0);
245                 if (empty($pending)) {
246                         throw new RuntimeException($this->l10n->t('User is not pending.'));
247                 }
248
249                 return ($allow) ? UserModel::allow($pending['hash']) : UserModel::deny($pending['hash']);
250         }
251
252         /**
253          * Blocks/unblocks a user
254          *
255          * @param bool $block True, if the given user should get blocked
256          *
257          * @return bool True, if the command was successful
258          * @throws \Exception
259          */
260         private function blockUser(bool $block = true)
261         {
262                 $nick = $this->getArgument(1);
263
264                 if (!$nick) {
265                         $this->out($this->l10n->t('Enter user nickname: '));
266                         $nick = CliPrompt::prompt();
267                         if (empty($nick)) {
268                                 throw new RuntimeException('A nick name must be set.');
269                         }
270                 }
271
272                 $user = $this->dba->selectFirst('user', ['uid'], ['nickname' => $nick]);
273                 if (empty($user)) {
274                         throw new RuntimeException($this->l10n->t('User not found'));
275                 }
276
277                 return $block ? UserModel::block($user['uid'] ?? 0) : UserModel::block($user['uid'] ?? 0, false);
278         }
279
280         /**
281          * Deletes a user
282          *
283          * @return bool True, if the delete was successful
284          * @throws \Exception
285          */
286         private function deleteUser()
287         {
288                 $nick = $this->getArgument(1);
289
290                 if (!$nick) {
291                         $this->out($this->l10n->t('Enter user nickname: '));
292                         $nick = CliPrompt::prompt();
293                         if (empty($nick)) {
294                                 throw new RuntimeException('A nick name must be set.');
295                         }
296                 }
297
298                 $user = $this->dba->selectFirst('user', ['uid'], ['nickname' => $nick]);
299                 if (empty($user)) {
300                         throw new RuntimeException($this->l10n->t('User not found'));
301                 }
302
303                 if (!$this->getOption('q')) {
304                         $this->out($this->l10n->t('Type "yes" to delete %s', $nick));
305                         if (CliPrompt::prompt() !== 'yes') {
306                                 throw new RuntimeException('Delete abort.');
307                         }
308                 }
309
310                 return UserModel::remove($user['uid'] ?? -1);
311         }
312
313         /**
314          * List user of the current node
315          *
316          * @return bool True, if the command was successful
317          */
318         private function listUser()
319         {
320                 $subCmd = $this->getArgument(1);
321                 $start = $this->getArgument(2, 0);
322                 $count = $this->getArgument(3, Pager::ITEMS_PER_PAGE);
323
324                 $table = new Console_Table();
325
326                 switch ($subCmd) {
327                         case 'pending':
328                                 $table->setHeaders(['Nick', 'Name', 'URL', 'E-Mail', 'Register Date', 'Comment']);
329                                 $pending = Register::getPending($start, $count);
330                                 foreach ($pending as $contact) {
331                                         $table->addRow([
332                                                 $contact['nick'],
333                                                 $contact['name'],
334                                                 $contact['url'],
335                                                 $contact['email'],
336                                                 $contact['created'],
337                                                 $contact['note'],
338                                         ]);
339                                 }
340                                 $this->out($table->getTable());
341                                 return true;
342                         case 'all':
343                         default:
344                                 $table->setHeaders(['Nick', 'Name', 'URL', 'E-Mail', 'Register Date', 'Comment']);
345                                 $contacts = UserModel::getUsers($start, $count);
346                                 foreach ($contacts as $contact) {
347                                         $table->addRow([
348                                                 $contact['nick'],
349                                                 $contact['name'],
350                                                 $contact['url'],
351                                                 $contact['email'],
352                                                 $contact['created'],
353                                                 $contact['note'],
354                                         ]);
355                                 }
356                                 $this->out($table->getTable());
357                                 return true;
358                 }
359         }
360 }