GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 221cb7...4c749c )
by Christian
04:35 queued 02:34
created

RegistrationModel::validateUserEmail()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 22
rs 8.9197
cc 4
eloc 11
nc 4
nop 2
1
<?php
2
3
/**
4
 * Class RegistrationModel
5
 *
6
 * Everything registration-related happens here.
7
 */
8
class RegistrationModel
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
9
{
10
	/**
11
	 * Handles the entire registration process for DEFAULT users (not for people who register with
12
	 * 3rd party services, like facebook) and creates a new user in the database if everything is fine
13
	 *
14
	 * @return boolean Gives back the success status of the registration
15
	 */
16
	public static function registerNewUser()
17
	{
18
		// clean the input
19
		$user_name = strip_tags(Request::post('user_name'));
20
		$user_email = strip_tags(Request::post('user_email'));
21
		$user_email_repeat = strip_tags(Request::post('user_email_repeat'));
22
		$user_password_new = Request::post('user_password_new');
23
		$user_password_repeat = Request::post('user_password_repeat');
24
25
		// stop registration flow if registrationInputValidation() returns false (= anything breaks the input check rules)
26
		$validation_result = self::registrationInputValidation(Request::post('captcha'), $user_name, $user_password_new, $user_password_repeat, $user_email, $user_email_repeat);
27
		if (!$validation_result) {
28
			return false;
29
		}
30
31
		// crypt the password with the PHP 5.5's password_hash() function, results in a 60 character hash string.
32
		// @see php.net/manual/en/function.password-hash.php for more, especially for potential options
33
		$user_password_hash = password_hash($user_password_new, PASSWORD_DEFAULT);
34
35
        // make return a bool variable, so both errors can come up at once if needed
36
        $return = true;
37
38
		// check if username already exists
39
		if (UserModel::doesUsernameAlreadyExist($user_name)) {
40
			Session::add('feedback_negative', Text::get('FEEDBACK_USERNAME_ALREADY_TAKEN'));
41
			$return = false;
42
		}
43
44
		// check if email already exists
45
		if (UserModel::doesEmailAlreadyExist($user_email)) {
46
			Session::add('feedback_negative', Text::get('FEEDBACK_USER_EMAIL_ALREADY_TAKEN'));
47
			$return = false;
48
		}
49
50
        // if Username or Email were false, return false
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
51
        if (!$return) return false;
52
53
		// generate random hash for email verification (40 char string)
54
		$user_activation_hash = sha1(uniqid(mt_rand(), true));
55
56
		// write user data to database
57
		if (!self::writeNewUserToDatabase($user_name, $user_password_hash, $user_email, time(), $user_activation_hash)) {
58
			Session::add('feedback_negative', Text::get('FEEDBACK_ACCOUNT_CREATION_FAILED'));
59
            return false; // no reason not to return false here
60
		}
61
62
		// get user_id of the user that has been created, to keep things clean we DON'T use lastInsertId() here
63
		$user_id = UserModel::getUserIdByUsername($user_name);
64
65
		if (!$user_id) {
66
			Session::add('feedback_negative', Text::get('FEEDBACK_UNKNOWN_ERROR'));
67
			return false;
68
		}
69
70
		// send verification email
71
		if (self::sendVerificationEmail($user_id, $user_email, $user_activation_hash)) {
72
			Session::add('feedback_positive', Text::get('FEEDBACK_ACCOUNT_SUCCESSFULLY_CREATED'));
73
			return true;
74
		}
75
76
		// if verification email sending failed: instantly delete the user
77
		self::rollbackRegistrationByUserId($user_id);
78
		Session::add('feedback_negative', Text::get('FEEDBACK_VERIFICATION_MAIL_SENDING_FAILED'));
79
		return false;
80
	}
81
82
	/**
83
	 * Validates the registration input
84
	 *
85
	 * @param $captcha
86
	 * @param $user_name
87
	 * @param $user_password_new
88
	 * @param $user_password_repeat
89
	 * @param $user_email
90
	 * @param $user_email_repeat
91
	 *
92
	 * @return bool
93
	 */
94
	public static function registrationInputValidation($captcha, $user_name, $user_password_new, $user_password_repeat, $user_email, $user_email_repeat)
95
	{
96
        $return = true;
97
98
		// perform all necessary checks
99
		if (!CaptchaModel::checkCaptcha($captcha)) {
100
			Session::add('feedback_negative', Text::get('FEEDBACK_CAPTCHA_WRONG'));
101
            $return = false;
102
		}
103
104
        // if username, email and password are all correctly validated, but make sure they all run on first sumbit
105
        if (self::validateUserName($user_name) AND self::validateUserEmail($user_email, $user_email_repeat) AND self::validateUserPassword($user_password_new, $user_password_repeat) AND $return) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
106
            return true;
107
        }
108
109
		// otherwise, return false
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
110
		return false;
111
	}
