]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/RequireValidatedEmail/RequireValidatedEmailPlugin.php
Merge branch 'statusnetworkapi' into 1.0.x
[quix0rs-gnu-social.git] / plugins / RequireValidatedEmail / RequireValidatedEmailPlugin.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * Plugin that requires the user to have a validated email address before they
6  * can post notices
7  *
8  * PHP version 5
9  *
10  * LICENCE: This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * @category  Plugin
24  * @package   StatusNet
25  * @author    Craig Andrews <candrews@integralblue.com>
26  * @author    Brion Vibber <brion@status.net>
27  * @author    Evan Prodromou <evan@status.net>
28  * @copyright 2011 StatusNet Inc. http://status.net/
29  * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
30  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
31  * @link      http://status.net/
32  */
33
34 if (!defined('STATUSNET') && !defined('LACONICA')) {
35     exit(1);
36 }
37
38 /**
39  * Plugin for requiring a validated email before posting.
40  *
41  * Enable this plugin using addPlugin('RequireValidatedEmail');
42  *
43  * @category  Plugin
44  * @package   StatusNet
45  * @author    Craig Andrews <candrews@integralblue.com>
46  * @author    Brion Vibber <brion@status.net>
47  * @author    Evan Prodromou <evan@status.net>
48  * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
49  * @copyright 2009-2010 StatusNet, Inc.
50  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
51  * @link      http://status.net/
52  */
53 class RequireValidatedEmailPlugin extends Plugin
54 {
55     /**
56      * Users created before this time will be grandfathered in
57      * without the validation requirement.
58      */
59     public $grandfatherCutoff = null;
60
61     /**
62      * If OpenID plugin is installed, users with a verified OpenID
63      * association whose provider URL matches one of these regexes
64      * will be considered to be sufficiently valid for our needs.
65      *
66      * For example, to trust WikiHow and Wikipedia OpenID users:
67      *
68      * addPlugin('RequireValidatedEmailPlugin', array(
69      *    'trustedOpenIDs' => array(
70      *        '!^http://\w+\.wikihow\.com/!',
71      *        '!^http://\w+\.wikipedia\.org/!',
72      *    ),
73      * ));
74      */
75     public $trustedOpenIDs = array();
76
77     /**
78      * Whether or not to disallow login for unvalidated users.
79      */
80     public $disallowLogin = false;
81
82     function onAutoload($cls)
83     {
84         $dir = dirname(__FILE__);
85
86         switch ($cls)
87         {
88         case 'ConfirmfirstemailAction':
89             include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
90             return false;
91         default:
92             return true;
93         }
94     }
95
96     function onRouterInitialized($m)
97     {
98         $m->connect('main/confirmfirst/:code',
99                     array('action' => 'confirmfirstemail'));
100         return true;
101     }
102
103     /**
104      * Event handler for notice saves; rejects the notice
105      * if user's address isn't validated.
106      *
107      * @param Notice $notice The notice being saved
108      *
109      * @return bool hook result code
110      */
111     function onStartNoticeSave($notice)
112     {
113         $user = User::staticGet('id', $notice->profile_id);
114         if (!empty($user)) { // it's a remote notice
115             if (!$this->validated($user)) {
116                 // TRANS: Client exception thrown when trying to post notices before validating an e-mail address.
117                 $msg = _m('You must validate your email address before posting.');
118                 throw new ClientException($msg);
119             }
120         }
121         return true;
122     }
123
124     /**
125      * Event handler for registration attempts; rejects the registration
126      * if email field is missing.
127      *
128      * @param Action $action Action being executed
129      *
130      * @return bool hook result code
131      */
132     function onStartRegisterUser(&$user, &$profile)
133     {
134         $email = $user->email;
135
136         if (empty($email)) {
137             // TRANS: Client exception thrown when trying to register without providing an e-mail address.
138             throw new ClientException(_m('You must provide an email address to register.'));
139         }
140
141         return true;
142     }
143
144     /**
145      * Check if a user has a validated email address or has been
146      * otherwise grandfathered in.
147      *
148      * @param User $user User to valide
149      *
150      * @return bool
151      */
152     protected function validated($user)
153     {
154         // The email field is only stored after validation...
155         // Until then you'll find them in confirm_address.
156         $knownGood = !empty($user->email) ||
157           $this->grandfathered($user) ||
158           $this->hasTrustedOpenID($user);
159
160         // Give other plugins a chance to override, if they can validate
161         // that somebody's ok despite a non-validated email.
162
163         // @todo FIXME: This isn't how to do it! Use Start*/End* instead
164         Event::handle('RequireValidatedEmailPlugin_Override',
165                       array($user, &$knownGood));
166
167         return $knownGood;
168     }
169
170     /**
171      * Check if a user was created before the grandfathering cutoff.
172      * If so, we won't need to check for validation.
173      *
174      * @param User $user User to check
175      *
176      * @return bool true if user is grandfathered
177      */
178     protected function grandfathered($user)
179     {
180         if ($this->grandfatherCutoff) {
181             $created = strtotime($user->created . " GMT");
182             $cutoff  = strtotime($this->grandfatherCutoff);
183             if ($created < $cutoff) {
184                 return true;
185             }
186         }
187         return false;
188     }
189
190     /**
191      * Override for RequireValidatedEmail plugin. If we have a user who's
192      * not validated an e-mail, but did come from a trusted provider,
193      * we'll consider them ok.
194      *
195      * @param User $user User to check
196      *
197      * @return bool true if user has a trusted OpenID.
198      */
199     function hasTrustedOpenID($user)
200     {
201         if ($this->trustedOpenIDs && class_exists('User_openid')) {
202             foreach ($this->trustedOpenIDs as $regex) {
203                 $oid = new User_openid();
204
205                 $oid->user_id = $user->id;
206
207                 $oid->find();
208                 while ($oid->fetch()) {
209                     if (preg_match($regex, $oid->canonical)) {
210                         return true;
211                     }
212                 }
213             }
214         }
215         return false;
216     }
217
218     /**
219      * Add version information for this plugin.
220      *
221      * @param array &$versions Array of associative arrays of version data
222      *
223      * @return boolean hook value
224      */
225     function onPluginVersion(&$versions)
226     {
227         $versions[] =
228           array('name' => 'Require Validated Email',
229                 'version' => STATUSNET_VERSION,
230                 'author' => 'Craig Andrews, '.
231                 'Evan Prodromou, '.
232                 'Brion Vibber',
233                 'homepage' =>
234                 'http://status.net/wiki/Plugin:RequireValidatedEmail',
235                 'rawdescription' =>
236                 // TRANS: Plugin description.
237                 _m('Disables posting without a validated email address.'));
238
239         return true;
240     }
241
242     /**
243      * Hide the notice form if the user isn't able to post.
244      *
245      * @param Action $action action being shown
246      *
247      * @return boolean hook value
248      */
249     function onStartShowNoticeForm($action)
250     {
251         $user = common_current_user();
252         if (!empty($user)) { // it's a remote notice
253             if (!$this->validated($user)) {
254                 return false;
255             }
256         }
257         return true;
258     }
259
260     /**
261      * Prevent unvalidated folks from creating spam groups.
262      *
263      * @param Profile $profile User profile we're checking
264      * @param string $right rights key
265      * @param boolean $result if overriding, set to true/false has right
266      * @return boolean hook result value
267      */
268     function onUserRightsCheck(Profile $profile, $right, &$result)
269     {
270         if ($right == Right::CREATEGROUP ||
271             ($this->disallowLogin && ($right == Right::WEBLOGIN || $right == Right::API))) {
272             $user = User::staticGet('id', $profile->id);
273             if ($user && !$this->validated($user)) {
274                 $result = false;
275                 return false;
276             }
277         }
278         return true;
279     }
280
281     function onLoginAction($action, &$login)
282     {
283         if ($action == 'confirmfirstemail') {
284             $login = true;
285             return false;
286         }
287         return true;
288     }
289 }