summaryrefslogtreecommitdiff
path: root/html/app
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-17 02:19:27 +0200
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-17 02:19:27 +0200
commit26229c110fb92646b36c7b2f48ac7518fd3810a5 (patch)
tree72b2f2e0e0c789853ceb815fd5b513ad31672cac /html/app
parent1e438654005bd408447dc19c8a96099d228bb1aa (diff)
downloadclassroom-26229c110fb92646b36c7b2f48ac7518fd3810a5.tar.gz
classroom-26229c110fb92646b36c7b2f48ac7518fd3810a5.tar.bz2
classroom-26229c110fb92646b36c7b2f48ac7518fd3810a5.zip
set algorithns for user authentication and authorization
Diffstat (limited to 'html/app')
-rw-r--r--html/app/config/app_constants.php (renamed from html/app/config/assets.php)34
-rw-r--r--html/app/controllers/Auth.php196
-rw-r--r--html/app/models/admin/History_model.php28
-rw-r--r--html/app/models/admin/User_model.php227
-rw-r--r--html/app/models/user/Validate_model.php27
5 files changed, 484 insertions, 28 deletions
diff --git a/html/app/config/assets.php b/html/app/config/app_constants.php
index 9203c47..3dac5ec 100644
--- a/html/app/config/assets.php
+++ b/html/app/config/app_constants.php
@@ -1,6 +1,38 @@
<?php
-// PATHS USED HEAVILY //////////////////////////////////////////////////////////
+// DEFAULT VALUES //////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
+
+// default privileges (for the subscribed user)
+// (array of privilege aliases)
+// ---
+define('DEFAULT_PRIVILEGES', [
+ 'e.1', // economics, level 1
+ 'p.1' // programming. level 1
+]);
+
+
+
+
+// ACCESS HISTORY //////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
+// (user-)access types
+
+define('TRACK_LOGIN', 1); // login / logout
+define('TRACK_ACCOUNT', 2); // create user / activate account
+define('TRACK_PAYMENTS', 3); // order / payment / refund etc...
+
+// access type strings
+// ---
+define('USER_ACCESS_TYPE', [
+ 1 => 'Login',
+ 2 => 'Account',
+ 3 => 'Payment'
+]);
+
+
+
+// ASSETS: PATHS USED HEAVILY //////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// these paths are used in order to easily find and autoload useful elemets
diff --git a/html/app/controllers/Auth.php b/html/app/controllers/Auth.php
new file mode 100644
index 0000000..c75f979
--- /dev/null
+++ b/html/app/controllers/Auth.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace app\controllers;
+
+use Registry;
+use UserManager;
+use User;
+use app\models\user\User_model;
+
+
+/** class Auth
+ *
+ * handles user's Authentication and Authorizarion
+ *
+ */
+class Auth {
+
+ /** login
+ *
+ * checks visitor's credentials;
+ * if valid, authenticates user
+ *
+ */
+ public static function login()
+ {
+ $req = Registry::get('REQUEST');
+
+ // get the record of the target user
+ $record = User_model::checkUser('email', $req->POST['email']);
+
+ // if no user exists, return false
+ if ($record === false) return false;
+
+ // create a user object
+ $user = (new User())
+ ->setUserName($record['email'])
+ ->setPassword($record['password'])
+ ->setRoles(json_decode($record['roles']))
+ ->setEnabled($record['active']);
+
+ // let user manager to validate user credentials
+ $userManager = new UserManager();
+
+ if ($userManager->isPasswordValid($user, $req->POST['password'])) {
+
+ // login OK, set Token in session
+ $userManager->createUserToken($user);
+
+ } else {
+ return false;
+ }
+ }
+
+
+ /** register
+ *
+ * registers new user
+ *
+ */
+ public static function register()
+ {
+ $userManager = new UserManager();
+ $req = Registry::get('REQUEST');
+
+ // create a salted password hash
+ $password = $userManager->cryptPassword($req->POST['password']);
+
+ $user = (new User())
+ ->setUserName($req->POST['username'])
+ ->setPassword($password)
+ ->setRoles(['ROLE_USER']);
+
+ // TODO:
+ // store user to database
+
+ $userManager->createUserToken($user);
+ }
+
+
+
+ public static function logout()
+ {
+ $userManager = new UserManager();
+ $userManager->logout();
+ }
+
+
+
+ /** isGranted( ROLE )
+ *
+ * checks if the user is granted (some of) the specified role(s)
+ * to access the source
+ *
+ * NOTE:
+ * if no roles are specified then user is granted
+ * (because every user is granted the 'no-role')
+ *
+ * @param $roles (array): array of roles to check (if any is granted)
+ *
+ */
+ public static function isGranted($roles = [])
+ {
+ // no role required ? user is granted access
+ if ($roles == []) return true;
+
+ // else, UserManager knows if user isGranted
+ $userManager = new UserManager();
+ if ($userManager->isGranted($roles)) {
+ return true;
+
+ } else {
+ return false;
+ }
+ }
+
+
+ /** hasPermition( PERMIT )
+ *
+ * checks if the user owns the specified permition
+ * to access the source
+ *
+ */
+ public static function hasPermition($permit = [])
+ {
+ if ($permit == []) return true;
+ }
+
+
+ /** isAuthenticated()
+ *
+ * chechs if the user's roles and permitions
+ * satisfy the specified requirements
+ * to access the source
+ *
+ * @param $requirements (array of rules-array)
+ *
+ * example:
+ * [
+ * [
+ * role => ['editor','designer']
+ * permition => ['10', '12', '18']
+ * ],
+ * [
+ * role => ['admin' , 'developερ']
+ * ],
+ * [
+ * permition => [ 3 ]
+ * ]
+ * ]
+ *
+ * defines (and parses to) a requirements rule of:
+ * [
+ * user should be editor or designer
+ * and have permition 10 or 12 or 18
+ * ]
+ * OR
+ * [
+ * user should be an administratoe or developer
+ * ]
+ * OR
+ * [
+ * user should have permition #3
+ * ]
+ *
+ *
+ */
+ public static function isAuthorized($requirements)
+ {
+ $authorized = false;
+ foreach($requirements as $required) {
+ if ( (self::isGranted($required['role'] ?? []))
+ && (self::hasPermition($required['permition'] ?? [])) ) {
+ $authorized = true;
+ }
+ }
+ return $authorized;
+ }
+
+
+
+
+ public static function forgot_pass()
+ {
+ }
+
+
+
+ public static function validate_otp()
+ {
+ }
+
+
+
+}
+
+
diff --git a/html/app/models/admin/History_model.php b/html/app/models/admin/History_model.php
new file mode 100644
index 0000000..63086e3
--- /dev/null
+++ b/html/app/models/admin/History_model.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace app\models\admin;
+
+use \Registry;
+use app\models\admin\history;
+
+class User_model
+{
+
+ /** track user access
+ *
+ */
+ public static function trackUserAccess($user_id, $type, $message, $note='')
+ {
+ $access = [
+ 'user_id' => $user_id,
+ 'type' => $type,
+ 'message' => $message,
+ 'note' => $note,
+ 'ip' => Registry::get('REQUEST')->IP
+ ];
+
+ }
+
+
+
+} \ No newline at end of file
diff --git a/html/app/models/admin/User_model.php b/html/app/models/admin/User_model.php
new file mode 100644
index 0000000..63d826f
--- /dev/null
+++ b/html/app/models/admin/User_model.php
@@ -0,0 +1,227 @@
+<?php
+
+namespace app\models\admin;
+
+use \Registry;
+use app\models\admin\history;
+
+class User_model
+{
+
+ /** check user (by index key)
+ *
+ * @param $indexKey (string) : key for user identification
+ * @param $value (string)
+ *
+ * NOTE: $indexKey MUST BE a unique key
+ *
+ * @return $user : [array] or false
+ */
+ public static function checkUser($indexKey, $value)
+ {
+ $user = Registry::use('database')->query(
+ "SELECT * FROM user WHERE {$indexKey} = :val",
+ [ ':val' => $value ]
+ )->getFirst();
+
+ // if no user, return false
+ if ($user === false) return false;
+
+ return $user;
+ }
+
+
+ /** get user (by index key)
+ *
+ * user detailed array
+ * includes all user properties + granted roles + privileges
+ *
+ * @param $id (int) : user id
+ * @param $value (string)
+ */
+ public static function getUser($id)
+ {
+ $user = Registry::use('database')->query(
+ "SELECT user.*,
+ ( -- construct array (json) of roles granted to user
+ SELECT CONCAT(
+ '[',
+ GROUP_CONCAT(role.id),
+ ']'
+ )
+ FROM `role`
+ WHERE role.id IN (
+ SELECT user_role.role_id
+ FROM user_role
+ WHERE user_role.user_id = :id
+ )
+ ) AS Roles_json,
+ ( -- construct array of (root-)privileges granted to user
+ SELECT CONCAT(
+ '[',
+ GROUP_CONCAT(privilege.id),
+ ']'
+ )
+ FROM privilege
+ WHERE privilege.id IN (
+ SELECT user_privilege.privilege_id
+ FROM user_privilege
+ WHERE user_privilege.user_id = :id
+ )
+ ) AS RootPrivileges_json,
+ (
+ SELECT CONCAT( -- array of array of sub-privileges
+ '[',
+ GROUP_CONCAT(
+ (
+ SELECT CONCAT( -- array (json) of subprivileges
+ '[',
+ GROUP_CONCAT(included_id),
+ ']'
+ )
+ FROM privilege_includes
+ WHERE privilege_id = privilege.id
+ )
+ ),
+ ']'
+ )
+ FROM privilege
+ WHERE privilege.id IN (
+ SELECT user_privilege.privilege_id
+ FROM user_privilege
+ WHERE user_id = :id
+ )
+ ) AS SubPrivileges_json
+ FROM user
+ WHERE id = :id",
+ [ ':id' => $id ]
+ )->getFirst();
+
+
+ // if no user, return false
+ if ($user === false) return false;
+
+
+ // TODO:
+ // * merge root+sub privilede lists
+ // * convert json strings to php arrays
+
+
+ // TODO:
+ // cache user super array
+
+ return $user;
+ }
+
+
+ /** create user
+ *
+ */
+ public static function createUser($data, $privileges = ['ec.1', 'pr.1'])
+ {
+ $user = [
+ 'prefix' => $data['prefix'],
+ 'name' => $data['name'],
+ 'surname' => $data['surname'],
+ 'email' => $data['email'],
+ 'password' => $data['password'],
+ 'active' => 0 // needs email confirmation
+ ];
+
+ $sql = "INSERT INTO user (`prefix`, `name`, `surname`, email, `password`, user_id)
+ VALUES (:prrfic, :name, :surname, :email, :password, :userid)";
+ $stmt = $this->pdo->prepare($sql);
+ $stmt->execute($user);
+
+ $inserted_id = $this->pdo->lastInsertId();
+
+ // set default privileges
+ self::set_user_privileges($privileges);
+
+ // update history
+
+
+
+ return [ "success" => true, 'id' => $inserted_id ];
+ }
+
+
+
+
+ /** inherited privileges
+ *
+ * list of all inhereted (sub-)privileges
+ * from a list of root-privileges
+ *
+ * @param $list (array of int): list of root privilege id(s)
+ */
+ public static function inheritedPrivileges($list)
+ {
+ $rootList = "(". implode(', ', $list) .")";
+
+ $subPrivileges = Registry::use('database')->runQuery(
+ "SELECT privilege.id, (
+ SELECT CONCAT('[', GROUP_CONCAT(included_id), ']') FROM privilege_includes
+ WHERE privilege_id = privilege.id
+ ) as subprivilege_json
+ FROM privilege
+ WHERE privilege.id IN {$rootlist}", []
+ );
+ }
+
+
+
+}
+
+/* example query getUser (super-array)
+--- -- -- - - -
+
+SELECT user.*,
+( -- array (json) of roles granted to user
+ SELECT CONCAT('[', GROUP_CONCAT(role.id), ']')
+ FROM `role`
+ WHERE role.id IN (
+ SELECT user_role.role_id
+ FROM user_role
+ WHERE user_role.user_id = 1
+ )
+) AS Roles_json,
+(
+ SELECT CONCAT(
+ '[',
+ GROUP_CONCAT(privilege.id),
+ ']'
+ )
+ FROM privilege
+ WHERE privilege.id IN (
+ SELECT user_privilege.privilege_id
+ FROM user_privilege
+ WHERE user_privilege.user_id = 1
+ )
+) AS RootPrivileges_json,
+(
+ SELECT CONCAT( -- array of array of sub-privileges
+ '[',
+ GROUP_CONCAT( -- array (json) of subprivileges
+ (
+ SELECT CONCAT(
+ '[',
+ GROUP_CONCAT(included_id),
+ ']'
+ )
+ FROM privilege_includes
+ WHERE privilege_id = privilege.id
+ )
+ ),
+ ']'
+ )
+ FROM privilege
+ WHERE privilege.id IN (
+ SELECT user_privilege.privilege_id
+ FROM user_privilege
+ WHERE user_id = 1
+ )
+) AS SubPrivileges_json
+FROM user
+WHERE id = 1
+--- */ \ No newline at end of file
diff --git a/html/app/models/user/Validate_model.php b/html/app/models/user/Validate_model.php
deleted file mode 100644
index 16ad70a..0000000
--- a/html/app/models/user/Validate_model.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-namespace app\models\user;
-
-use \Registry;
-
-
-class Validate
-{
- /** ticket
- *
- * validate that the user owns the `ticket`
- *
- */
- public static function ticket($ticket)
- {
- }
-
- /** access
- *
- * validate that the `ticket` is compatible with access_level
- */
- public static function access($ticket, $access_level)
- {
- }
-
-} \ No newline at end of file