2021-07-10 19:18:17 +01:00
< ? php
2021-07-10 18:21:03 -04:00
require_once ( 'includes/common.php' );
2021-07-10 19:18:17 +01:00
require_once ( 'includes/functions.php' );
2021-07-17 12:33:08 -04:00
require_once ( 'includes/passwords.php' );
2021-07-15 12:40:12 -04:00
2021-11-01 16:56:17 -04:00
use PonePaste\Helpers\SessionHelper ;
use PonePaste\Models\User ;
use PonePaste\Models\UserSession ;
2021-07-10 19:18:17 +01:00
// Check if already logged in
2021-07-17 18:17:29 -04:00
if ( $current_user !== null ) {
2021-07-11 12:50:24 -04:00
header ( " Location: ./ " );
2021-07-17 18:17:29 -04:00
die ();
2021-07-10 19:18:17 +01:00
}
2022-03-12 13:56:32 -05:00
updatePageViews ();
2021-07-10 19:18:17 +01:00
2021-07-16 10:32:25 -04:00
if ( isset ( $_POST [ 'forgot' ])) {
if ( ! empty ( $_POST [ 'username' ]) && ! empty ( $_POST [ 'recovery_code' ])) {
$username = trim ( $_POST [ 'username' ]);
$recovery_code = trim ( $_POST [ 'recovery_code' ]);
2021-11-01 16:56:17 -04:00
$user = User :: select ( 'id' , 'recovery_code_hash' )
-> where ( 'username' , $username );
/* see justification below for error-suppression operator */
if ( pp_password_verify ( $_POST [ 'recovery_code' ], @ $user -> recovery_code_hash )) {
2021-07-24 14:45:46 -04:00
$new_password = pp_random_password ();
2021-07-17 12:33:08 -04:00
$new_password_hash = pp_password_hash ( $new_password );
2021-07-16 10:32:25 -04:00
2021-07-24 14:45:46 -04:00
$recovery_code = pp_random_token ();
2021-07-17 12:33:08 -04:00
$new_recovery_code_hash = pp_password_hash ( $recovery_code );
2021-07-16 10:32:25 -04:00
2021-11-01 16:56:17 -04:00
$user -> password = $new_password_hash ;
$user -> recovery_code_hash = $new_recovery_code_hash ;
$user -> save ();
2021-07-16 10:32:25 -04:00
$success = 'Your password has been changed. A new recovery code has also been generated. Please note the recovery code and then sign in with the new password.' ;
} else {
2021-11-01 16:56:17 -04:00
$error = 'Incorrect username or recovery code.' ;
2021-07-16 10:32:25 -04:00
}
} else {
2021-08-26 05:35:21 -04:00
$error = 'All fields must be filled out.' ;
2021-07-15 12:40:12 -04:00
}
2021-07-26 17:42:43 -04:00
} elseif ( isset ( $_POST [ 'signin' ])) { // Login process
2021-07-16 10:32:25 -04:00
if ( ! empty ( $_POST [ 'username' ]) && ! empty ( $_POST [ 'password' ])) {
2021-08-22 22:05:26 -04:00
$remember_me = ( bool ) $_POST [ 'remember_me' ];
2021-07-16 10:32:25 -04:00
$username = trim ( $_POST [ 'username' ]);
2021-11-01 16:56:17 -04:00
$user = User :: select ( 'id' , 'password' , 'banned' )
-> where ( 'username' , $username )
-> first ();
2021-07-24 14:45:46 -04:00
2021-07-17 12:33:08 -04:00
$needs_rehash = false ;
2021-07-24 14:45:46 -04:00
/* This is designed to be a constant time lookup , hence the warning suppression operator so that
2021-11-01 16:56:17 -04:00
* we always call pp_password_verify , even if the user is null .
2021-07-24 14:45:46 -04:00
*/
2021-11-01 16:56:17 -04:00
if ( pp_password_verify ( $_POST [ 'password' ], @ $user -> password , $needs_rehash )) {
2021-07-17 12:33:08 -04:00
if ( $needs_rehash ) {
2021-11-01 16:56:17 -04:00
$user -> password = pp_password_hash ( $_POST [ 'password' ]);
$user -> save ();
2021-07-17 12:33:08 -04:00
}
2021-11-01 16:56:17 -04:00
if ( $user -> banned ) {
2021-07-16 10:32:25 -04:00
// User is banned
2021-08-26 05:35:21 -04:00
$error = 'You are banned.' ;
2021-07-17 12:36:21 -04:00
} else {
2021-07-16 10:32:25 -04:00
// Login successful
2021-11-01 16:56:17 -04:00
$_SESSION [ 'user_id' ] = ( string ) $user -> id ;
2021-07-24 14:45:46 -04:00
if ( $remember_me ) {
$remember_token = pp_random_token ();
2021-07-24 15:12:19 -04:00
$expire_at = ( new DateTime ()) -> add ( new DateInterval ( 'P1Y' ));
2021-07-24 14:45:46 -04:00
2021-11-01 16:56:17 -04:00
$session = new UserSession ([
'user_id' => $user -> id ,
'token' => $remember_token ,
'expire_at' => $expire_at
]);
$session -> save ();
2021-07-24 14:45:46 -04:00
2021-11-01 16:56:17 -04:00
setcookie ( SessionHelper :: REMEMBER_TOKEN_COOKIE , $remember_token , [
2021-08-22 22:05:26 -04:00
'expires' => ( int ) $expire_at -> format ( 'U' ),
2021-07-24 14:45:46 -04:00
'secure' => ! empty ( $_SERVER [ 'HTTPS' ]), /* Local dev environment is non-HTTPS */
'httponly' => true ,
'samesite' => 'Lax'
]);
}
2021-07-16 10:32:25 -04:00
header ( 'Location: ' . $_SERVER [ 'HTTP_REFERER' ]);
exit ();
2021-07-10 19:18:17 +01:00
}
2021-07-15 12:40:12 -04:00
} else {
2021-07-16 10:32:25 -04:00
// Username not found or password incorrect.
2021-08-26 05:35:21 -04:00
$error = 'Incorrect username or password.' ;
2021-07-10 19:18:17 +01:00
}
2021-07-16 10:32:25 -04:00
} else {
2021-08-26 05:35:21 -04:00
$error = 'All fields must be filled out.' ;
2021-07-10 19:18:17 +01:00
}
2021-07-26 17:42:43 -04:00
} elseif ( isset ( $_POST [ 'signup' ])) { // Registration process
2021-11-01 16:56:17 -04:00
$username = trim ( $_POST [ 'username' ]);
2021-07-17 12:33:08 -04:00
$password = pp_password_hash ( $_POST [ 'password' ]);
2021-07-11 12:50:24 -04:00
2021-07-16 10:08:21 -04:00
if ( empty ( $_POST [ 'password' ]) || empty ( $_POST [ 'username' ])) {
2021-08-26 05:35:21 -04:00
$error = 'All fields must be filled out.' ;
} elseif ( strlen ( $username ) > 25 ) {
2022-04-23 18:22:16 -04:00
$error = 'Username too long.' ;
2022-04-20 18:45:29 -04:00
} elseif ( ! preg_match ( '/^[A-Za-z0-9._\\-]+$/' , $username )) {
2021-08-26 05:35:21 -04:00
$error = 'Username is invalid - please use A-Za-z0-9, periods, hyphens, and underscores only.' ;
2021-07-11 12:50:24 -04:00
} else {
2021-11-01 16:56:17 -04:00
if ( User :: where ( 'username' , $username ) -> first ()) {
2021-08-26 05:35:21 -04:00
$error = 'That username has already been taken.' ;
2021-07-11 12:50:24 -04:00
} else {
2021-11-01 16:56:17 -04:00
/* this is displayed to the user in the template, hence the variable rather than inlining */
2021-07-24 14:45:46 -04:00
$recovery_code = pp_random_token ();
2021-11-01 16:56:17 -04:00
$user = new User ([
'username' => $username ,
'password' => $password ,
'recovery_code_hash' => pp_password_hash ( $recovery_code ),
'date' => $date ,
'ip' => $ip
]);
$user -> save ();
2021-07-15 12:40:12 -04:00
2021-08-26 05:35:21 -04:00
$success = 'Your account was successfully registered.' ;
2021-07-10 19:18:17 +01:00
}
}
}
// Theme
2021-08-22 21:45:26 -04:00
$page_template = 'login' ;
2021-08-26 05:35:21 -04:00
$page_title = 'Login / Register' ;
2021-08-22 21:45:26 -04:00
require_once ( 'theme/' . $default_theme . '/common.php' );