2020-02-09 23:02:19 +01:00
< ? php
namespace Objects ;
2020-04-03 15:56:04 +02:00
use Api\SetLanguage ;
use Configuration\Configuration ;
2020-06-17 23:50:08 +02:00
use DateTime ;
use Driver\SQL\Expression\Add ;
use Driver\SQL\Strategy\UpdateStrategy ;
2020-04-03 15:56:04 +02:00
use Exception ;
use External\JWT ;
use Driver\SQL\SQL ;
2020-04-02 00:02:51 +02:00
use Driver\SQL\Condition\Compare ;
use Driver\SQL\Condition\CondBool ;
2020-02-09 23:02:19 +01:00
class User extends ApiObject {
2020-04-03 15:56:04 +02:00
private ? SQL $sql ;
private Configuration $configuration ;
private bool $loggedIn ;
private ? Session $session ;
private int $uid ;
private string $username ;
private Language $language ;
2020-04-03 18:09:01 +02:00
private array $groups ;
2020-02-09 23:02:19 +01:00
public function __construct ( $configuration ) {
2020-02-17 00:18:37 +01:00
session_start ();
2020-02-09 23:02:19 +01:00
$this -> configuration = $configuration ;
2020-04-03 15:56:04 +02:00
$this -> setLanguage ( Language :: DEFAULT_LANGUAGE ());
2020-02-09 23:02:19 +01:00
$this -> reset ();
$this -> connectDb ();
$this -> parseCookies ();
}
public function __destruct () {
if ( $this -> sql && $this -> sql -> isConnected ()) {
$this -> sql -> close ();
}
}
private function connectDb () {
$databaseConf = $this -> configuration -> getDatabase ();
if ( $databaseConf ) {
2020-04-03 15:56:04 +02:00
$this -> sql = SQL :: createConnection ( $databaseConf );
} else {
$this -> sql = null ;
2020-02-09 23:02:19 +01:00
}
}
public function getId () { return $this -> uid ; }
public function isLoggedIn () { return $this -> loggedIn ; }
public function getUsername () { return $this -> username ; }
public function getSQL () { return $this -> sql ; }
public function getLanguage () { return $this -> language ; }
2020-04-03 15:56:04 +02:00
public function setLanguage ( Language $language ) { $this -> language = $language ; $language -> load (); }
2020-02-09 23:02:19 +01:00
public function getSession () { return $this -> session ; }
public function getConfiguration () { return $this -> configuration ; }
2020-04-03 18:09:01 +02:00
public function getGroups () { return $this -> groups ; }
public function hasGroup ( int $group ) { return isset ( $this -> groups [ $group ]); }
2020-02-09 23:02:19 +01:00
public function __debugInfo () {
$debugInfo = array (
'loggedIn' => $this -> loggedIn ,
'language' => $this -> language -> getName (),
);
if ( $this -> loggedIn ) {
$debugInfo [ 'uid' ] = $this -> uid ;
$debugInfo [ 'username' ] = $this -> username ;
}
return $debugInfo ;
}
public function jsonSerialize () {
2020-06-14 19:39:52 +02:00
if ( $this -> isLoggedIn ()) {
return array (
'uid' => $this -> uid ,
'name' => $this -> username ,
'groups' => $this -> groups ,
'language' => $this -> language -> jsonSerialize (),
'session' => $this -> session -> jsonSerialize (),
);
} else {
return array (
'language' => $this -> language -> jsonSerialize (),
);
}
2020-02-09 23:02:19 +01:00
}
private function reset () {
$this -> uid = 0 ;
$this -> username = '' ;
$this -> loggedIn = false ;
2020-04-03 15:56:04 +02:00
$this -> session = null ;
2020-02-09 23:02:19 +01:00
}
public function logout () {
2020-04-02 00:02:51 +02:00
$success = true ;
2020-02-09 23:02:19 +01:00
if ( $this -> loggedIn ) {
2020-04-02 00:02:51 +02:00
$success = $this -> session -> destroy ();
2020-02-09 23:02:19 +01:00
$this -> reset ();
}
2020-04-02 00:02:51 +02:00
return $success ;
2020-02-09 23:02:19 +01:00
}
public function updateLanguage ( $lang ) {
2020-02-10 00:52:25 +01:00
if ( $this -> sql ) {
2020-04-03 15:56:04 +02:00
$request = new SetLanguage ( $this );
2020-02-10 00:52:25 +01:00
return $request -> execute ( array ( " langCode " => $lang ));
2020-04-03 15:56:04 +02:00
} else {
return false ;
2020-02-10 00:52:25 +01:00
}
2020-02-09 23:02:19 +01:00
}
public function sendCookies () {
if ( $this -> loggedIn ) {
$this -> session -> sendCookie ();
}
$this -> language -> sendCookie ();
2020-06-17 23:50:08 +02:00
session_write_close ();
2020-02-09 23:02:19 +01:00
}
public function readData ( $userId , $sessionId , $sessionUpdate = true ) {
2020-02-17 00:18:37 +01:00
2020-04-02 00:02:51 +02:00
$res = $this -> sql -> select ( " User.name " , " Language.uid as langId " , " Language.code as langCode " , " Language.name as langName " ,
2020-06-14 19:39:52 +02:00
" Session.data " , " Session.stay_logged_in " , " Session.csrf_token " , " Group.uid as groupId " , " Group.name as groupName " )
2020-04-02 00:02:51 +02:00
-> from ( " User " )
-> innerJoin ( " Session " , " Session.user_id " , " User.uid " )
-> leftJoin ( " Language " , " User.language_id " , " Language.uid " )
2020-04-03 18:09:01 +02:00
-> leftJoin ( " UserGroup " , " UserGroup.user_id " , " User.uid " )
-> leftJoin ( " Group " , " UserGroup.group_id " , " Group.uid " )
2020-04-02 00:02:51 +02:00
-> where ( new Compare ( " User.uid " , $userId ))
-> where ( new Compare ( " Session.uid " , $sessionId ))
-> where ( new Compare ( " Session.active " , true ))
2020-04-02 15:08:14 +02:00
-> where ( new CondBool ( " Session.stay_logged_in " ), new Compare ( " Session.expires " , $this -> sql -> currentTimestamp (), '>' ))
2020-04-02 00:02:51 +02:00
-> execute ();
$success = ( $res !== FALSE );
2020-02-09 23:02:19 +01:00
if ( $success ) {
2020-04-02 00:02:51 +02:00
if ( empty ( $res )) {
2020-02-09 23:02:19 +01:00
$success = false ;
} else {
2020-04-02 00:02:51 +02:00
$row = $res [ 0 ];
2020-06-14 19:39:52 +02:00
$csrfToken = $row [ " csrf_token " ];
2020-04-02 00:02:51 +02:00
$this -> username = $row [ 'name' ];
2020-02-09 23:02:19 +01:00
$this -> uid = $userId ;
2020-06-14 19:39:52 +02:00
$this -> session = new Session ( $this , $sessionId , $csrfToken );
2020-04-02 21:32:26 +02:00
$this -> session -> setData ( json_decode ( $row [ " data " ] ? ? '{}' ));
2020-04-02 00:02:51 +02:00
$this -> session -> stayLoggedIn ( $row [ " stay_logged_in " ]);
2020-02-09 23:02:19 +01:00
if ( $sessionUpdate ) $this -> session -> update ();
$this -> loggedIn = true ;
2020-04-03 18:09:01 +02:00
2020-02-09 23:02:19 +01:00
if ( ! is_null ( $row [ 'langId' ])) {
2020-04-03 15:56:04 +02:00
$this -> setLanguage ( Language :: newInstance ( $row [ 'langId' ], $row [ 'langCode' ], $row [ 'langName' ]));
2020-02-09 23:02:19 +01:00
}
2020-04-03 18:09:01 +02:00
foreach ( $res as $row ) {
$this -> groups [ $row [ " groupId " ]] = $row [ " groupName " ];
}
2020-02-09 23:02:19 +01:00
}
}
return $success ;
}
private function parseCookies () {
if ( isset ( $_COOKIE [ 'session' ])
&& is_string ( $_COOKIE [ 'session' ])
&& ! empty ( $_COOKIE [ 'session' ])
&& ( $jwt = $this -> configuration -> getJWT ())) {
try {
$token = $_COOKIE [ 'session' ];
2020-04-02 21:19:06 +02:00
$decoded = ( array ) JWT :: decode ( $token , $jwt -> getKey ());
2020-02-09 23:02:19 +01:00
if ( ! is_null ( $decoded )) {
$userId = ( isset ( $decoded [ 'userId' ]) ? $decoded [ 'userId' ] : NULL );
$sessionId = ( isset ( $decoded [ 'sessionId' ]) ? $decoded [ 'sessionId' ] : NULL );
if ( ! is_null ( $userId ) && ! is_null ( $sessionId )) {
$this -> readData ( $userId , $sessionId );
}
}
2020-04-03 15:56:04 +02:00
} catch ( Exception $e ) {
2020-04-02 21:19:06 +02:00
// ignored
2020-02-09 23:02:19 +01:00
}
}
if ( isset ( $_GET [ 'lang' ]) && is_string ( $_GET [ " lang " ]) && ! empty ( $_GET [ " lang " ])) {
$this -> updateLanguage ( $_GET [ 'lang' ]);
2020-02-17 00:18:37 +01:00
} else if ( isset ( $_COOKIE [ 'lang' ]) && is_string ( $_COOKIE [ " lang " ]) && ! empty ( $_COOKIE [ " lang " ])) {
2020-02-09 23:02:19 +01:00
$this -> updateLanguage ( $_COOKIE [ 'lang' ]);
2020-02-17 00:18:37 +01:00
}
2020-02-09 23:02:19 +01:00
}
2020-02-17 00:18:37 +01:00
public function createSession ( $userId , $stayLoggedIn ) {
2020-02-09 23:02:19 +01:00
$this -> uid = $userId ;
2020-02-17 00:18:37 +01:00
$this -> session = Session :: create ( $this , $stayLoggedIn );
if ( $this -> session ) {
$this -> loggedIn = true ;
return true ;
}
return false ;
2020-02-09 23:02:19 +01:00
}
public function authorize ( $apiKey ) {
2020-04-02 00:02:51 +02:00
2020-02-09 23:02:19 +01:00
if ( $this -> loggedIn )
return true ;
2020-04-02 00:02:51 +02:00
$res = $this -> sql -> select ( " ApiKey.user_id as uid " , " User.name as username " , " Language.uid as langId " , " Language.code as langCode " , " Language.name as langName " )
-> from ( " ApiKey " )
-> innerJoin ( " User " , " ApiKey.user_id " , " User.uid " )
-> leftJoin ( " Language " , " User.language_id " , " Language.uid " )
-> where ( new Compare ( " ApiKey.api_key " , $apiKey ))
2020-04-02 15:08:14 +02:00
-> where ( new Compare ( " valid_until " , $this -> sql -> currentTimestamp (), " > " ))
2020-04-03 15:56:04 +02:00
-> where ( new Compare ( " ApiKey.active " , 1 ))
2020-04-02 00:02:51 +02:00
-> execute ();
2020-02-09 23:02:19 +01:00
2020-04-02 00:02:51 +02:00
$success = ( $res !== FALSE );
2020-02-09 23:02:19 +01:00
if ( $success ) {
2020-04-02 00:02:51 +02:00
if ( empty ( $res )) {
2020-02-09 23:02:19 +01:00
$success = false ;
} else {
2020-04-02 00:02:51 +02:00
$row = $res [ 0 ];
2020-02-09 23:02:19 +01:00
$this -> uid = $row [ 'uid' ];
$this -> username = $row [ 'username' ];
if ( ! is_null ( $row [ 'langId' ])) {
2020-04-03 15:56:04 +02:00
$this -> setLanguage ( Language :: newInstance ( $row [ 'langId' ], $row [ 'langCode' ], $row [ 'langName' ]));
2020-02-09 23:02:19 +01:00
}
}
}
return $success ;
}
2020-06-17 23:50:08 +02:00
public function processVisit () {
if ( $this -> sql && isset ( $_COOKIE [ " PHPSESSID " ]) && ! empty ( $_COOKIE [ " PHPSESSID " ])) {
2020-06-18 15:08:09 +02:00
if ( $this -> isBot ()) {
return ;
}
2020-06-17 23:50:08 +02:00
$cookie = $_COOKIE [ " PHPSESSID " ];
$month = ( new DateTime ()) -> format ( " Ym " );
$this -> sql -> insert ( " Visitor " , array ( " cookie " , " month " ))
-> addRow ( $cookie , $month )
2020-06-18 15:08:09 +02:00
-> onDuplicateKeyStrategy ( new UpdateStrategy (
array ( " month " , " cookie " ),
array ( " count " => new Add ( " Visitor.count " , 1 ))))
2020-06-17 23:50:08 +02:00
-> execute ();
}
}
2020-06-18 15:08:09 +02:00
private function isBot () {
if ( ! isset ( $_SERVER [ " HTTP_USER_AGENT " ]) || empty ( $_SERVER [ " HTTP_USER_AGENT " ])) {
return false ;
}
return preg_match ( '/robot|spider|crawler|curl|^$/i' , $_SERVER [ 'HTTP_USER_AGENT' ]) === 1 ;
}
2020-02-09 23:02:19 +01:00
}