112
113
    /**
114
     * Validates the username
115
     *
116
     * @param $user_name
117
     * @return bool
118
     */
119
    public static function validateUserName($user_name)
120
    {
121
        if (empty($user_name)) {
122
            Session::add('feedback_negative', Text::get('FEEDBACK_USERNAME_FIELD_EMPTY'));
123
            return false;
124
        }
125
126
        // if username is too short (2), too long (64) or does not fit the pattern (aZ09)
127
        if (!preg_match('/^[a-zA-Z0-9]{2,64}$/', $user_name)) {
128
            Session::add('feedback_negative', Text::get('FEEDBACK_USERNAME_DOES_NOT_FIT_PATTERN'));
129
            return false;
130
        }
131
132
        return true;
133
    }
134
135
    /**
136
     * Validates the email
137
     *
138
     * @param $user_email
139
	 * @param $user_email_repeat
140
     * @return bool
141
     */
142
    public static function validateUserEmail($user_email, $user_email_repeat)
143
    {
144
        if (empty($user_email)) {
145
            Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_FIELD_EMPTY'));
146
            return false;
147
        }
148
149
		if ($user_email !== $user_email_repeat) {
150
			Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_REPEAT_WRONG'));
151
			return false;
152
		}
153
154
        // validate the email with PHP's internal filter
155
        // side-fact: Max length seems to be 254 chars
156
        // @see http://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
157
        if (!filter_var($user_email, FILTER_VALIDATE_EMAIL)) {
158
            Session::add('feedback_negative', Text::get('FEEDBACK_EMAIL_DOES_NOT_FIT_PATTERN'));
159
            return false;
160
        }
161
162
        return true;
163
    }
164
165
    /**
166
     * Validates the password
167
     *
168
     * @param $user_password_new
169
     * @param $user_password_repeat
170
     * @return bool
171
     */
172
    public static function validateUserPassword($user_password_new, $user_password_repeat)
173
    {
174
        if (empty($user_password_new) OR empty($user_password_repeat)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
175
            Session::add('feedback_negative', Text::get('FEEDBACK_PASSWORD_FIELD_EMPTY'));
176
            return false;
177
        }
178
179
        if ($user_password_new !== $user_password_repeat) {
180
            Session::add('feedback_negative', Text::get('FEEDBACK_PASSWORD_REPEAT_WRONG'));
181
            return false;
182
        }
183
184
        if (strlen($user_password_new) < 6) {
185
            Session::add('feedback_negative', Text::get('FEEDBACK_PASSWORD_TOO_SHORT'));
186
            return false;
187
        }
188
189
        return true;
190
    }
191
192
	/**
193
	 * Writes the new user's data to the database
194
	 *
195
	 * @param $user_name
196
	 * @param $user_password_hash
197
	 * @param $user_email
198
	 * @param $user_creation_timestamp
199
	 * @param $user_activation_hash
200
	 *
201
	 * @return bool
202
	 */
203
	public static function writeNewUserToDatabase($user_name, $user_password_hash, $user_email, $user_creation_timestamp, $user_activation_hash)
