]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/RegisterThrottle/RegisterThrottlePlugin.php
Merge branch 'master' into nightly
[quix0rs-gnu-social.git] / plugins / RegisterThrottle / RegisterThrottlePlugin.php
index 05709b7807b2cc408d34168409b3cfb2d05ec3ee..5b999a4370cccd95bc9a752707f7323b1d2e21f4 100644 (file)
@@ -28,9 +28,7 @@
  * @link      http://status.net/
  */
 
-if (!defined('STATUSNET')) {
-    exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
 
 /**
  * Throttle registration by IP address
@@ -52,11 +50,29 @@ class RegisterThrottlePlugin extends Plugin
      *
      * Default is 3 registrations per hour, 5 per day, 10 per week.
      */
-
     public $regLimits = array(604800 => 10, // per week
                               86400 => 5, // per day
                               3600 => 3); // per hour
 
+    /**
+     * Disallow registration if a silenced user has registered from
+     * this IP address.
+     */
+    public $silenced = true;
+
+    /**
+     * Auto-silence all other users from the same registration_ip
+     * as the one being silenced. Caution: Many users may come from
+     * the same IP (even entire countries) without having any sort
+     * of relevant connection for moderation.
+     */
+    public $auto_silence_by_ip = false;
+
+    /**
+     * Whether we're enabled; prevents recursion.
+     */
+    static private $enabled = true;
+
     /**
      * Database schema setup
      *
@@ -64,42 +80,20 @@ class RegisterThrottlePlugin extends Plugin
      *
      * @return boolean hook value; true means continue processing, false means stop.
      */
-
-    function onCheckSchema()
+    public function onCheckSchema()
     {
         $schema = Schema::get();
 
         // For storing user-submitted flags on profiles
-
-        $schema->ensureTable('registration_ip',
-                             array(new ColumnDef('user_id', 'integer', null,
-                                                 false, 'PRI'),
-                                   new ColumnDef('ipaddress', 'varchar', 15, false, 'MUL'),
-                                   new ColumnDef('created', 'timestamp', null, false, 'MUL')));
-
+        $schema->ensureTable('registration_ip', Registration_ip::schemaDef());
         return true;
     }
 
-    /**
-     * Load related modules when needed
-     *
-     * @param string $cls Name of the class to be loaded
-     *
-     * @return boolean hook value; true means continue processing, false means stop.
-     */
-
-    function onAutoload($cls)
+    public function onRouterInitialized(URLMapper $m)
     {
-        $dir = dirname(__FILE__);
-
-        switch ($cls)
-        {
-        case 'Registration_ip':
-            include_once $dir . '/'.$cls.'.php';
-            return false;
-        default:
-            return true;
-        }
+        $m->connect('main/ipregistrations/:ipaddress',
+                    array('action'      => 'ipregistrations'),
+                    array('ipaddress'   => '[0-9a-f\.\:]+'));
     }
 
     /**
@@ -111,14 +105,13 @@ class RegisterThrottlePlugin extends Plugin
      * @param Action $action Action that is being executed
      *
      * @return boolean hook value
-     *
      */
-
-    function onStartRegistrationTry($action)
+    public function onStartRegistrationTry($action)
     {
         $ipaddress = $this->_getIpAddress();
 
         if (empty($ipaddress)) {
+            // TRANS: Server exception thrown when no IP address can be found for a registation attempt.
             throw new ServerException(_m('Cannot find IP address.'));
         }
 
@@ -134,7 +127,21 @@ class RegisterThrottlePlugin extends Plugin
                 $now     = time();
                 $this->debug("Comparing {$regtime} to {$now}");
                 if ($now - $regtime < $seconds) {
-                    throw new Exception(_("Too many registrations. Take a break and try again later."));
+                    // TRANS: Exception thrown when too many user have registered from one IP address within a given time frame.
+                    throw new Exception(_m('Too many registrations. Take a break and try again later.'));
+                }
+            }
+        }
+
+        // Check for silenced users
+
+        if ($this->silenced) {
+            $ids = Registration_ip::usersByIP($ipaddress);
+            foreach ($ids as $id) {
+                $profile = Profile::getKV('id', $id);
+                if ($profile && $profile->isSilenced()) {
+                    // TRANS: Exception thrown when attempting to register from an IP address from which silenced users have registered.
+                    throw new Exception(_m('A banned user has registered from this address.'));
                 }
             }
         }
@@ -142,39 +149,79 @@ class RegisterThrottlePlugin extends Plugin
         return true;
     }
 
