DataInterface = $DataInterface; } /** * Get data required for signing up new account. */ public function accountSignupGet($lang) { $statement = $this->DataInterface->DatabaseConnection->prepare( "SELECT *, name_$lang AS name FROM country ORDER BY name_$lang" ); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } $countries = $statement->fetchAll(\PDO::FETCH_ASSOC); return [ 'result' => 'OK', 'countries' => $countries ]; } /** * */ public function accountResetPost($data) { $statement = $this->DataInterface->DatabaseConnection->prepare( "SELECT address FROM email WHERE type = 'postmaster'" ); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } $postmaster = $statement->fetchAll(\PDO::FETCH_ASSOC)[0]['address']; // user if (!filter_var($data['to'], FILTER_VALIDATE_EMAIL)) { return ['result' => 'ERROR', 'reason' => 'invalid_email']; } // Check email exists $statement = $this->DataInterface->DatabaseConnection->prepare( 'SELECT ID FROM user WHERE email = \''.$data['to'].'\'' ); $statement->execute(); if(count($statement->fetchAll(\PDO::FETCH_ASSOC))==0) { return ['result' => 'ERROR', 'reason' => 'invalid_email']; } // $reset_token = \Tools\UUID::v4(); $statement = $this->DataInterface->DatabaseConnection->prepare( 'UPDATE user SET password = \''.$reset_token.'\' WHERE email = \''.$data['to'].'\'' ); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } // return [ 'result' => 'OK', 'email' => $data['to'], 'sender' => $postmaster, 'reset_token' => $reset_token ]; } /** * */ public function accountReset2Post($data) { if (strlen($data['newPassword']) < 8 || !preg_match("#[0-9]+#", $data['newPassword']) || !preg_match("#[a-z]+#", $data['newPassword']) || !preg_match("#[A-Z]+#", $data['newPassword'])) { return ['result' => 'ERROR', 'reason' => 'password_strength']; } $password = \Tools\Crypto::getHashPassword($data['newPassword']); $statement = $this->DataInterface->DatabaseConnection->prepare( "UPDATE user SET password = :newPassword WHERE password = :token" ); $statement->bindParam(':newPassword', $password); $statement->bindParam(':token', $data['token']); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } // return [ 'result' => 'OK' ]; } /** * Check data and create new account. */ public function accountSignupPost($data) { $statement = $this->DataInterface->DatabaseConnection->prepare( "SELECT address FROM email WHERE type = 'postmaster'" ); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } $email = $statement->fetchAll(\PDO::FETCH_ASSOC)[0]['address']; // user if (!filter_var($data['user']['email'], FILTER_VALIDATE_EMAIL)) { return ['result' => 'ERROR', 'group' => 'user', 'reason' => 'email']; } // Check email exists $statement = $this->DataInterface->DatabaseConnection->prepare( 'SELECT ID FROM user WHERE email = \''.$data['user']['email'].'\' AND type = \'physician\'' ); $statement->execute(); if(count($statement->fetchAll(\PDO::FETCH_ASSOC))!=0) { return ['result' => 'ERROR', 'reason' => 'duplicate_user']; } if (strlen($data['user']['password']) < 8 || !preg_match("#[0-9]+#", $data['user']['password']) || !preg_match("#[a-z]+#", $data['user']['password']) || !preg_match("#[A-Z]+#", $data['user']['password'])) { return ['result' => 'ERROR', 'reason' => 'password_strength']; } if($data['user']['password'] != $data['user']['password2']) { return ['result' => 'ERROR', 'reason' => 'password_mismatch']; } if(empty($data['user']['firstname'])) { return ['result' => 'ERROR', 'group' => 'user', 'reason' => 'firstname']; } if(empty($data['user']['lastname'])) { return ['result' => 'ERROR', 'group' => 'user', 'reason' => 'lastname']; } if(empty($data['user']['phone'])) { return ['result' => 'ERROR', 'group' => 'user', 'reason' => 'phone']; } // organization if(empty($data['organization']['name'])) { return ['result' => 'ERROR', 'group' => 'organization', 'reason' => 'name']; } if(empty($data['organization']['country'])) { return ['result' => 'ERROR', 'group' => 'organization', 'reason' => 'country']; } if(empty($data['organization']['zip'])) { return ['result' => 'ERROR', 'group' => 'organization', 'reason' => 'zip']; } if(empty($data['organization']['city'])) { return ['result' => 'ERROR', 'group' => 'organization', 'reason' => 'city']; } if(empty($data['organization']['address'])) { return ['result' => 'ERROR', 'group' => 'organization', 'reason' => 'address']; } if(empty($data['organization']['phone'])) { return ['result' => 'ERROR', 'group' => 'organization', 'reason' => 'phone']; } // probe if(empty($data['probe']['brand'])) { return ['result' => 'ERROR', 'group' => 'probe', 'reason' => 'brand']; } if(empty($data['probe']['year'])) { $data['probe']['year'] = null; } if(empty($data['probe']['frequency'])) { return ['result' => 'ERROR', 'group' => 'probe', 'reason' => 'frequency']; } // validation if($data['validation']['terms'] != 'true') { return ['result' => 'ERROR', 'reason' => 'validation_terms']; } /*if($data['validation']['database'] != 'true') { return ['result' => 'ERROR', 'reason' => 'validation_database']; }*/ // Begin transaction $this->DataInterface->DatabaseConnection->beginTransaction(); // Insert user $statement = $this->DataInterface->DatabaseConnection->prepare( "INSERT INTO user(activation_token, activation_expire, password, firstname, lastname, email, phone, type) VALUES(:activation_token, :activation_expire, :password, :firstname, :lastname, :email, :phone, 'physician')" ); $activation_token = \Tools\UUID::v4(); $activation_expire = date('Y-m-d H:i:s', strtotime(date('Y-m-d H:i:s'). ' + 1 days')); $statement->bindParam(':activation_token', $activation_token); $statement->bindParam(':activation_expire', $activation_expire); $password = \Tools\Crypto::getHashPassword($data['user']['password']); $statement->bindParam(':password', $password); $statement->bindParam(':firstname', $data['user']['firstname']); $statement->bindParam(':lastname', $data['user']['lastname']); $statement->bindParam(':email', $data['user']['email']); $statement->bindParam(':phone', $data['user']['phone']); // Error check if(!$statement->execute()) { $this->DataInterface->DatabaseConnection->rollback(); return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } $fk_user = $this->DataInterface->DatabaseConnection->lastInsertId(); // Insert organization $statement = $this->DataInterface->DatabaseConnection->prepare( "INSERT INTO organization(fk_user, name, fk_country, zip, city, address, phone) VALUES(:fk_user, :name, :fk_country, :zip, :city, :address, :phone)" ); $statement->bindParam(':fk_user', $fk_user); $statement->bindParam(':name', $data['organization']['name']); $statement->bindParam(':fk_country', $data['organization']['country']); $statement->bindParam(':zip', $data['organization']['zip']); $statement->bindParam(':city', $data['organization']['city']); $statement->bindParam(':address', $data['organization']['address']); $statement->bindParam(':phone', $data['organization']['phone']); // Error check if(!$statement->execute()) { $this->DataInterface->DatabaseConnection->rollback(); return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } // Insert probe $statement = $this->DataInterface->DatabaseConnection->prepare( "INSERT INTO probe(fk_user, name, brand, type, year, frequency) VALUES(:fk_user, :name, :brand, :type, :year, :frequency)" ); $statement->bindParam(':fk_user', $fk_user); $statement->bindParam(':name', $data['probe']['name']); $statement->bindParam(':brand', $data['probe']['brand']); $statement->bindParam(':type', $data['probe']['type']); $statement->bindParam(':year', $data['probe']['year']); $statement->bindParam(':frequency', $data['probe']['frequency']); // Error check if(!$statement->execute()) { $this->DataInterface->DatabaseConnection->rollback(); return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } // Commit $this->DataInterface->DatabaseConnection->commit(); return [ 'result' => 'OK', 'data' => $data, 'activation_token' => $activation_token, 'email' => $data['user']['email'], 'sender' => $email ]; } /** * Activate an account. */ public function accountActivateGet($activation_token) { $statement = $this->DataInterface->DatabaseConnection->prepare( "SELECT ID FROM user WHERE activation_token = :activation_token" ); $statement->bindParam(':activation_token', $activation_token); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } if(count($statement->fetchAll(\PDO::FETCH_ASSOC))==0) { return ['result' => 'ERROR', 'reason' => 'invalid_token']; } // update account $statement = $this->DataInterface->DatabaseConnection->prepare( "UPDATE user SET activation = NOW() WHERE activation_token = :activation_token" ); $statement->bindParam(':activation_token', $activation_token); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } $statement->bindParam(':activation_token', $activation_token); return ['result' => 'OK']; } /** * Check login/password and create JWT token. */ public function accountSigninPost(&$User, $data) { if($data['type']=='physician') { $typeSql = "AND type = 'physician'"; } else { // 'ct' $typeSql = "AND (type = 'reader' OR type = 'investigator')"; } $statement = $this->DataInterface->DatabaseConnection->prepare( "SELECT * FROM user WHERE activation IS NOT NULL AND active = 1 AND email = :email $typeSql" ); $statement->bindParam(':email', $data['email']); if(!$statement->execute()) { return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()]; } $results = $statement->fetchAll(\PDO::FETCH_ASSOC); if(count($results)){ if(\Tools\Crypto::verify($data['password'], $results[0]['password'])) { // Generate JWT token $issuer_claim = \Config\Settings::getTokenIssuer(); $audience_claim = \Config\Settings::getTokenAudience(); $issuedat_claim = time(); // issued at $notbefore_claim = $issuedat_claim + \Config\Settings::getTokenNotBefore(); $expire_claim = $issuedat_claim + \Config\Settings::getTokenExpiration(); $token = array( "iss" => $issuer_claim, "aud" => $audience_claim, "iat" => $issuedat_claim, "nbf" => $notbefore_claim, "exp" => $expire_claim, "data" => array( "ID" => $results[0]['ID'], "firstname" => $results[0]['firstname'], "lastname" => $results[0]['lastname'], "email" => $results[0]['email'], "type" => $results[0]['type'] ) ); $jwt = \Firebase\JWT\JWT::encode($token, \Config\Settings::getTokenPrivateKey()); // OK return [ "result" => "OK", "token" => $jwt, "expireAt" => $expire_claim, "username" => $data['email'], "store" => $data['store'], "type" => $results[0]['type'] ]; } return ['result' => 'ERROR', 'reason' => 'bad_password', 'message' => 'Invalid password']; } return ['result' => 'ERROR', 'reason' => 'unknown', 'message' => 'No such user']; } /** * Logout. */ public function accountLogoutGet(&$User) { $User->logout(); return ['result' => 'OK']; } } }