204
	{
205
		$database = DatabaseFactory::getFactory()->getConnection();
206
207
		// write new users data into database
208
		$sql = "INSERT INTO users (user_name, user_password_hash, user_email, user_creation_timestamp, user_activation_hash, user_provider_type)
209
                    VALUES (:user_name, :user_password_hash, :user_email, :user_creation_timestamp, :user_activation_hash, :user_provider_type)";
210
		$query = $database->prepare($sql);
211
		$query->execute(array(':user_name' => $user_name,
212
		                      ':user_password_hash' => $user_password_hash,
213
		                      ':user_email' => $user_email,
214
		                      ':user_creation_timestamp' => $user_creation_timestamp,
215
		                      ':user_activation_hash' => $user_activation_hash,
216
		                      ':user_provider_type' => 'DEFAULT'));
217
		$count =  $query->rowCount();
218
		if ($count == 1) {
219
			return true;
220
		}
221
222
		return false;
223
	}
224
225
	/**
226
	 * Deletes the user from users table. Currently used to rollback a registration when verification mail sending
227
	 * was not successful.
228
	 *
229
	 * @param $user_id
230
	 */
231
	public static function rollbackRegistrationByUserId($user_id)
232
	{
233
		$database = DatabaseFactory::getFactory()->getConnection();
234
235
		$query = $database->prepare("DELETE FROM users WHERE user_id = :user_id");
236
		$query->execute(array(':user_id' => $user_id));
237
	}
238
239
	/**
240
	 * Sends the verification email (to confirm the account).
241
	 * The construction of the mail $body looks weird at first, but it's really just a simple string.
242
	 *
243
	 * @param int $user_id user's id
244
	 * @param string $user_email user's email
245
	 * @param string $user_activation_hash user's mail verification hash string
246
	 *
247
	 * @return boolean gives back true if mail has been sent, gives back false if no mail could been sent
248
	 */
249
	public static function sendVerificationEmail($user_id, $user_email, $user_activation_hash)
250
	{
251
		$body = Config::get('EMAIL_VERIFICATION_CONTENT') . Config::get('URL') . Config::get('EMAIL_VERIFICATION_URL')
252
		        . '/' . urlencode($user_id) . '/' . urlencode($user_activation_hash);
253
254
		$mail = new Mail;
255
		$mail_sent = $mail->sendMail($user_email, Config::get('EMAIL_VERIFICATION_FROM_EMAIL'),
256
			Config::get('EMAIL_VERIFICATION_FROM_NAME'), Config::get('EMAIL_VERIFICATION_SUBJECT'), $body
257
		);
258
259
		if ($mail_sent) {
260
			Session::add('feedback_positive', Text::get('FEEDBACK_VERIFICATION_MAIL_SENDING_SUCCESSFUL'));
261
			return true;
262
		} else {
263
			Session::add('feedback_negative', Text::get('FEEDBACK_VERIFICATION_MAIL_SENDING_ERROR') . $mail->getError() );
264
			return false;
265
		}
266
	}
267
268
	/**
269
	 * checks the email/verification code combination and set the user's activation status to true in the database
270
	 *
271
	 * @param int $user_id user id
272
	 * @param string $user_activation_verification_code verification token
273
	 *
274
	 * @return bool success status
275
	 */
276
	public static function verifyNewUser($user_id, $user_activation_verification_code)
277
	{
278
		$database = DatabaseFactory::getFactory()->getConnection();
279
280
		$sql = "UPDATE users SET user_active = 1, user_activation_hash = NULL
281
                WHERE user_id = :user_id AND user_activation_hash = :user_activation_hash LIMIT 1";
282
		$query = $database->prepare($sql);
283
		$query->execute(array(':user_id' => $user_id, ':user_activation_hash' => $user_activation_verification_code));
284
285
		if ($query->rowCount() == 1) {
286
			Session::add('feedback_positive', Text::get('FEEDBACK_ACCOUNT_ACTIVATION_SUCCESSFUL'));
287
			return true;
288
		}
289
290
		Session::add('feedback_negative', Text::get('FEEDBACK_ACCOUNT_ACTIVATION_FAILED'));
291
		return false;
292
	}
293
}
294