10 Commits 714ab0c872 ... ac654a6b6c

Author SHA1 Message Date
  SENOO, Ken ac654a6b6c Add CHANGELOG 10 months ago
  SENOO, Ken 0558e54545 Add display count on user directory 10 months ago
  SENOO, Ken 32c8f5de68 Support `count` URL query for max value per userdirectory page 10 months ago
  SENOO, Ken 8817c95ba2 Add account/delete API and bulk action 10 months ago
  SENOO, Ken ec6acc4ddb Add account delete API base code 10 months ago
  SENOO, Ken c8d35f5d7e Rename class and date format 10 months ago
  SENOO, Ken d7f9a2e7d7 Add checkbox 11 months ago
  SENOO, Ken d782053817 Add control for common_config('site', 'closed') with apiaccountregister API. 1 year ago
  SENOO, Ken 5386dec03e Add stderr=true for testing with header 1 year ago
  SENOO, Ken 228a5ad078 Update dependency with run 'composer install' 1 year ago

+ 5 - 0
CHANGELOG.md

@@ -2,9 +2,14 @@
 
 ## 2.x.x - YYYY-mm-dd
 
+### Added
+
+- Support bulk action and display count for user directory (/directory/users) <https://imgur.com/gallery/nei6Ij2>. And add account/delete API for bulk spam account deleteion <https://notabug.org/gnusocialjp/gnusocial/issues/20>.
+
 ### Fixed
 
 - Duplicated post with unlike between remote GNU social server ((URL)[https://notabug.org/gnusocialjp/gnusocial/issues/10)]).
+- Add control for common_config('site', 'closed') with apiaccountregister API.
 
 ## 2.0.2 - 2023-08-21
 

+ 116 - 0
actions/apiaccountdelete.php

@@ -0,0 +1,116 @@
+<?php declare(strict_types=1);
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Delete account
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 <http://www.gnu.org/licenses/>.
+ *
+ * @category  API
+ * @package   GNUsocial
+ * @author    SENOO, Ken <develop@senooken.jp>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Delete a account with API.
+ * 
+ * Refer to DeleteuserAction.
+ */
+class ApiAccountDeleteAction extends ApiAuthAction
+{
+    var $user = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    protected function prepare(array $args=array())
+    {
+        if (!parent::prepare($args)) {
+            return false;
+        }
+
+        assert($this->scoped instanceof Profile);
+
+        $profile = $this->getTargetProfile($this->arg('id'));
+        if (empty($profile)) {
+            // TRANS: Client error displayed when trying delete who's profile could not be found.
+            throw new ClientException(_('Could not delete user: user not found.'), 403);
+        }
+        $this->user = $profile->getUser();
+
+        if ($this->user->id === $this->scoped->id) {
+            throw new ClientException('Could not delete self for mistake.', 403);
+        }
+
+        if (!$this->scoped->hasRight(Right::DELETEUSER)) {
+            // TRANS: Client error displayed when trying to delete a user without having the right to delete users.
+            throw new AuthorizationException(_('You cannot delete users.'));
+        }
+
+        // Only administrators can delete other privileged users (such as others who have the right to silence).
+        if ($this->scoped->isPrivileged() && !$this->scoped->hasRole(Profile_role::ADMINISTRATOR)) {
+            // TRANS: Client error displayed when trying to delete a user that has been granted moderation privileges
+            throw new AuthorizationException(_('You cannot delete other privileged users.'));
+        }
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    protected function handle()
+    {
+        parent::handle();
+
+        if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
+            $this->handleDelete();
+        }
+    }
+
+    /**
+     * Actually delete a user.
+     *
+     * @return void
+     */
+    function handleDelete()
+    {
+        if (Event::handle('StartDeleteUser', array($this, $this->user))) {
+            // Mark the account as deleted and shove low-level deletion tasks
+            // to background queues. Removing a lot of posts can take a while...
+            if (!$this->user->hasRole(Profile_role::DELETED)) {
+                $this->user->grantRole(Profile_role::DELETED);
+            }
+
+            $qm = QueueManager::get();
+            $qm->enqueue($this->user, 'deluser');
+
+            Event::handle('EndDeleteUser', array($this, $this->user));
+        }
+    }
+}

+ 6 - 1
actions/apiaccountregister.php

@@ -1,4 +1,4 @@
-<?php
+<?php declare(strict_types=1);
 /**
  * StatusNet, the distributed open-source microblogging tool
  *
@@ -95,6 +95,11 @@ class ApiAccountRegisterAction extends ApiAction
             }
         }
 
+        if (common_config('site', 'closed')) {
+            // TRANS: Client error displayed when trying to register to a closed site.
+            $this->clientError(_('Registration not allowed.'));
+        }
+
         if (common_config('site', 'inviteonly') && empty($this->code)) {
             // TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
             $this->clientError(_('Sorry, only invited people can register.'), 401);

+ 8 - 0
doc-src/twitterapi

@@ -221,6 +221,14 @@ This method is powerful when used in conjunction with users/lookup.
 
 ## Account resources
 
+### account/delete
+
+```
+DELETE /api/account/delete.json?user_id=[id]
+```
+
+Delete account (original).
+
 ### account/verify_credentials
 
 Returns an HTTP 200 OK response code and a representation of the requesting user if

+ 7 - 2
lib/action/action.php

@@ -1792,13 +1792,18 @@ class Action extends HTMLOutputter // lawsuit
      */
     public function pagination(bool $have_before, bool $have_after, int $page, string $action, ?array $args = null): void
     {
+        $count = $this->trimmed('count');
+        if ($count) {
+            $pargs['count'] = $count;
+        }
+
         // Does a little before-after block for next/prev page
         if ($have_before || $have_after) {
             $this->elementStart('ul', ['class' => 'nav',
                 'id' => 'pagination',]);
         }
         if ($have_before) {
-            $pargs = ['page' => $page - 1];
+            $pargs['page'] = $page - 1;
             $this->elementStart('li', ['class' => 'nav_prev']);
             $this->element(
                 'a',
@@ -1811,7 +1816,7 @@ class Action extends HTMLOutputter // lawsuit
             $this->elementEnd('li');
         }
         if ($have_after) {
-            $pargs = ['page' => $page + 1];
+            $pargs['page'] = $page + 1;
             $this->elementStart('li', ['class' => 'nav_next']);
             $this->element(
                 'a',

+ 4 - 5
lib/profile/profilelist.php

@@ -54,13 +54,13 @@ class ProfileList extends Widget
         $this->action = $action;
     }
 
-    function show()
+    function show(int $maxCount = PROFILES_PER_PAGE)
     {
         $cnt = 0;
 
         if (Event::handle('StartProfileList', array($this))) {
             $this->startList();
-            $cnt = $this->showProfiles();
+            $cnt = $this->showProfiles($maxCount);
             $this->endList();
             Event::handle('EndProfileList', array($this));
         }
@@ -78,12 +78,11 @@ class ProfileList extends Widget
         $this->out->elementEnd('ul');
     }
 
-    function showProfiles()
+    function showProfiles(int $count = PROFILES_PER_PAGE)
     {
         $cnt = $this->profile->N;
         $profiles = $this->profile->fetchAll();
-
-        $max = min($cnt, $this->maxProfiles());
+        $max = min($cnt, $count);
 
         for ($i = 0; $i < $max; $i++) {
             $pli = $this->newListItem($profiles[$i]);

+ 1 - 1
lib/util/framework.php

@@ -35,7 +35,7 @@ define('GNUSOCIAL_ENGINE_URL', 'https://gnusocial.rocks/');
 define('GNUSOCIAL_ENGINE_REPO_URL', 'https://notabug.org/diogo/gnu-social/'); // Change to https://git.gnu.io/gnu/gnu-social
 
 define('GNUSOCIAL_BASE_VERSION', '2.0.2');
-define('GNUSOCIAL_LIFECYCLE', 'beta0'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
+define('GNUSOCIAL_LIFECYCLE', 'dev'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release'
 
 define('GNUSOCIAL_VERSION', GNUSOCIAL_BASE_VERSION . '-' . GNUSOCIAL_LIFECYCLE);
 

+ 1 - 1
lib/util/htmloutputter.php

@@ -44,7 +44,7 @@ define('PAGE_TYPE_PREFS', 'text/html');
  * @copyright 2008-2019 Free Software Foundation, Inc http://www.fsf.org
  * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  */
-class htmloutputter extends XMLOutputter
+class HTMLOutputter extends XMLOutputter
 {
     protected $DTD = ['doctype' => 'html',
         'spec'                  => '-//W3C//DTD XHTML 1.0 Strict//EN',

+ 8 - 0
lib/util/router.php

@@ -574,6 +574,14 @@ class Router
                         ['action' => 'ApiAccountRateLimitStatus'],
                         ['format' => '(xml|json)']);
 
+            $m->connect('api/account/delete/:id.:format',
+                        ['action' => 'ApiAccountDelete'],
+                        ['id' => Nickname::INPUT_FMT,
+                         'format' => '(xml|json)']);
+            $m->connect('api/account/delete.:format',
+                         ['action' => 'ApiAccountDelete'],
+                         ['format' => '(xml|json)']);
+
             // blocks
 
             $m->connect('api/blocks/create/:id.:format',

+ 0 - 0
phpunit.xml


Some files were not shown because too many files changed in this diff