diff --git a/.gitignore b/.gitignore
index f56cefe..e1e6c5e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,19 @@
-test
-Experimental
-vendor
-composer.lock
\ No newline at end of file
+# Global
+.phpunit*
+.composer
+composer.lock
+package-lock.json
+vendor/
+test/
+*.tests.php
+workflows
+
+# OS Generated
+.DS_Store*
+ehthumbs.db
+Icon?
+Thumbs.db
+*.swp
+
+# phpstorm
+.idea/*
diff --git a/README.md b/README.md
index 7846809..e35cfe9 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-
Leaf Auth Module
+ Leaf Auth v2
@@ -10,7 +10,9 @@
[![Total Downloads](https://poser.pugx.org/leafs/auth/downloads)](https://packagist.org/packages/leafs/auth)
[![License](https://poser.pugx.org/leafs/auth/license)](https://packagist.org/packages/leafs/auth)
-Leaf's auth helper packaged as a serve-yourself module.
+Leaf auth is a simple but powerful module which comes with powerful functions for handling all your authentication needs.
+
+v2 comes with tons of fixes, improvements and upgrades. Running on top of leaf db v2, it also has support for other database types like PostgreSQL, Sqlite and many more.
## Installation
@@ -20,6 +22,84 @@ You can easily install Leaf using [Composer](https://getcomposer.org/).
composer require leafs/auth
```
+Or with leaf db
+
+```sh
+leaf install auth
+```
+
+## Basic Usage
+
+After installing leaf auth, you need to connect to your database. v2 presents additional ways to achieve this.
+
+### connect
+
+The connect method allows you to pass in your database connection parameters directly to leaf auth.
+
+```php
+auth()->connect('127.0.0.1', 'dbname', 'username', 'password');
+```
+
+### autoConnect
+
+This method creates a database connection using your env variables.
+
+```env
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=LEAF_DB_NAME
+DB_USERNAME=LEAF_DB_USERNAME
+DB_PASSWORD=
+```
+
+And call `autoConnect` in your app.
+
+```php
+auth()->autoConnect();
+```
+
+### db connection (v2 only)
+
+Leaf auth now allows you to directly pass a PDO connection into leaf auth. This allows you to share your connection with leaf auth and avoid multiple connections.
+
+```php
+$auth = new Leaf\Auth;
+$auth->dbConnection($pdoConnecction);
+```
+
+This also means that you can share you leaf db v2 connection with leaf auth like this:
+
+```php
+$auth = new Leaf\Auth;
+$auth->dbConnection($db->connection());
+```
+
+### Leaf db (auth v2 + leaf 3 only)
+
+If you are using leaf auth in a leaf 3 app, you will have access to the `auth` global as shown in some of the above connections. Along with this, if you already have a leaf db connection, you no longer need to explicitly connect to your database. Leaf auth searches for a leaf db instance and connects to it automatically.
+
+**Note that this only works in a leaf 3 app and only if you already have a leaf db connection.**
+
+```php
+connect('127.0.0.1', 'dbname', 'username', 'password');
+
+// you can use auth straight away without any connect
+auth()->login(...);
+```
+
+## 📚 Auth methods
+
+After connecting your db, you can use any of the methods below.
+
+WIP: This page will be updated
+
+## ⚡️ Funtional Mode
+
+When using leaf auth in a leaf 3 app, you will have access to the `auth`, `guard`, `hasAuth` and `sessionUser` globals.
+
## 💬 Stay In Touch
- [Twitter](https://twitter.com/leafphp)
@@ -85,6 +165,13 @@ And to all our existing cash/code contributors, we love you all ❤️
Vano
+
+
+
+
+ Casprine
+
+ |
diff --git a/composer.json b/composer.json
index 6079f26..e389b0d 100644
--- a/composer.json
+++ b/composer.json
@@ -34,9 +34,9 @@
"require": {
"leafs/date": "^1.0",
"leafs/password": "^1.0",
- "leafs/session": "^1.0",
- "leafs/db": "^1.0",
- "leafs/form": "^1.0",
- "leafs/http": "^1.0"
+ "leafs/session": "^1.1",
+ "leafs/db": "^2.0",
+ "leafs/form": "^1.1",
+ "leafs/http": "^1.2.1"
}
}
diff --git a/src/Auth.php b/src/Auth.php
old mode 100755
new mode 100644
index fdb6fde..71e73db
--- a/src/Auth.php
+++ b/src/Auth.php
@@ -2,222 +2,539 @@
namespace Leaf;
+use Leaf\Auth\Core;
+use Leaf\Helpers\Authentication;
+use Leaf\Helpers\Password;
+
/**
* Leaf Simple Auth
* -------------------------
- * Authentication made easy.
+ * Simple, straightforward authentication.
*
* @author Michael Darko
* @since 1.5.0
* @version 2.0.0
*/
-class Auth
+class Auth extends Core
{
/**
- * Create a db connection
+ * Simple user login
+ *
+ * @param string table: Table to look for users
+ * @param array $credentials User credentials
*
- * @param string $host The db name
- * @param string $user
- * @param string $password
- * @param string $dbname
+ * @return array|null null or all user info + tokens + session data
*/
- public static function connect(string $host, string $user, string $password, string $dbname): void
- {
- Auth\Core::connect($host, $user, $password, $dbname);
- }
-
- /**
- * Create a database connection from env variables
- */
- public static function autoConnect()
- {
- Auth\Core::autoConnect();
- }
-
- /**
- * Set auth config
- */
- public static function config($config, $value = null)
- {
- return Auth\Core::config($config, $value);
- }
-
- /**
- * Simple user login
- *
- * @param string table: Table to look for users
- * @param array $credentials User credentials
- * @param array $validate Validation for parameters
- *
- * @return array user: all user info + tokens + session data
- */
- public static function login(string $table, array $credentials, array $validate = []): array
+ public static function login(
+ string $table,
+ array $credentials
+ ) {
+ static::leafDbConnect();
+ if (static::config('USE_SESSION')) {
+ static::useSession();
+ }
+
+ $passKey = static::$settings['PASSWORD_KEY'];
+ $password = $credentials[$passKey] ?? null;
+
+ if (isset($credentials[$passKey])) {
+ unset($credentials[$passKey]);
+ } else {
+ static::$settings['AUTH_NO_PASS'] = true;
+ }
+
+ $user = static::$db->select($table)->where($credentials)->fetchAssoc();
+
+ if (!$user) {
+ static::$errors['auth'] = static::$settings['LOGIN_PARAMS_ERROR'];
+ return null;
+ }
+
+ if (static::$settings['AUTH_NO_PASS'] === false) {
+ $passwordIsValid = true;
+
+ if (static::$settings['PASSWORD_VERIFY'] !== false && isset($user[$passKey])) {
+ if (is_callable(static::$settings['PASSWORD_VERIFY'])) {
+ $passwordIsValid = call_user_func(static::$settings['PASSWORD_VERIFY'], $password, $user[$passKey]);
+ } else if (static::$settings['PASSWORD_VERIFY'] === Password::MD5) {
+ $passwordIsValid = (md5($password) === $user[$passKey]);
+ } else {
+ $passwordIsValid = Password::verify($password, $user[$passKey]);
+ }
+ }
+
+ if (!$passwordIsValid) {
+ static::$errors['password'] = static::$settings['LOGIN_PASSWORD_ERROR'];
+ return null;
+ }
+ }
+
+ $token = Authentication::generateSimpleToken(
+ $user[static::$settings['ID_KEY']],
+ static::config('TOKEN_SECRET'),
+ static::config('TOKEN_LIFETIME')
+ );
+
+ if (isset($user[static::$settings['ID_KEY']])) {
+ $userId = $user[static::$settings['ID_KEY']];
+ }
+
+ if (static::$settings['HIDE_ID']) {
+ unset($user[static::$settings['ID_KEY']]);
+ }
+
+ if (static::$settings['HIDE_PASSWORD'] && (isset($user[$passKey]) || !$user[$passKey])) {
+ unset($user[$passKey]);
+ }
+
+ if (!$token) {
+ static::$errors = array_merge(static::$errors, Authentication::errors());
+ return null;
+ }
+
+ if (static::config('USE_SESSION')) {
+ if (isset($userId)) {
+ $user[static::$settings['ID_KEY']] = $userId;
+ }
+
+ static::$session->set('AUTH_USER', $user);
+ static::$session->set('HAS_SESSION', true);
+
+ if (static::config('SAVE_SESSION_JWT')) {
+ static::$session->set('AUTH_TOKEN', $token);
+ }
+
+ exit(header('location: ' . static::config('GUARD_HOME')));
+ }
+
+ $response['user'] = $user;
+ $response['token'] = $token;
+
+ return $response;
+ }
+
+ /**
+ * Simple user registration
+ *
+ * @param string $table Table to store user in
+ * @param array $credentials Information for new user
+ * @param array $uniques Parameters which should be unique
+ *
+ * @return array null or all user info + tokens + session data
+ */
+ public static function register(
+ string $table,
+ array $credentials,
+ array $uniques = []
+ ) {
+ static::leafDbConnect();
+
+ $passKey = static::$settings['PASSWORD_KEY'];
+
+ if (!isset($credentials[$passKey])) {
+ static::$settings['AUTH_NO_PASS'] = true;
+ }
+
+ if (static::$settings['AUTH_NO_PASS'] === false) {
+ if (static::$settings['PASSWORD_ENCODE'] !== false) {
+ if (is_callable(static::$settings['PASSWORD_ENCODE'])) {
+ $credentials[$passKey] = call_user_func(static::$settings['PASSWORD_ENCODE'], $credentials[$passKey]);
+ } else if (static::$settings['PASSWORD_ENCODE'] === 'md5') {
+ $credentials[$passKey] = md5($credentials[$passKey]);
+ } else {
+ $credentials[$passKey] = Password::hash($credentials[$passKey]);
+ }
+ }
+ }
+
+ if (static::$settings['USE_TIMESTAMPS']) {
+ $now = Date::now();
+ $credentials['created_at'] = $now;
+ $credentials['updated_at'] = $now;
+ }
+
+ if (static::$settings['USE_UUID'] !== false) {
+ $credentials[static::$settings['ID_KEY']] = static::$settings['USE_UUID'];
+ }
+
+ try {
+ $query = static::$db->insert($table)->params($credentials)->unique($uniques)->execute();
+ } catch (\Throwable $th) {
+ trigger_error($th->getMessage());
+ }
+
+ if (!$query) {
+ static::$errors = array_merge(static::$errors, static::$db->errors());
+ return null;
+ }
+
+ $user = static::$db->select($table)->where($credentials)->fetchAssoc();
+
+ if (!$user) {
+ static::$errors = array_merge(static::$errors, static::$db->errors());
+ return null;
+ }
+
+ $token = Authentication::generateSimpleToken(
+ $user[static::$settings['ID_KEY']],
+ static::config('TOKEN_SECRET'),
+ static::config('TOKEN_LIFETIME')
+ );
+
+ if (isset($user[static::$settings['ID_KEY']])) {
+ $userId = $user[static::$settings['ID_KEY']];
+ }
+
+ if (static::$settings['HIDE_ID']) {
+ unset($user[static::$settings['ID_KEY']]);
+ }
+
+ if (static::$settings['HIDE_PASSWORD'] && (isset($user[$passKey]) || !$user[$passKey])) {
+ unset($user[$passKey]);
+ }
+
+ if (!$token) {
+ static::$errors = array_merge(static::$errors, Authentication::errors());
+ return null;
+ }
+
+ if (static::config('USE_SESSION')) {
+ if (static::config('SESSION_ON_REGISTER')) {
+ if (isset($userId)) {
+ $user[static::$settings['ID_KEY']] = $userId;
+ }
+
+ static::$session->set('AUTH_USER', $user);
+ static::$session->set('HAS_SESSION', true);
+
+ if (static::config('SAVE_SESSION_JWT')) {
+ static::$session->set('AUTH_TOKEN', $token);
+ }
+
+ exit(header('location: ' . static::config('GUARD_HOME')));
+ } else {
+ exit(header('location: ' . static::config('GUARD_LOGIN')));
+ }
+ }
+
+ $response['user'] = $user;
+ $response['token'] = $token;
+
+ return $response;
+ }
+
+ /**
+ * Simple user update
+ *
+ * @param string $table Table to store user in
+ * @param array $credentials New information for user
+ * @param array $where Information to find user by
+ * @param array $uniques Parameters which should be unique
+ *
+ * @return array all user info + tokens + session data
+ */
+ public static function update(string $table, array $credentials, array $uniques = [])
{
- return Auth\Login::user($table, $credentials, $validate);
- }
-
- /**
- * Simple user registration
- *
- * @param string $table Table to store user in
- * @param array $credentials Information for new user
- * @param array $uniques Parameters which should be unique
- * @param array $validate Validation for parameters
- *
- * @return array user: all user info + tokens + session data
- */
- public static function register(string $table, array $credentials, array $uniques = [], array $validate = []): array
+ static::leafDbConnect();
+ if (static::config('USE_SESSION')) {
+ static::useSession();
+ }
+
+ $passKey = static::$settings['PASSWORD_KEY'];
+ $loggedInUser = static::user();
+
+ if (!$loggedInUser) {
+ static::$errors['auth'] = 'Not authenticated';
+ return null;
+ }
+
+ $where = isset($loggedInUser[static::$settings['ID_KEY']]) ? [static::$settings['ID_KEY'] => $loggedInUser[static::$settings['ID_KEY']]] : $loggedInUser;
+
+ if (!isset($credentials[$passKey])) {
+ static::$settings['AUTH_NO_PASS'] = true;
+ }
+
+ if (
+ static::$settings['AUTH_NO_PASS'] === false &&
+ static::$settings['PASSWORD_ENCODE'] !== false
+ ) {
+ if (is_callable(static::$settings['PASSWORD_ENCODE'])) {
+ $credentials[$passKey] = call_user_func(static::$settings['PASSWORD_ENCODE'], $credentials[$passKey]);
+ } else if (static::$settings['PASSWORD_ENCODE'] === 'md5') {
+ $credentials[$passKey] = md5($credentials[$passKey]);
+ } else {
+ $credentials[$passKey] = Password::hash($credentials[$passKey]);
+ }
+ }
+
+ if (static::$settings['USE_TIMESTAMPS']) {
+ $credentials['updated_at'] = Date::now();
+ }
+
+ if (count($uniques) > 0) {
+ foreach ($uniques as $unique) {
+ if (!isset($credentials[$unique])) {
+ trigger_error("$unique not found in credentials.");
+ }
+
+ $data = static::$db->select($table)->where($unique, $credentials[$unique])->fetchAssoc();
+
+ $wKeys = array_keys($where);
+ $wValues = array_values($where);
+
+ if (isset($data[$wKeys[0]]) && $data[$wKeys[0]] != $wValues[0]) {
+ static::$errors[$unique] = "$unique already exists";
+ }
+ }
+
+ if (count(static::$errors) > 0) return null;
+ }
+
+ try {
+ $query = static::$db->update($table)->params($credentials)->where($where)->execute();
+ } catch (\Throwable $th) {
+ trigger_error($th->getMessage());
+ }
+
+ if (!$query) {
+ static::$errors = array_merge(static::$errors, static::$db->errors());
+ return null;
+ }
+
+ if (isset($credentials['updated_at'])) {
+ unset($credentials['updated_at']);
+ }
+
+ $user = static::$db->select($table)->where($credentials)->fetchAssoc();
+ if (!$user) {
+ static::$errors = array_merge(static::$errors, static::$db->errors());
+ return null;
+ }
+
+ $token = Authentication::generateSimpleToken(
+ $user[static::$settings['ID_KEY']],
+ static::config('TOKEN_SECRET'),
+ static::config('TOKEN_LIFETIME')
+ );
+
+ if (isset($user[static::$settings['ID_KEY']])) {
+ $userId = $user[static::$settings['ID_KEY']];
+ }
+
+ if (static::$settings['HIDE_ID'] && isset($user[static::$settings['ID_KEY']])) {
+ unset($user[static::$settings['ID_KEY']]);
+ }
+
+ if (static::$settings['HIDE_PASSWORD'] && (isset($user[$passKey]) || !$user[$passKey])) {
+ unset($user[$passKey]);
+ }
+
+ if (!$token) {
+ static::$errors = array_merge(static::$errors, Authentication::errors());
+ return null;
+ }
+
+ if (static::config('USE_SESSION')) {
+ if (isset($userId)) {
+ $user[static::$settings['ID_KEY']] = $userId;
+ }
+
+ static::$session->set('AUTH_USER', $user);
+ static::$session->set('HAS_SESSION', true);
+
+ if (static::config('SAVE_SESSION_JWT')) {
+ static::$session->set('AUTH_TOKEN', $token);
+ }
+
+ return $user;
+ }
+
+ $response['user'] = $user;
+ $response['token'] = $token;
+
+ return $response;
+ }
+
+ /**
+ * Validation for parameters
+ *
+ * @param array $rules Rules for parameter validation
+ */
+ public function validate(array $rules): bool
+ {
+ $validation = Form::validate($rules);
+
+ if (!$validation) {
+ static::$errors = array_merge(static::$errors, Form::errors());
+ }
+
+ return $validation;
+ }
+
+ /**
+ * Manually start an auth session
+ */
+ public static function useSession()
+ {
+ static::config('USE_SESSION', true);
+ static::$session = Auth\Session::init();
+ }
+
+ /**
+ * Throw a 'use session' warning
+ */
+ protected static function sessionCheck()
+ {
+ if (!static::config('USE_SESSION')) {
+ trigger_error('Turn on USE_SESSION to use this feature.');
+ }
+
+ if (!static::$session) {
+ static::useSession();
+ }
+ }
+
+ /**
+ * A simple auth guard: 'guest' pages can't be viewed when logged in,
+ * 'auth' pages can't be viewed without authentication
+ *
+ * @param string $type The type of guard/guard options
+ */
+ public static function guard(string $type)
+ {
+ static::sessionCheck();
+
+ if ($type === 'guest' && static::status()) {
+ exit(header('location: ' . static::config('GUARD_HOME'), true, 302));
+ }
+
+ if ($type === 'auth' && !static::status()) {
+ exit(header('location: ' . static::config('GUARD_LOGIN'), true, 302));
+ }
+ }
+
+ /**
+ * Check session status
+ */
+ public static function status()
+ {
+ static::sessionCheck();
+
+ return static::$session->get('AUTH_USER') ?? false;
+ }
+
+ /**
+ * Return the user id encoded in token or session
+ */
+ public static function id()
+ {
+ static::leafDbConnect();
+
+ if (static::config('USE_SESSION')) {
+ return static::$session->get('AUTH_USER')[static::$settings['ID_KEY']] ?? null;
+ }
+
+ $payload = static::validateToken(static::config('TOKEN_SECRET'));
+ if (!$payload) return null;
+ return $payload->user_id;
+ }
+
+ /**
+ * Get the current user data from token
+ *
+ * @param string $table The table to look for user
+ * @param array $hidden Fields to hide from user array
+ */
+ public static function user(string $table = 'users', array $hidden = [])
+ {
+ if (!static::id()) {
+ if (static::config('USE_SESSION')) {
+ return static::$session->get('AUTH_USER');
+ }
+
+ return null;
+ }
+
+ $user = static::$db->select($table)->where('id', static::id())->fetchAssoc();
+
+ if (count($hidden) > 0) {
+ foreach ($hidden as $item) {
+ if (isset($user[$item]) || !$user[$item]) {
+ unset($user[$item]);
+ }
+ }
+ }
+
+ return $user;
+ }
+
+ /**
+ * End a session
+ *
+ * @param string $location A route to redirect to after logout
+ */
+ public static function logout(?string $location = null)
+ {
+ static::sessionCheck();
+
+ static::$session->destroy();
+
+ if (is_string($location)) {
+ $route = static::config($location) ?? $location;
+ return \Leaf\Http\Response::redirect($route);
+ }
+ }
+
+ /**
+ * Session last active
+ */
+ public static function lastActive()
{
- return Auth\Register::user($table, $credentials, $uniques, $validate);
- }
-
- /**
- * Simple user update
- *
- * @param string $table Table to store user in
- * @param array $credentials New information for user
- * @param array $where Information to find user by
- * @param array $uniques Parameters which should be unique
- * @param array $validate Validation for parameters
- *
- * @return array user: all user info + tokens + session data
- */
- public static function update(string $table, array $credentials, array $where, array $uniques = [], array $validate = []): array
+ static::sessionCheck();
+
+ return time() - static::$session->get('SESSION_LAST_ACTIVITY');
+ }
+
+ /**
+ * Refresh session
+ *
+ * @param bool $clearData Remove existing session data
+ */
+ public static function refresh(bool $clearData = true)
+ {
+ static::sessionCheck();
+
+ $success = static::$session->regenerate($clearData);
+
+ static::$session->set('SESSION_STARTED_AT', time());
+ static::$session->set('SESSION_LAST_ACTIVITY', time());
+ static::$session->set('AUTH_SESISON', true);
+
+ return $success;
+ }
+
+ /**
+ * Define/Return session middleware
+ *
+ * @param string $name The name of the middleware to set/get
+ * @param callable|null $handler The handler for the middleware
+ */
+ public static function middleware(string $name, ?callable $handler = null)
{
- return Auth\User::update($table, $credentials, $where, $uniques, $validate);
- }
-
- /**
- * Validate Json Web Token
- *
- * @param string $token The token validate
- * @param string|null $secretKey The secret key used to encode token
- */
- public static function validate(string $token, string $secretKey = null)
- {
- return Auth\User::validate($token, $secretKey);
- }
-
- /**
- * Validate Bearer Token
- *
- * @param string|null $secretKey The secret key used to encode token
- */
- public static function validateToken(string $secretKey = null)
- {
- return Auth\User::validateToken($secretKey);
- }
-
- /**
- * Get Bearer token
- */
- public static function getBearerToken()
- {
- return Auth\User::getBearerToken();
- }
-
- /**
- * Get the current user data from token
- *
- * @param string $table The table to look for user
- * @param array $hidden Fields to hide from user array
- */
- public static function user(string $table = "users", array $hidden = [])
- {
- return Auth\User::info($table, $hidden);
- }
-
- /**
- * Return the user id encoded in token
- */
- public static function id()
- {
- return Auth\User::id();
- }
-
- /**
- * Return form field
- */
- public static function get($param)
- {
- return Auth\Core::$form->get($param);
- }
-
- /**
- * Manually start an auth session
- */
- public static function useSession()
- {
- Auth\Session::init();
- }
-
- /**
- * Session Length
- */
- public static function sessionLength()
- {
- return Auth\Session::length();
- }
-
- /**
- * Session last active
- *
- * @deprecated Use `Auth\Session::lastActive()` instead
- */
- public static function sessionActive()
- {
- return Auth\Session::lastActive();
- }
-
- /**
- * Check session status
- */
- protected static function session()
- {
- return Auth\Session::status();
- }
-
- /**
- * End a session
- */
- public static function endSession($location = null)
- {
- return Auth\Session::end($location);
- }
-
- /**
- * Define/Return session middleware
- *
- * **This method only works with session auth**
- */
- public static function middleware(string $name, callable $handler = null)
- {
- return Auth\Session::middleware($name, $handler);
- }
-
- /**
- * Save some data to auth session
- *
- * @deprecated Use `Auth::save()` instead
- */
- public static function saveToSession($key, $data = null)
- {
- Auth\Session::save($key, $data);
- }
-
- /**
- * Save some data to auth session
- */
- public static function save($key, $data = null)
- {
- Auth\Session::save($key, $data);
- }
-
- /**
- * Get all authentication errors as associative array
- */
- public static function errors(): array
- {
- return Auth\Core::errors();
- }
+ static::sessionCheck();
+
+ if (!$handler) return static::$middleware[$name];
+
+ static::$middleware[$name] = $handler;
+ }
+
+ /**
+ * Check how long a session has been going on
+ */
+ public static function length()
+ {
+ static::sessionCheck();
+
+ return time() - static::$session->get('SESSION_STARTED_AT');
+ }
}
diff --git a/src/Auth/Core.php b/src/Auth/Core.php
index 384e1e7..ef65478 100644
--- a/src/Auth/Core.php
+++ b/src/Auth/Core.php
@@ -2,8 +2,7 @@
namespace Leaf\Auth;
-use Leaf\Db;
-use Leaf\Form;
+use Leaf\Helpers\Authentication;
/**
* Leaf Simple Auth [Core]
@@ -19,17 +18,7 @@ class Core
/**
* All errors caught
*/
- protected static $errorsArray = [];
-
- /**
- * @var \Leaf\Http\Session
- */
- protected static $session;
-
- /**
- * All defined session middleware
- */
- protected static $middleware = [];
+ protected static $errors = [];
/**
* Auth Settings
@@ -60,56 +49,87 @@ class Core
/**
* @var \Leaf\Db
*/
- public static $db;
+ protected static $db;
/**
- * @var \Leaf\Form
+ * @var \Leaf\Http\Session
*/
- public static $form;
-
- public function __construct($useSession = false)
- {
- static::$form = new Form;
- static::$db = new Db();
+ protected static $session;
- if ($useSession) {
- static::$useSession();
- }
+ /**
+ * Connect leaf auth to the database
+ *
+ * @param string|array $host Host Name or full config
+ * @param string $dbname Database name
+ * @param string $user Database username
+ * @param string $password Database password
+ * @param string $dbtype Type of database: mysql, postgres, sqlite, ...
+ * @param array $pdoOptions Options for PDO connection
+ */
+ public static function connect(
+ $host,
+ string $dbname,
+ string $user,
+ string $password,
+ string $dbtype,
+ array $pdoOptions = []
+ ) {
+ $db = new \Leaf\Db();
+ $db->connect($host, $dbname, $user, $password, $dbtype, $pdoOptions);
}
/**
- * Create a db connection
- *
- * @param string $host The db name
- * @param string $user
- * @param string $password
- * @param string $dbname
+ * Connect to database using environment variables
+ *
+ * @param array $pdoOptions Options for PDO connection
*/
- public static function connect(string $host, string $user, string $password, string $dbname): void
+ public function autoConnect(array $pdoOptions = [])
{
- static::$form = new Form;
- static::$db = new Db;
+ $this->connect(
+ getenv('DB_HOST'),
+ getenv('DB_DATABASE'),
+ getenv('DB_USERNAME'),
+ getenv('DB_PASSWORD'),
+ getenv('DB_CONNECTION') ? getenv('DB_CONNECTION') : 'mysql',
+ $pdoOptions,
+ );
+ }
- static::$db->connect($host, $user, $password, $dbname);
+ /**
+ * Pass in db connetion instance directly
+ *
+ * @param \PDO $connection A connection instance of your db
+ */
+ public static function dbConnection(\PDO $connection)
+ {
+ $db = new \Leaf\Db();
+ $db->connection($connection);
+ static::$db = $db;
}
/**
- * Create a database connection from env variables
+ * Auto connect to leaf db
*/
- public static function autoConnect(): void
+ protected static function leafDbConnect()
{
- static::connect(
- getenv("DB_HOST"),
- getenv("DB_USERNAME"),
- getenv("DB_PASSWORD"),
- getenv("DB_DATABASE")
- );
+ if (!static::$db && function_exists('db')) {
+ if (db()->connection() instanceof \PDO) {
+ static::$db = db();
+ }
+ }
+
+ if (!static::$db) {
+ trigger_error('You need to connect to your database first');
+ }
}
/**
* Set auth config
+ *
+ * @param string|array $config The auth config key or array of config
+ * @param string $value The value if $config is a string
*/
- public static function config($config, $value = null)
+ public static function config($config, ?string $value = null)
{
if (is_array($config)) {
foreach ($config as $key => $configValue) {
@@ -122,13 +142,47 @@ public static function config($config, $value = null)
}
/**
- * Exception for experimental features
+ * Validate Json Web Token
+ *
+ * @param string $token The token validate
+ * @param string $secretKey The secret key used to encode token
*/
- protected static function experimental($method)
+ public static function validateUserToken(string $token, ?string $secretKey = null)
{
- if (!static::config("USE_SESSION")) {
- trigger_error("Auth::$method is experimental. Turn on USE_SESSION to use this feature.");
- }
+ $payload = Authentication::validate($token, $secretKey ?? static::config("TOKEN_SECRET"));
+ if ($payload) return $payload;
+
+ static::$errors = array_merge(static::$errors, Authentication::errors());
+
+ return null;
+ }
+
+ /**
+ * Validate Bearer Token
+ *
+ * @param string $secretKey The secret key used to encode token
+ */
+ public static function validateToken(?string $secretKey = null)
+ {
+ $payload = Authentication::validateToken($secretKey ?? static::config("TOKEN_SECRET"));
+ if ($payload) return $payload;
+
+ static::$errors = array_merge(static::$errors, Authentication::errors());
+
+ return null;
+ }
+
+ /**
+ * Get Bearer token
+ */
+ public static function getBearerToken()
+ {
+ $token = Authentication::getBearerToken();
+ if ($token) return $token;
+
+ static::$errors = array_merge(static::$errors, Authentication::errors());
+
+ return null;
}
/**
@@ -136,6 +190,6 @@ protected static function experimental($method)
*/
public static function errors(): array
{
- return static::$errorsArray;
+ return static::$errors;
}
}
diff --git a/src/Auth/Login.php b/src/Auth/Login.php
deleted file mode 100644
index dfbb245..0000000
--- a/src/Auth/Login.php
+++ /dev/null
@@ -1,107 +0,0 @@
-select($table)->where($credentials)->validate($validate)->fetchAssoc();
- if (!$user) {
- static::$errorsArray["auth"] = static::$settings["LOGIN_PARAMS_ERROR"];
- return null;
- }
-
- if (static::$settings["AUTH_NO_PASS"] === false) {
- $passwordIsValid = true;
-
- if (static::$settings["PASSWORD_VERIFY"] !== false && isset($user[$passKey])) {
- if (is_callable(static::$settings["PASSWORD_VERIFY"])) {
- $passwordIsValid = call_user_func(static::$settings["PASSWORD_VERIFY"], $password, $user[$passKey]);
- } else if (static::$settings["PASSWORD_VERIFY"] === Password::MD5) {
- $passwordIsValid = (md5($password) === $user[$passKey]);
- } else {
- $passwordIsValid = Password::verify($password, $user[$passKey]);
- }
- }
-
- if (!$passwordIsValid) {
- static::$errorsArray["password"] = static::$settings["LOGIN_PASSWORD_ERROR"];
- return null;
- }
- }
-
- $token = Authentication::generateSimpleToken(
- $user[static::$settings["ID_KEY"]],
- static::config("TOKEN_SECRET"),
- static::config("TOKEN_LIFETIME")
- );
-
- if (isset($user[static::$settings["ID_KEY"]])) {
- $userId = $user[static::$settings["ID_KEY"]];
- }
-
- if (static::$settings["HIDE_ID"]) {
- unset($user[static::$settings["ID_KEY"]]);
- }
-
- if (static::$settings["HIDE_PASSWORD"] && (isset($user[$passKey]) || !$user[$passKey])) {
- unset($user[$passKey]);
- }
-
- if (!$token) {
- static::$errorsArray = array_merge(static::$errorsArray, Authentication::errors());
- return null;
- }
-
- if (static::config("USE_SESSION")) {
- if (isset($userId)) {
- $user[static::$settings["ID_KEY"]] = $userId;
- }
-
- static::save("AUTH_USER", $user);
- static::save("HAS_SESSION", true);
-
- if (static::config("SAVE_SESSION_JWT")) {
- static::save("AUTH_TOKEN", $token);
- }
-
- exit(header("location: " . static::config("GUARD_HOME")));
- }
-
- $response["user"] = $user;
- $response["token"] = $token;
-
- return $response;
- }
-}
\ No newline at end of file
diff --git a/src/Auth/Register.php b/src/Auth/Register.php
deleted file mode 100644
index 3d187e1..0000000
--- a/src/Auth/Register.php
+++ /dev/null
@@ -1,125 +0,0 @@
-insert($table)->params($credentials)->unique($uniques)->validate($validate)->execute();
- } catch (\Throwable $th) {
- trigger_error($th->getMessage());
- }
-
- if (!$query) {
- static::$errorsArray = array_merge(static::$errorsArray, static::$db->errors());
- return null;
- }
-
- $user = static::$db->select($table)->where($credentials)->validate($validate)->fetchAssoc();
-
- if (!$user) {
- static::$errorsArray = array_merge(static::$errorsArray, static::$db->errors());
- return null;
- }
-
- $token = Authentication::generateSimpleToken(
- $user[static::$settings["ID_KEY"]],
- static::config("TOKEN_SECRET"),
- static::config("TOKEN_LIFETIME")
- );
-
- if (isset($user[static::$settings["ID_KEY"]])) {
- $userId = $user[static::$settings["ID_KEY"]];
- }
-
- if (static::$settings["HIDE_ID"]) {
- unset($user[static::$settings["ID_KEY"]]);
- }
-
- if (static::$settings["HIDE_PASSWORD"] && (isset($user[$passKey]) || !$user[$passKey])) {
- unset($user[$passKey]);
- }
-
- if (!$token) {
- static::$errorsArray = array_merge(static::$errorsArray, Authentication::errors());
- return null;
- }
-
- if (static::config("USE_SESSION")) {
- if (static::config("SESSION_ON_REGISTER")) {
- if (isset($userId)) {
- $user[static::$settings["ID_KEY"]] = $userId;
- }
-
- static::save("AUTH_USER", $user);
- static::save("HAS_SESSION", true);
-
- if (static::config("SAVE_SESSION_JWT")) {
- static::save("AUTH_TOKEN", $token);
- }
-
- exit(header("location: " . static::config("GUARD_HOME")));
- } else {
- exit(header("location: " . static::config("GUARD_LOGIN")));
- }
- }
-
- $response["user"] = $user;
- $response["token"] = $token;
-
- return $response;
- }
-}
diff --git a/src/Auth/Session.php b/src/Auth/Session.php
index ab0e1cc..e4b9111 100644
--- a/src/Auth/Session.php
+++ b/src/Auth/Session.php
@@ -1,142 +1,38 @@
get("SESSION_STARTED_AT")) {
static::$session->set("SESSION_STARTED_AT", time());
}
static::$session->set("SESSION_LAST_ACTIVITY", time());
- }
-
- /**
- * Session Length
- */
- public static function length()
- {
- static::experimental("length");
-
- return time() - static::$session->get("SESSION_STARTED_AT");
- }
-
- /**
- * Session last active
- */
- public static function lastActive()
- {
- static::experimental("lastActive");
-
- return time() - static::$session->get("SESSION_LAST_ACTIVITY");
- }
-
- /**
- * Refresh session
- */
- public static function refresh($clearData = true)
- {
- static::experimental("refresh");
-
- $success = static::$session->regenerate($clearData);
-
- static::$session->set("SESSION_STARTED_AT", time());
- static::$session->set("SESSION_LAST_ACTIVITY", time());
- static::$session->set("AUTH_SESISON", true);
-
- return $success;
- }
-
- /**
- * Define/Return session middleware
- *
- * **This method only works with session auth**
- */
- public static function middleware(string $name, callable $handler = null)
- {
- static::experimental("middleware");
-
- if (!$handler) return static::$middleware[$name];
-
- static::$middleware[$name] = $handler;
- }
-
- /**
- * Check session status
- */
- public static function status()
- {
- static::experimental("status");
-
- return static::$session->get("AUTH_USER") ?? false;
- }
-
- /**
- * End a session
- */
- public static function end($location = null)
- {
- static::experimental("end");
-
- static::$session->destroy();
-
- if ($location) {
- $route = static::config($location) ?? $location;
- \Leaf\Http\Response::redirect($route);
- }
- }
-
- /**
- * A simple auth guard: 'guest' pages can't be viewed when logged in,
- * 'auth' pages can't be viewed without authentication
- *
- * @param array|string $type The type of guard/guard options
- */
- public static function guard($type)
- {
- static::experimental("guard");
-
- if (is_array($type)) {
- if (isset($type["hasAuth"])) {
- $type = $type["hasAuth"] ? 'auth' : 'guest';
- }
- }
-
- if ($type === 'guest' && static::status()) {
- exit(header("location: " . static::config("GUARD_HOME"), true, 302));
- }
-
- if ($type === 'auth' && !static::status()) {
- exit(header("location: " . static::config("GUARD_LOGIN"), true, 302));
- }
- }
-
- /**
- * Save some data to auth session
- */
- public static function save($key, $data = null)
- {
- static::experimental("save");
- static::$session->set($key, $data);
+ return static::$session;
}
}
diff --git a/src/Auth/User.php b/src/Auth/User.php
deleted file mode 100644
index 3d99fdb..0000000
--- a/src/Auth/User.php
+++ /dev/null
@@ -1,226 +0,0 @@
- 0) {
- foreach ($uniques as $unique) {
- if (!isset($credentials[$unique])) {
- trigger_error("$unique not found in credentials.");
- }
-
- $data = static::$db->select($table)->where($unique, $credentials[$unique])->fetchAssoc();
-
- $wKeys = array_keys($where);
- $wValues = array_values($where);
-
- if (isset($data[$wKeys[0]]) && $data[$wKeys[0]] != $wValues[0]) {
- static::$errorsArray[$unique] = "$unique already exists";
- }
- }
-
- if (count(static::$errorsArray) > 0) return null;
- }
-
- try {
- $query = static::$db->update($table)->params($credentials)->where($where)->validate($validate)->execute();
- } catch (\Throwable $th) {
- trigger_error($th->getMessage());
- }
-
- if (!$query) {
- static::$errorsArray = array_merge(static::$errorsArray, static::$db->errors());
- return null;
- }
-
- if (isset($credentials["updated_at"])) {
- unset($credentials["updated_at"]);
- }
-
- $user = static::$db->select($table)->where($credentials)->validate($validate)->fetchAssoc();
- if (!$user) {
- static::$errorsArray = array_merge(static::$errorsArray, static::$db->errors());
- return null;
- }
-
- $token = Authentication::generateSimpleToken(
- $user[static::$settings["ID_KEY"]],
- static::config("TOKEN_SECRET"),
- static::config("TOKEN_LIFETIME")
- );
-
- if (isset($user[static::$settings["ID_KEY"]])) {
- $userId = $user[static::$settings["ID_KEY"]];
- }
-
- if (static::$settings["HIDE_ID"] && isset($user[static::$settings["ID_KEY"]])) {
- unset($user[static::$settings["ID_KEY"]]);
- }
-
- if (static::$settings["HIDE_PASSWORD"] && (isset($user[$passKey]) || !$user[$passKey])) {
- unset($user[$passKey]);
- }
-
- if (!$token) {
- static::$errorsArray = array_merge(static::$errorsArray, Authentication::errors());
- return null;
- }
-
- if (static::config("USE_SESSION")) {
- if (isset($userId)) {
- $user[static::$settings["ID_KEY"]] = $userId;
- }
-
- static::save("AUTH_USER", $user);
- static::save("HAS_SESSION", true);
-
- if (static::config("SAVE_SESSION_JWT")) {
- static::save("AUTH_TOKEN", $token);
- }
-
- return $user;
- }
-
- $response["user"] = $user;
- $response["token"] = $token;
-
- return $response;
- }
-
- /**
- * Validate Json Web Token
- *
- * @param string $token The token validate
- * @param string $secretKey The secret key used to encode token
- */
- public static function validate($token, $secretKey = null)
- {
- $payload = Authentication::validate($token, $secretKey ?? static::config("TOKEN_SECRET"));
- if ($payload) return $payload;
-
- static::$errorsArray = array_merge(static::$errorsArray, Authentication::errors());
-
- return null;
- }
-
- /**
- * Validate Bearer Token
- *
- * @param string $secretKey The secret key used to encode token
- */
- public static function validateToken($secretKey = null)
- {
- $payload = Authentication::validateToken($secretKey ?? static::config("TOKEN_SECRET"));
- if ($payload) return $payload;
-
- static::$errorsArray = array_merge(static::$errorsArray, Authentication::errors());
-
- return null;
- }
-
- /**
- * Get Bearer token
- */
- public static function getBearerToken()
- {
- $token = Authentication::getBearerToken();
- if ($token) return $token;
-
- static::$errorsArray = array_merge(static::$errorsArray, Authentication::errors());
-
- return null;
- }
-
- /**
- * Return the user id encoded in token
- */
- public static function id()
- {
- if (static::config("USE_SESSION")) {
- return static::$session->get("AUTH_USER")[static::$settings["ID_KEY"]] ?? null;
- }
-
- $payload = static::validateToken(static::config("TOKEN_SECRET"));
- if (!$payload) return null;
- return $payload->user_id;
- }
-
- /**
- * Get the current user data from token
- *
- * @param string $table The table to look for user
- * @param array $hidden Fields to hide from user array
- */
- public static function info($table = "users", $hidden = [])
- {
- if (!static::id()) {
- if (static::config("USE_SESSION")) {
- return static::$session->get("AUTH_USER");
- }
-
- return null;
- }
-
- $user = static::$db->select($table)->where("id", static::id())->fetchAssoc();
-
- if (count($hidden) > 0) {
- foreach ($hidden as $item) {
- if (isset($user[$item]) || !$user[$item]) {
- unset($user[$item]);
- }
- }
- }
-
- return $user;
- }
-}
diff --git a/src/functions.php b/src/functions.php
index f5aec8f..b2b8f59 100644
--- a/src/functions.php
+++ b/src/functions.php
@@ -1,37 +1,34 @@
$auth]);
- }
-
- return $auth;
- }
-
- return \Leaf\Auth::class;
+ if (!(\Leaf\Config::get("auth.instance"))) {
+ \Leaf\Config::set("auth.instance", new Leaf\Auth());
}
- if ($guard === 'session') {
- return \Leaf\Auth::session();
- }
+ return \Leaf\Config::get("auth.instance");
+ }
+}
- return \Leaf\Auth::guard($guard);
+if (!function_exists('guard') && function_exists('auth')) {
+ /**
+ * Run an auth guard
+ *
+ * @param string $guard The auth guard to run
+ */
+ function guard(string $guard)
+ {
+ return auth()->guard($guard);
}
}
-if (!function_exists('hasAuth')) {
+if (!function_exists('hasAuth') && function_exists('auth')) {
/**
* Find out if there's an active sesion
*/
@@ -41,7 +38,7 @@ function hasAuth(): bool
}
}
-if (!function_exists('sessionUser')) {
+if (!function_exists('sessionUser') && function_exists('auth')) {
/**
* Get the currently logged in user
*/