diff --git a/Modules/sessions/Views/view.email_layout.tpl b/Modules/sessions/Views/view.email_layout.tpl
new file mode 100644
index 0000000..e69de29
diff --git a/Modules/sessions/class.events.php b/Modules/sessions/class.events.php
new file mode 100644
index 0000000..c8b2d26
--- /dev/null
+++ b/Modules/sessions/class.events.php
@@ -0,0 +1,72 @@
+customHtml = $bool;
+ return true;
+ }
+ throw new ServiceException("Could not set customHtml. Input is not a Boolean", 1);
+ }
+
+ /**
+ * Intializes the event and it's variables
+ * @access public
+ * @param Array UDT of user to send mail to
+ * @param String VerificationCode
+ * @param String VerificationURL
+ */
+ public function init($udt, $verifyCode, $verifyURL) {
+ $this->udt = $udt;
+ }
+
+}
\ No newline at end of file
diff --git a/Modules/sessions/class.sessions.php b/Modules/sessions/class.sessions.php
new file mode 100644
index 0000000..80f9668
--- /dev/null
+++ b/Modules/sessions/class.sessions.php
@@ -0,0 +1,925 @@
+getmodulePath() . "/class.events.php");
+ $this->setModuleConfig($this->config->loadConfigFile('sessions', $this->getModulePath()));
+ $this->db = &$this->mods->database;
+ }
+
+ /**
+ * Validate a session using a sessionKey
+ * Looks up wether a session exists and returns sessionData
+ * @access public
+ * @param String SessionKey (optional)
+ * @return SessionData Array
+ */
+ public function start($sessionKey = null) {
+ // Fetch the sessionKey, if it exists
+ $sessionKey = (isset($_COOKIE[$this->cfg->cookie_name]) ? $_COOKIE[$this->cfg->cookie_name] : (isset($_REQUEST['sessionKey']) ? $_REQUEST['sessionKey'] : $sessionKey ));
+
+ // If a sessionKey is given, check it
+ if (!is_null($sessionKey)) {
+ $data = $this->sessionIsValid($sessionKey, true);
+ if ($data !== false) {
+ $udt = $this->convertUserData($data);
+ if (!$this->sessionBlocked($udt)) {
+ return $this->sendUserSession($udt);
+ }
+ }
+ }
+
+ return $this->sendGuestSession();
+ }
+
+ /**
+ * Send a Guest Session to the user
+ * @access private
+ * @return Guest UDT
+ */
+ private function sendGuestSession() {
+ if (isset($_COOKIE[$this->cfg->cookie_name])) {
+ setcookie($this->cfg->cookie_name, '', time()-3600, '/', $this->config->main->SITE_DOMAIN);
+ }
+ $udt = array(
+ 'user_id' => 0,
+ 'user_username' => 'Guest',
+ 'username' => 'Guest',
+ 'user_email' => 'Guest@'.$this->config->main->SITE_DOMAIN,
+ 'email' => 'Guest@'.$this->config->main->SITE_DOMAIN,
+ 'permissions' => array('GUEST' => 'GUEST', 'LOGIN' => 'LOGIN'),
+ 'session_hash' => '0'
+ );
+ $this->udt = $udt;
+ $this->logSessionData();
+ return $udt;
+ }
+
+ /**
+ * Send a user session to the user
+ * Also sets the module UDT to the input
+ * @access private
+ * @param Array UDT
+ * @return UDT
+ */
+ private function sendUserSession($udt) {
+ $udt['username'] = $udt['user_username'];
+ $udt['email'] = $udt['user_email'];
+ $this->udt = $udt;
+ $this->logSessionData();
+ return $udt;
+ }
+
+ /**
+ * Log the session data to the FuzeWorks logger
+ * @access private
+ */
+ private function logSessionData() {
+ $this->logger->newLevel("Activating Session");
+ $this->logger->logInfo("
SessionKey: " . $this->session_hash . "
Username: " . $this->user_username . "
Email: " . $this->user_email . "
Permissions: " . implode('-', $this->permissions));
+ $this->logger->stopLevel();
+ }
+
+ /**
+ * Convert the userdata from the database to UDT
+ * @access private
+ * @param Array SessionData
+ * @return Array Userdata
+ * @todo change this
+ */
+ private function convertUserData($userData) {
+ $udt = array();
+ for ($i=0; $i < count($userData); $i++) {
+ foreach ($userData[$i] as $key => $value) {
+ if (strpos($key, 'user_') === 0 || strpos($key, 'session_') === 0) {
+ $udt[$key] = $value;
+ }
+ }
+ $udt['permissions'][$userData[$i]['tag_name']] = $userData[$i]['tag_name'];
+ }
+ return $udt;
+ }
+
+ /**
+ * Check wether the UDT has a permission tag that blocks the account
+ * @access private
+ * @param Array UDT
+ * @return Boolean true if blocked, false if not
+ */
+ private function sessionBlocked($udt) {
+ if (isset($udt['permissions']['UNVERIFIED']) || isset($udt['permissions']['BLOCKED'])) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check wether a sessionKey is valid and active
+ * @access private
+ * @param String SessionKey
+ * @param Boolean fetchData (wether to return the sessionData)
+ * @return Boolean False if invalid, true if valid and no fetchData, array if valid and fetchData
+ */
+ private function sessionIsValid($sessionKey, $fetchData = false) {
+ $prefix = $this->db->getPrefix();
+ $query = "
+ SELECT *
+ FROM ".$prefix."session_permissions AS permissions
+
+ LEFT JOIN ".$prefix."session_users AS users
+ ON permissions.permission_user_id=users.user_id
+
+ LEFT JOIN ".$prefix."session_tags AS tags
+ ON permissions.permission_tag_id=tags.tag_id
+
+ LEFT JOIN ".$prefix."session_sessions AS sessions
+ ON permissions.permission_user_id=sessions.session_user_id
+
+ WHERE sessions.session_hash = ?
+ AND sessions.session_active = 1
+ ";
+ $stmnt = $this->db->prepare($query);
+ $stmnt->execute(array($sessionKey));
+ $result = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+
+ if (count($result) > 0) {
+ if (is_null($result[0]['session_hash'])) {
+ return false;
+ }
+ if ($fetchData) {
+ return $result;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Logs a user into the system. Checks the password and generates a session hash
+ * @access public
+ * @param String identifier (email or username)
+ * @param String password
+ * @param Boolean Wether to remember the session (true for 100 years, false for incremental)
+ * @param Boolean propagate, wether the login should be propagated to the database (default true)
+ * @todo Add ADMITTED Tag to check wether a user is allowed to log in
+ * @return Array SessionData
+ */
+ public function login($identifier, $password, $remember_me = false, $propagate = true) {
+ // Get the user with this identifier
+ $prefix = $this->db->getPrefix();
+ $query = "
+ SELECT *
+ FROM ".$prefix."session_users AS users
+ WHERE users.user_email = :identifier OR users.user_username = :identifier";
+ $stmnt = $this->db->prepare($query);
+ $stmnt->execute(array('identifier' => $identifier));
+ $result = $stmnt->fetch(\PDO::FETCH_ASSOC);
+
+ // Prepare the return variable
+ $sessionData = array();
+ if (count($result) > 0) {
+ $sessionData = $result;
+ // If user found, check password
+ if (password_verify($password, $result['user_password'])) {
+ // If correct, prepare sessionData
+ // Create Session
+ $one = uniqid();
+ $two = sha1(uniqid() . $identifier);
+ $three = uniqid();
+ $hash = sha1($one . $two . $three);
+
+ // Add SessionInfo to the SessionData Array
+ $info['type'] = 'fuzeworks.sessions';
+ $info['agent'] = (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "");
+ $info['IP'] = (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "UNKNOWN");
+
+ $sessionData['info'] = json_encode($info);
+ $sessionData['ip'] = $info['IP'];
+ $sessionData['session_start'] = date('Y-m-d H:i:s',strtotime("now"));
+ $sessionData['hash'] = $hash;
+ $sessionData['valid_time'] = ($remember_me ? time()+(10*365*24*3600) : time()+3600*720);
+
+ // Add the success value
+ $sessionData['valid'] = true;
+
+ if ($propagate) {
+ $this->propagate($sessionData);
+ }
+ } else {
+ // Password incorrect
+ $sessionData['valid'] = false;
+ $sessionData['reason'] = "PASSWORD_INCORRECT";
+ $sessionData['reason_explained'] = "Username and/or password is incorrect";
+ }
+ } else {
+ // User not found
+ $sessionData['valid'] = false;
+ $sessionData['reason'] = "USER_NOT_FOUND";
+ $sessionData['reason_explained'] = "Username and/or password is incorrect";
+ }
+
+ return $sessionData;
+ }
+
+ /**
+ * Propagate a login to the database and set the cookie. Don't forget to redirect to apply the cookie
+ * @access public
+ * @param Array SessionData
+ * @return Boolean true on success, false on failure
+ */
+ public function propagate($sessionData) {
+ $prefix = $this->db->getPrefix();
+ // The variables to insert
+ $insert_array = array(
+ 'hash' => $sessionData['hash'],
+ 'user_id' => $sessionData['user_id'],
+ 'info' => $sessionData['info'],
+ 'ip' => $sessionData['ip'],
+ 'session_start' => $sessionData['session_start']);
+
+ $query = "
+ INSERT INTO ".$prefix."session_sessions
+ (session_hash,session_user_id,session_info,session_ip,session_start)
+ VALUES (:hash, :user_id, :info, :ip, :session_start)
+ ";
+ $stmnt = $this->db->prepare($query);
+ $stmnt->execute($insert_array);
+ if ($stmnt->rowCount() == 1) {
+ // Set the cookie
+ setcookie($this->cfg->cookie_name, $sessionData['hash'], $sessionData['valid_time'], '/', $this->config->main->SITE_DOMAIN);
+ return true;
+ } else {
+ throw new SessionException("Could not log user in. Database error", 1);
+ return false;
+ }
+ }
+
+ /**
+ * Sign a user out of the system
+ *
+ * @access public
+ * @param String SessionKey (optional)
+ * @param Boolean Propagate the logout to the database (default true)
+ * @return Boolean true on success
+ * @throws SessionException on fatal error
+ */
+ public function logout($sessionKey = null, $propagate = true) {
+ // Fetch the sessionKey, if it exists
+ $sessionKey = (isset($_COOKIE[$this->cfg->cookie_name]) ? $_COOKIE[$this->cfg->cookie_name] : (isset($_REQUEST['sessionKey']) ? $_REQUEST['sessionKey'] : $sessionKey ));
+
+ // If a sessionKey is given, check it
+ if (!is_null($sessionKey)) {
+ // Fetch the session data
+ $data = $this->sessionIsValid($sessionKey, true);
+ if ($data !== false) {
+ // If valid, remove the current session
+ $this->udt = null;
+ if ($propagate) {
+ // If set to propagete, edit the entry in the database
+ $prefix = $this->db->getPrefix();
+ $query = "UPDATE ".$prefix."session_sessions SET session_active = 0 WHERE session_hash = ?";
+ $stmnt = $this->db->prepare($query);
+ $stmnt->execute(array($sessionKey));
+
+ // And after that remove the cookie
+ if ($stmnt->rowCount() == 1) {
+ // Set the cookie
+ setcookie($this->cfg->cookie_name, $sessionKey, date('U') - 3600, '/', $this->config->main->SITE_DOMAIN);
+ return true;
+ }
+
+ throw new SessionException("Could not log user out. Database error", 1);
+ }
+ }
+ }
+
+ throw new SessionException("Could not log user out. SessionKey not found", 1);
+ }
+
+ /**
+ * Register a new User. Features input handling
+ * @access public
+ * @param String Username. Username of the new user
+ * @param String email. Email of the new user
+ * @param String password. Password of the new user
+ * @return Boolean true on success
+ * @throws SessionException on fatal error
+ */
+ public function register($username, $email, $password) {
+ // First match if the username and email are valid
+
+ $errors = [];
+ // Email
+ if (!preg_match('/^[^\W][a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*\@[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*\.[a-zA-Z]{2,4}$/',$email)) {
+ // Invalid
+ $errors[] = 'Invalid Email';
+ }
+
+ // Username
+ if (!preg_match('/^(?=.{1,15}$)[a-zA-Z][a-zA-Z0-9]*(?: [a-zA-Z0-9]+)*$/', $username)) {
+ // Invalid
+ $errors[] = "Invalid Username";
+ }
+
+ // And finally parse the error if there are errors present
+ if (!empty($errors)) {
+ throw new SessionException("Could not register user. " . implode(' .', $errors), 1);
+ }
+
+ // And perform the handling
+ try {
+ return $this->createUser($username, $email, $password, true);
+ } catch (SessionException $e) {
+ throw new SessionException("Could not register user. '" . $e->getMessage() . "'", 1, $e);
+ }
+ }
+
+ /**
+ * Create a new User
+ * @access public
+ * @param String username
+ * @param String email
+ * @param String password
+ * @param Boolean Send Email of registration (default false)
+ * @throws SessionException on fatal error
+ * @return Boolean true on success
+ */
+ public function createUser($username, $email, $password, $send_email = false) {
+ // Prepare the variables
+ $password = password_hash($password, PASSWORD_DEFAULT);
+
+ // Check for the existence of an account
+ $qry = "SELECT * FROM hi_session_users WHERE user_username = :username OR user_email = :email";
+ $stmnt = $this->mods->database->prepare($qry);
+ $stmnt->execute(['username' => $username, 'email' => $email]);
+ $data = $stmnt->fetch(\PDO::FETCH_ASSOC);
+ if (empty($data)) {
+ // And put the data into the database
+ $prefix = $this->db->getPrefix();
+ $qry1 = "INSERT INTO ".$prefix."session_users (user_username,user_password,user_email,verify_code) VALUES (:username,:password,:email,:verify_code)";
+ $qry2 = "INSERT INTO ".$prefix."session_permissions (permission_tag_id,permission_user_id) VALUES (:tag_id,:user_id)";
+
+ $this->mods->database->beginTransaction();
+ $stmnt1 = $this->mods->database->prepare($qry1);
+ $stmnt2 = $this->mods->database->prepare($qry2);
+
+ $stmnt1->execute(['username' => $username, 'password' => $password, 'email' => $email, 'verify_code' => substr(sha1(uniqid()), 0, 15)]);
+ $id = $this->mods->database->lastInsertId();
+ $stmnt2->execute(['tag_id' => 1, 'user_id' => $id]);
+
+ $this->mods->database->commit();
+
+ // After that send a registration mail
+ if ($send_email) {
+ $this->registerMail($id);
+ }
+
+ return true;
+ } else {
+ throw new SessionException("Could not create user. Username or email already exists", 1);
+ return false;
+ }
+ }
+
+ /**
+ * Sends a mail to a user when a registration happens
+ * @access private
+ * @param Int UserID
+ * @param Boolean Verify. Wether the user needs to verify using the email (default false)
+ * @throws SessionException on fatal error
+ * @todo Apply new Template Engine
+ */
+ public function registerMail($userId, $verify = false) {
+ $udt = $this->getUsersByIds(intval($userId));
+ if (empty($udt)) {
+ throw new SessionException("Could not send mail. User not found", 1);
+ }
+ $udt = $udt[0];
+
+ // Load the mailer module
+ $mailer = $this->core->loadMod('techfuze/mailer')->mailer;
+ $mailer->setFrom('no-reply@'.$this->config->main->SITE_DOMAIN, 'Auth Service');
+
+ // First prepare the layout manager
+ // $this->layout->setEngine('PHP');
+
+ // Assign all variables
+ $verifyCode = $udt['user_verify_code'];
+ $verifyURL = '';
+
+ $event = $this->events->fireEvent(new RegisterMailEvent(), $udt, $verifyCode, $verifyURL);
+ if ($event->isCancelled()) {
+ $this->logger->log("Sending of Registration Mail has been cancelled");
+ return false;
+ }
+
+ // Retrieve some variables
+ $udt = $event->udt;
+
+ // Assign new variables
+ $this->layout->assign('serverName', $this->config->main->SERVER_NAME);
+ $this->layout->assign('logo', $this->config->main->SITE_LOGO_URL);
+
+ // More if there is a need to verify
+ if ($verify) {
+ $this->layout->assign('verifyURL', $event->verifyURL);
+ $this->layout->assign('verifyCode', $event->verifyCode);
+ }
+
+ // Check if a custom HTML should be used
+ if ($event->customHtml) {
+ $html = $event->html;
+ } else {
+ // Or retrieve it from a layout file
+ $html = $this->layout->get('email_layout', $this->getModulePath() . "/Views/" );
+ }
+
+ // And finally send it
+ $mailer->addAddress($udt['email']);
+ $mailer->isHTML(true);
+ $mailer->Body = $html;
+ $mailer->Subject = $this->config->main->SERVER_NAME . " | Registration";
+ $mailer->send();
+ if (!empty($mailer->ErrorInfo)) {
+ // Throw Exception if something goes wrong
+ throw new SessionException("Could not send mailer. PHPMailer Error", 1);
+ }
+ }
+
+ /**
+ * Modifies a user entry
+ * @access public
+ * @param Int UserID to edit
+ * @param String column to edit
+ * @param Mixed value to apply
+ * @return true on success
+ * @throws \Exception|SessionException on fatal error
+ */
+ public function modifyUser($userId, $key, $value) {
+ $udt = $this->getUsersByIds($userId)[0];
+ // And fetch tag information
+ $prefix = $this->db->getPrefix();
+ $stmnt = $this->mods->database->prepare("UPDATE ".$prefix."session_users SET $key = ?");
+ $stmnt->execute([$value]);
+ if ($stmnt->rowCount() == 1) {
+ return true;
+ }
+
+ throw new SessionException("Could not modify user. Database error", 1);
+ }
+
+ /**
+ * Changes the password of a user
+ * @access public
+ * @param Int UserID to edit
+ * @param String|null Old password of the user or nothing if trying to change as admin
+ * @param String New password of the user
+ * @return true on success
+ * @throws \Exception|SessionException on fatal error
+ */
+ public function changePassword($userId, $oldPassword = null, $newPassword) {
+ $udt = $this->getUsersByIds($userId)[0];
+ // First check if the oldPassword is correct
+ if (is_null($oldPassword) || password_verify($oldPassword, $udt['user_password'])) {
+ // Then apply the new password
+ $hash = password_hash($newPassword, PASSWORD_DEFAULT);
+ $this->modifyUser($userId, 'user_password', $hash);
+ return true;
+ }
+
+ throw new SessionException("Could not change password. Old password did not match", 1);
+ }
+
+ /**
+ * Suspends a user from using the system
+ * @access public
+ * @param Int UserID
+ * @return true on success
+ * @throws SessionException on fatal error
+ */
+ public function suspendUser($userId) {
+ return $this->removePermission('ADMITTED', $userId, false);
+ }
+
+ /**
+ * Allows a user to log in again
+ * @access public
+ * @param Int UserID
+ * @return true on success
+ * @throws SessionException on fatal error
+ */
+ public function unsuspendUser($userId) {
+ return $this->addPermission('ADMITTED', $userId, false);
+ }
+
+ /**
+ * Removes a user from the system
+ * @access public
+ * @param Int UserID
+ * @return true on success
+ * @throws SessionException on fatal error
+ */
+ public function removeUser($userId) {
+ // First get all relevant data
+ $udt = $this->getUsersByIds($userId)[0];
+ $userId = $udt['user_id'];
+
+ // Remove the active permission, effectively removing the user
+ return $this->removePermission('ACTIVE', $userId, false, true);
+ }
+
+ /**
+ * Verify a user with a code to we can unsuspend them
+ * @access public
+ * @param String VerifyCode
+ * @return true on success
+ * @throws SessionException on fatal error
+ */
+ public function verifyUser($verifyCode) {
+ // And fetch tag information
+ $prefix = $this->db->getPrefix();
+ $stmnt = $this->mods->database->prepare("SELECT * FROM ".$prefix."session_users WHERE user_verify_code = ?");
+ $stmnt->execute([$verifyCode]);
+ $data = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+ if (count($data == 1)) {
+ $id = $data[0]['user_id'];
+ return $this->unsuspendUser($id);
+ } else {
+ throw new SessionException("Could not verify user. Code invalid", 1);
+ }
+ }
+
+ /**
+ * Checks wether a user has permission to a certain action
+ * If a userID is provided, a specific user is checked. Otherwise the current session is used
+ * @access public
+ * @param String PermissionTag
+ * @param Int UserID (optional)
+ * @param Boolean Wether to ignore admin permission (default false)
+ * @throws SessionException on fatal error
+ * @return Boolean true on permission. False on no permission
+ */
+ public function hasPermission($permissionTag, $userId = null, $ignoreAdmin = false) {
+ // First retrieve the UDT
+ if (is_null($userId)) {
+ if (!is_null($this->udt)) {
+ $udt = $this->udt;
+ } else {
+ throw new SessionException("Could not check for permission. No user logged in and no user provided", 1);
+ }
+ } else {
+ $udt = $this->getUsersByIds($userId);
+ if (!empty($udt)) {
+ $udt = $udt[0];
+ } else {
+ throw new SessionException("Could not check for permission. User not found", 1);
+ }
+ }
+
+ // Then read it and check for permission
+ $tag = strtoupper($permissionTag);
+
+ // What type to return if ignoring admin
+ if ($ignoreAdmin) {
+ if (isset($udt['permissions'][$tag])) {
+ return true;
+ }
+ } else {
+ if (isset($udt['permissions'][$tag]) || isset($udt['permissions']['ADMIN'])) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes a permission from a user
+ * If a userID is provided, a specific user is checked. Otherwise the current session is used
+ * @access public
+ * @param String PermissionTag
+ * @param Int UserID (optional)
+ * @param Boolean Wether to remove the tag if it is not used anymore
+ * @param Boolean wether to ignore the ACTIVE tag. Seriously, do not touch this
+ * @throws SessionException on fatal error
+ * @return Boolean true on success
+ */
+ public function removePermission($permissionTag, $userId = null, $removeTag = false, $ignoreActive = false) {
+ // Check if the active tag is given
+ if (!$ignoreActive && strtoupper($permissionTag) == 'ACTIVE') {
+ throw new SessionException("Could not remove permission. ACTIVE tag removal is prohibited", 1);
+ }
+
+ // First retrieve the UDT
+ if (!$this->hasPermission($permissionTag, $userId, true)) {
+ throw new SessionException("Could not remove permission. User does not have permission", 1);
+ }
+
+ // Fetch the user ID
+ if (is_null($userId)) {
+ $user_id = $this->udt['user_id'];
+ } else {
+ $udt = $this->getUsersByIds($userId);
+ if (!empty($udt)) {
+ $udt = $udt[0];
+ $user_id = $udt['user_id'];
+ }
+ }
+
+ // And fetch tag information
+ $prefix = $this->db->getPrefix();
+ $stmnt = $this->mods->database->prepare("SELECT * FROM ".$prefix."session_tags WHERE tag_name = ?");
+ $stmnt->execute([strtoupper($permissionTag)]);
+ $tag = $stmnt->fetch(\PDO::FETCH_ASSOC);
+ if (!empty($tag)) {
+ $tag_id = intval($tag['tag_id']);
+ }
+
+ // And now remove the reference in the database
+ $stmnt = $this->mods->database->prepare("DELETE FROM ".$prefix."session_permissions WHERE permission_tag_id = :tag_id AND permission_user_id = :user_id");
+ $stmnt->execute(['tag_id' => $tag_id, 'user_id' => $user_id]);
+ if ($stmnt->rowCount() == 1) {
+ // Check if the tag is still used
+ if ($removeTag) {
+ $stmnt = $this->mods->database->prepare("SELECT * FROM ".$prefix."session_permissions WHERE permission_tag_id = ?");
+ $stmnt->execute([strtoupper($permissionTag)]);
+ if (count($stmnt->fetchAll(\PDO::FETCH_ASSOC)) == 0) {
+ // Remove the tag
+ $stmnt = $this->mods->database->prepare("DELETE FROM ".$prefix."session_tags WHERE tag_name = ?");
+ $stmnt->execute([strtoupper($permissionTag)]);
+ if ($stmnt->rowCount() == 0) {
+ // Something went wrong
+ throw new SessionException("Could not remove permission tag. Database error", 1);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ throw new SessionException("Could not remove permission. Database error", 1);
+ }
+
+ /**
+ * Adds a permission to a user
+ * If a userID is provided, a specific user is checked. Otherwise the current session is used
+ * @access public
+ * @param String PermissionTag
+ * @param Int UserID (optional)
+ * @throws SessionException on fatal error
+ * @return Boolean true on success
+ */
+ public function addPermission($permissionTag, $userId = null) {
+ // First retrieve the UDT
+ if ($this->hasPermission($permissionTag, $userId, true)) {
+ throw new SessionException("Could not add permission. User does already have permission", 1);
+ }
+
+ // Fetch the user ID
+ if (is_null($userId)) {
+ $user_id = $this->udt['user_id'];
+ } else {
+ $udt = $this->getUsersByIds($userId);
+ if (!empty($udt)) {
+ $udt = $udt[0];
+ $user_id = $udt['user_id'];
+ }
+ }
+
+ // Check if the tag already exists
+ $prefix = $this->db->getPrefix();
+ $stmnt = $this->mods->database->prepare("SELECT * FROM ".$prefix."session_tags WHERE tag_name = ?");
+ $stmnt->execute([strtoupper($permissionTag)]);
+ $d = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+
+ if (count($d) == 0) {
+ // Create tag
+ $stmnt = $this->mods->database->prepare("INSERT INTO ".$prefix."session_tags (tag_name) VALUES (:tag_name)");
+ $stmnt->execute(['tag_name' => strtoupper($permissionTag)]);
+ $id = $stmnt->lastInsertId();
+ } elseif (count($d) == 1) {
+ // Get ID
+ $data = $d[0];
+ $id = $data['tag_id'];
+ }
+
+ // Add the permission
+ $stmnt = $this->mods->database->prepare("INSERT INTO ".$prefix."session_permissions (permission_tag_id,permission_user_id) VALUES (:permission_tag_id,:permission_user_id)");
+ $stmnt->execute(['permission_tag_id' => $id, 'permission_user_id' => $user_id]);
+
+ if ($stmnt->rowCount() == 1) {
+ return true;
+ }
+
+ throw new SessionException("Could not add permission. Database Error", 1);
+ }
+
+ /**
+ * Get users by Usernames
+ * @access public
+ * @param Array of usernames
+ * @return Array of UDT's
+ * @todo Support for 1 parameter (STRING)
+ */
+ public function getUsersByName($usernames = array()) {
+ $prefix = $this->db->getPrefix();
+ $query = "
+ SELECT *
+ FROM ".$prefix."session_permissions AS permissions
+
+ LEFT JOIN ".$prefix."session_users AS users
+ ON permissions.permission_user_id=users.user_id
+
+ LEFT JOIN ".$prefix."session_tags AS tags
+ ON permissions.permission_tag_id=tags.tag_id
+
+ WHERE users.user_username = ?
+ ";
+ $stmnt = $this->mods->database->prepare($query);
+ $users = array();
+ for ($i=0; $i < count($usernames); $i++) {
+ $username = $usernames[$i];
+ $stmnt->execute(array($username));
+ $user_data = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+ if (!empty($user_data)) {
+ $users[] = $this->handleUserSelectData($user_data);
+ }
+ }
+ return $users;
+ }
+
+ /**
+ * Get users by Identifier
+ * @access public
+ * @param Array of user ids OR Int of single ID
+ * @return Array of UDT's
+ */
+ public function getUsersByIds($ids = array()) {
+ if (is_int($ids)) {
+ $ids = array($ids);
+ }
+
+ $prefix = $this->db->getPrefix();
+ $query = "
+ SELECT *
+ FROM ".$prefix."session_permissions AS permissions
+
+ LEFT JOIN ".$prefix."session_users AS users
+ ON permissions.permission_user_id=users.user_id
+
+ LEFT JOIN ".$prefix."session_tags AS tags
+ ON permissions.permission_tag_id=tags.tag_id
+
+ WHERE users.user_id = ?
+ ";
+ $stmnt = $this->mods->database->prepare($query);
+ $users = array();
+ for ($i=0; $i < count($ids); $i++) {
+ $id = $ids[$i];
+ $stmnt->execute(array($id));
+ $user_data = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+ if (!empty($user_data)) {
+ $users[] = $this->handleUserSelectData($user_data);
+ }
+ }
+
+ return $users;
+ }
+
+ /**
+ * Get users by Email address
+ * @access public
+ * @param Array of emails
+ * @return Array of UDT's
+ * @todo Support for 1 parameter (STRING)
+ */
+ public function getUsersByEmails($emails = array()) {
+ $prefix = $this->db->getPrefix();
+ $query = "
+ SELECT *
+ FROM ".$prefix."session_permissions AS permissions
+
+ LEFT JOIN ".$prefix."session_users AS users
+ ON permissions.permission_user_id=users.user_id
+
+ LEFT JOIN ".$prefix."session_tags AS tags
+ ON permissions.permission_tag_id=tags.tag_id
+
+ WHERE users.user_email = ?
+ ";
+ $stmnt = $this->mods->database->prepare($query);
+ $users = array();
+ for ($i=0; $i < count($emails); $i++) {
+ $email = $emails[$i];
+ $stmnt->execute(array($email));
+ $user_data = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+ if (!empty($user_data)) {
+ $users[] = $this->handleUserSelectData($user_data);
+ }
+ }
+ return $users;
+ }
+
+ /**
+ * Get all users who have a specific permission tag
+ * @access public
+ * @param String Permission Tag
+ * @return Array of UDT's
+ * @todo Support for 1 parameter (STRING)
+ */
+ public function getUsersByPermissions($permissionTags = array()) {
+ $prefix = $this->db->getPrefix();
+ $query = "
+ SELECT *
+ FROM ".$prefix."session_permissions AS permissions
+
+ LEFT JOIN ".$prefix."session_users AS users
+ ON permissions.permission_user_id=users.user_id
+
+ LEFT JOIN ".$prefix."session_tags AS tags
+ ON permissions.permission_tag_id=tags.tag_id
+
+ WHERE tags.tag_name = ?
+ ";
+ $stmnt = $this->mods->database->prepare($query);
+ $users = array();
+ for ($i=0; $i < count($permissionTags); $i++) {
+ $tag = $permissionTags[$i];
+ $stmnt->execute(array($tag));
+
+ $user_data = $stmnt->fetchAll(\PDO::FETCH_ASSOC);
+ if (!empty($user_data)) {
+ $users[] = $this->getUsersByIds(array($user_data[0]['user_id']))[0];
+ }
+ }
+ return $users;
+ }
+
+ /**
+ * Internal function used by the getUsersby* functions
+ * @access private
+ * @param Array PDO Data result
+ * @return UDT
+ */
+ private function handleUserSelectData($user_data) {
+ $user = array();
+ $basic = $user_data[0];
+ foreach ($basic as $key => $value) {
+ if (strpos($key, 'user_') === 0) {
+ $user[$key] = $value;
+ }
+ }
+ $user['permissions'] = array();
+
+ for ($j=0; $j < count($user_data); $j++) {
+ $user['permissions'][ $user_data[$j]['tag_name'] ] = $user_data[$j]['tag_name'];
+ }
+ $user['username'] = $user['user_username'];
+ $user['email'] = $user['user_email'];
+ return $user;
+ }
+
+ /**
+ * Fetch data from the current UDT
+ * @access public
+ * @param Mixed Key
+ * @return Mixed Value
+ */
+ public function __get($key) {
+ return $this->udt[$key];
+ }
+
+
+
+}
+
+/**
+ * Exception class for the Sessions Module
+ */
+class SessionException extends \Exception {}
+
+?>
\ No newline at end of file
diff --git a/Modules/sessions/config.sessions.php b/Modules/sessions/config.sessions.php
new file mode 100644
index 0000000..6c022e1
--- /dev/null
+++ b/Modules/sessions/config.sessions.php
@@ -0,0 +1,6 @@
+ 'FuzeCookie',
+
+);
diff --git a/Modules/sessions/database.sessions.php b/Modules/sessions/database.sessions.php
new file mode 100644
index 0000000..e69de29
diff --git a/Modules/sessions/moduleInfo.php b/Modules/sessions/moduleInfo.php
new file mode 100644
index 0000000..9d36907
--- /dev/null
+++ b/Modules/sessions/moduleInfo.php
@@ -0,0 +1,18 @@
+ '\Module\Sessions\Main',
+ 'module_file' => 'class.sessions.php',
+ 'module_name' => 'sessions',
+
+ 'dependencies' => array('techfuze/database'),
+
+ 'name' => 'Sessions',
+ 'description' => 'Lightweight user and permissions system',
+ 'author' => 'TechFuze',
+ 'version' => '1.0.0.0',
+ 'website' => 'http://fuzeworks.techfuze.net/',
+
+ 'date_created' => '23-02-2015',
+ 'date_updated' => '19-08-2015',
+);