+    function onEndShowSections(Action $action)
+    {
+        if (!$action instanceof ShowstreamAction) {
+            // early return for actions we're not interested in
+            return true;
+        }
+
+        $target = $action->getTarget();
+        if (!$target->isSilenced()) {
+            // Only show the IP of users who are not silenced.
+            return true;
+        }
+
+        $scoped = $action->getScoped();
+        if (!$scoped->hasRight(Right::SILENCEUSER)) {
+            // only show registration IP if we have the right to silence users
+            return true;
+        }
+
+        $ri = Registration_ip::getKV('user_id', $target->getID());
+        $ipaddress = null;
+        if ($ri instanceof Registration_ip) {
+            $ipaddress = $ri->ipaddress;
+            unset($ri);
+        }
+
+        $action->elementStart('div', array('id' => 'entity_mod_log',
+                                           'class' => 'section'));
+
+        $action->element('h2', null, _('Registration IP'));
+
+        // TRANS: Label for the information about which IP a users registered from.
+        $action->element('strong', null, _('Registered from:'));
+        $el = 'span';
+        $attrs = ['class'=>'ipaddress'];
+        if (!is_null($ipaddress)) {
+            $el = 'a';
+            $attrs['href'] = common_local_url('ipregistrations', array('ipaddress'=>$ipaddress));
+        }
+        $action->element($el, $attrs,
+                            // TRANS: Unknown IP address.
+                            $ipaddress ?: _('unknown'));
+
+        $action->elementEnd('div');
+    }
+
     /**
-     * Called after someone registers.
+     * Called after someone registers, by any means.
      *
      * We record the successful registration and IP address.
      *
-     * @param Action $action Action that is being executed
+     * @param Profile $profile new user's profile
      *
      * @return boolean hook value
-     *
      */
-
-    function onEndRegistrationTry($action)
+    public function onEndUserRegister(Profile $profile)
     {
         $ipaddress = $this->_getIpAddress();
 
         if (empty($ipaddress)) {
-            throw new ServerException(_m('Cannot find IP address.'));
-        }
-
-        $user = common_current_user();
-
-        if (empty($user)) {
-            throw new ServerException(_m('Cannot find user after successful registration.'));
+            // User registration can happen from command-line scripts etc.
+            return true;
         }
 
         $reg = new Registration_ip();
 
-        $reg->user_id   = $user->id;
-        $reg->ipaddress = $ipaddress;
+        $reg->user_id   = $profile->getID();
+        $reg->ipaddress = mb_strtolower($ipaddress);
+        $reg->created   = common_sql_now();
 
         $result = $reg->insert();
 
-        if (!$result) {
+        if ($result === false) {
             common_log_db_error($reg, 'INSERT', __FILE__);
             // @todo throw an exception?
         }
@@ -189,15 +236,15 @@ class RegisterThrottlePlugin extends Plugin
      *
      * @return boolean hook value
      */
-
-    function onPluginVersion(&$versions)
+    public function onPluginVersion(array &$versions)
     {
         $versions[] = array('name' => 'RegisterThrottle',
-                            'version' => STATUSNET_VERSION,
+                            'version' => GNUSOCIAL_VERSION,
                             'author' => 'Evan Prodromou',
-                            'homepage' => 'http://status.net/wiki/Plugin:RegisterThrottle',
+                            'homepage' => 'https://git.gnu.io/gnu/gnu-social/tree/master/plugins/RegisterThrottle',
                             'description' =>
-                            _m('Throttles excessive registration from a single IP.'));
+                            // TRANS: Plugin description.
+                            _m('Throttles excessive registration from a single IP address.'));
         return true;
     }
 
@@ -206,10 +253,10 @@ class RegisterThrottlePlugin extends Plugin
      *
      * @return string IP address or null if not found.
      */
-
     private function _getIpAddress()
     {
         $keys = array('HTTP_X_FORWARDED_FOR',
+                      'HTTP_X_CLIENT',
                       'CLIENT-IP',
                       'REMOTE_ADDR');
 
@@ -230,7 +277,6 @@ class RegisterThrottlePlugin extends Plugin
      *
      * @return Registration_ip nth registration or null if not found.
      */
-
     private function _getNthReg($ipaddress, $n)
     {
         $reg = new Registration_ip();
@@ -246,4 +292,62 @@ class RegisterThrottlePlugin extends Plugin
             return null;
         }
     }
+
+    /**
+     * When silencing a user, silence all other users registered from that IP
+     * address.
+     *
+     * @param Profile $profile Person getting a new role
+     * @param string  $role    Role being assigned like 'moderator' or 'silenced'
+     *
+     * @return boolean hook value
+     */
+    public function onEndGrantRole($profile, $role)
+    {
+        if (!self::$enabled) {
+            return true;
+        }
+
+        if ($role !== Profile_role::SILENCED) {
+            return true;
+        }
+
+        if (!$this->auto_silence_by_ip) {
+            return true;
+        }
+
+        $ri = Registration_ip::getKV('user_id', $profile->getID());
+
+        if (empty($ri)) {
+            return true;
+        }
+
+        $ids = Registration_ip::usersByIP($ri->ipaddress);
+
+        foreach ($ids as $id) {
+            if ($id == $profile->getID()) {
+                continue;
+            }
+
+            try {
+                $other = Profile::getByID($id);
+            } catch (NoResultException $e) {
+                continue;
+            }
+
+            if ($other->isSilenced()) {
+                continue;
+            }
+
+            // 'enabled' here is used to prevent recursion, since
+            // we'll end up in this function again on ->silence()
+            // though I actually think it doesn't matter since we
+            // do this in onEndGrantRole and that means the above
+            // $other->isSilenced() test should've 'continue'd...
+            $old = self::$enabled;
+            self::$enabled = false;
+            $other->silence();
+            self::$enabled = $old;
+        }
+    }
 }