Ver código fonte

Changes to the auth method. !!Incomplete!!

ahwelp 2 anos atrás
pai
commit
357baca274

+ 231 - 0
app/core/auth/AuthController.php

@@ -0,0 +1,231 @@
+<?php
+
+namespace App\Core\Auth;
+
+use ORM\DBInstance;
+use \App\Core\Template\Output as Output;
+
+use Singleton;
+use RR\Response;
+use \App\Core\Auth\Classes\Auth as Auth;
+use App\Core\Auth\Classes\AuthenticatedUser;
+use App\Core\Auth\Classes\Token;
+use \App\Core\Auth\Classes\User as User;
+
+class AuthController
+{
+
+    private static $user;
+    private static $permissions;
+
+    /**
+     * Index
+     * Show the main Auth list
+     */
+    function index()
+    {
+        Output::render('index', ['list' => User::findAll()]);
+    }
+
+    /**
+     * Create
+     *
+     * Render the main Auth formulary
+     */
+    function create(User $auth)
+    {
+        Output::render('form', $auth);
+    }
+
+    /**
+     * Store
+     *
+     * Store the param on the database
+     * @param User $auth
+     */
+    function store(User $auth)
+    {
+        $auth->charge($_POST);
+
+        if (request('password') == '') {
+            unset($auth->password);
+        } else {
+            $auth->password = md5(request('password'));
+        }
+
+        $auth->save();
+        $auth->appendGroups(request('groups'));
+
+        Response::json($auth)->send();
+    }
+
+    /**
+     * Show
+     *
+     * Render one register
+     *
+     * @param Auth $auth
+     */
+    function show(Auth $auth)
+    {
+    }
+
+    /**
+     * Edit
+     *
+     * Render the formular for a database Auth
+     *
+     * @param Auth $auth
+     */
+    function edit(User $auth)
+    {
+        Output::render('form', $auth);
+    }
+
+    /**
+     * Update
+     * Store the changes of the param on the database
+     *
+     * @param User $auth
+     */
+    function update(User $auth)
+    {
+        $auth->charge($_POST);
+
+        if (request('password') == '') {
+            unset($auth->password);
+        } else {
+            $auth->password = md5(request('password'));
+        }
+
+        $auth->save();
+        $auth->appendGroups(request('groups'));
+
+        Response::json($auth)->send();
+    }
+
+    /**
+     * Destroy
+     * If the object has soft delete.
+     *
+     * @param Auth $auth
+     */
+    function destroy(Auth $auth)
+    {
+    }
+
+    /**
+     * Purge
+     * Remove object even with soft delete.
+     *
+     * @param Auth $auth
+     */
+    function purge(Auth $auth)
+    {
+    }
+
+    function login()
+    {
+        if ($user = User::findOne(['username' => ['=', $_POST['login']], 'password' => ['=', md5($_POST['password'])]])) {
+            AuthController::executeLogin($user);
+        } else {
+            Output::setTemplate('NullTemplate');
+            Output::render('login', ['errors' => ['name' => 'Não há usuário com essa senha']]);
+        }
+    }
+
+    /**
+     * Prints the system login form
+     */
+    function loginForm()
+    {
+        if (self::isLoggedIn()) {
+            Response::redirect('/');
+        } else {
+            Output::setTemplate('NullTemplate');
+            Output::render('login');
+        }
+    }
+
+    /**
+     * Just check if the user is set on the _SESSION variable
+     *
+     * @return bool
+     */
+    public static function isLoggedIn()
+    {
+        if ($_SESSION['user']) {
+            AuthenticatedUser::load();
+        } else {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the token passed on the wstoken param is valid
+     * by valid.
+     * - Exist
+     * - Not Expired
+     * - Has the permission
+     *
+     * @return bool
+     */
+    public static function isTokenValid()
+    {
+        if ($token = Token::findOne(['token' => ['=', request('wstoken')]])) {
+            AuthenticatedUser::load($token->user());
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Given a permission. Check if the loged user can execute it
+     *
+     * @param String $permission
+     */
+    public static function canAccess($permission)
+    {
+
+        if (AuthenticatedUser::permissions() == null) {
+            return false;
+        }
+
+        if (in_array('sys:admin', AuthenticatedUser::permissions())) {
+            return true;
+        }
+
+        if (in_array($permission, AuthenticatedUser::permissions())) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * In case the login form is valid. Persist user data on SESSION
+     * so the login system words onwards
+     *
+     * TODO - Cache wantsPage
+     *
+     * @param User $user
+     */
+    function executeLogin(User $user)
+    {
+        $_SESSION['user']['user'] = $user->id;
+        $_SESSION['user']['permission'] = $user->permissions();
+        header("location: /");
+    }
+
+    /**
+     * Execute the system logout
+     */
+    function logout()
+    {
+        session_destroy();
+        header("location: /auth/login");
+    }
+}

+ 60 - 0
app/core/auth/Routes.php

@@ -0,0 +1,60 @@
+<?php
+
+use App\Core\Template\Output as Output;
+use Routes\RouteCollection as RouteCollection;
+
+use App\Core\Auth\AuthController as Auth;
+
+RouteCollection::get('*', function() {
+    Output::addMenu('/auth/logout', 'Logout', icon('sign-out'), ['class' => 'nav-link', 'data-method' => 'reload'], 99999);
+    Output::addOnSubmenu('config', '/auth', "Usuários", icon('user'), ['class' => 'nav-link']);
+}, -10)->doIgnore();
+
+RouteCollection::group("/auth", function () {
+    // Default
+    RouteCollection::get("/", "\App\Core\Auth\AuthController@index");
+    RouteCollection::get("/form", "\App\Core\Auth\AuthController@create");
+    RouteCollection::post("/", "\App\Core\Auth\AuthController@store");
+    RouteCollection::get("/[i:id]", "\App\Core\Auth\AuthController@show");
+    RouteCollection::get("/[i:id]/edit", "\App\Core\Auth\AuthController@edit");
+    RouteCollection::put("/[i:id]/edit", "\App\Core\Auth\AuthController@update");
+    RouteCollection::delete("/[i:id]", "\App\Core\Auth\AuthController@destroy");
+
+    // Auth process
+    RouteCollection::get('/logout', "\App\Core\Auth\AuthController@logout");
+    RouteCollection::get('/login',  "\App\Core\Auth\AuthController@loginForm")->middlewareIgnore('auth');
+    RouteCollection::post('/login', "\App\Core\Auth\AuthController@login")->middlewareIgnore('auth')->doBlock();
+});
+
+RouteCollection::addDefaultMiddleware('auth', function () {
+    global $ROUTE;
+
+    return true;
+
+    if($ROUTE->_verb == 'CLI' || $ROUTE->_verb[0] == 'CLI'){
+        return true;
+    }
+
+    if(Auth::isTokenValid()){
+        return true;
+    }
+
+    #ToDo use the Response API
+    if (!Auth::isLoggedIn()) {
+        header("location: /auth/login");
+        die;
+    }
+
+});
+
+/**
+ * Checks if the loged user can access a specific permission
+ */
+RouteCollection::registerMiddleware('canaccess', function ($permission) {
+    if(!Auth::canAccess($permission)){
+        Output::setTemplate('NullTemplate');
+        Output::render('forbiden', ['action' => $permission]);
+        return false;
+    }
+    return true;
+});

+ 36 - 0
app/core/auth/base.sql

@@ -0,0 +1,36 @@
+insert into inf_auth_group (name) VALUES ('Admin');
+insert into inf_auth_group (name) VALUES ('Vendedor');
+
+insert into inf_auth_permission (name) VALUES ('admin');
+
+insert into inf_auth_permission (name) VALUES ('user:search');
+insert into inf_auth_permission (name) VALUES ('user:create');
+insert into inf_auth_permission (name) VALUES ('user:update');
+insert into inf_auth_permission (name) VALUES ('user:delete');
+insert into inf_auth_permission (name) VALUES ('user:purge');
+
+insert into inf_auth_permission (name) VALUES ('sells:make');
+insert into inf_auth_permission (name) VALUES ('sells:lookSelf');
+
+insert into inf_auth_permission_group (group_id, permission_id) VALUES (1, 2);
+insert into inf_auth_permission_group (group_id, permission_id) VALUES (1, 3);
+insert into inf_auth_permission_group (group_id, permission_id) VALUES (1, 4);
+insert into inf_auth_permission_group (group_id, permission_id) VALUES (1, 5);
+insert into inf_auth_permission_group (group_id, permission_id) VALUES (1, 6);
+insert into inf_auth_permission_group (group_id, permission_id) VALUES (1, 7);
+
+insert into inf_auth_user (username, name, email, password) VALUES ('v', 'admin', 'admin@admin.com', '21232f297a57a5a743894a0e4a801fc3');
+insert into inf_auth_user (username, name, email, password) VALUES ('v1', 'vendedor', 'admin@admin.com', '0407e8c8285ab85509ac2884025dcf42');
+
+insert into inf_auth_group_user (user_id, group_id) VALUES (1, 1);
+insert into inf_auth_group_user (user_id, group_id) VALUES (1, 2);
+
+insert into inf_auth_permission_user (user_id, permission_id, action) VALUES (3, 5, 'a');
+insert into inf_auth_permission_user (user_id, permission_id, action) VALUES (3, 6, 'a');
+
+insert into inf_auth_permission_user (user_id, permission_id, action) VALUES (1, 1, 'd');
+
+drop table inf_auth_group;
+drop table inf_auth_permission;
+drop table inf_auth_permission_group;
+drop table inf_auth_user;

+ 7 - 0
app/core/auth/classes/Auth.php

@@ -0,0 +1,7 @@
+<?php
+
+namespace App\Core\Auth\Classes;
+
+class Auth{
+    
+}

+ 42 - 0
app/core/auth/classes/AuthenticatedUser.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Core\Auth\Classes;
+
+use Singleton;
+
+/**
+ * Store the user auth and permissions on a singleton
+ * so this will be used on ws and web requests
+ */
+class AuthenticatedUser extends Singleton
+{
+
+    private $user;
+    private $permissions;
+
+    public static function load(User $user = null)
+    {
+        $instance = self::getInstance();
+        if ($user) {
+            $instance->user = $user;
+            $instance->permissions = $user->permissions();
+        }
+
+        if ($_SESSION['user']) {
+            $instance->user = $_SESSION['user'];
+            $instance->permissions = $_SESSION['user']['permission'];
+        }
+
+        return $instance;
+    }
+
+    public static function user()
+    {
+        return self::getInstance()->user;
+    }
+
+    public static function permissions()
+    {
+        return self::getInstance()->permissions;
+    }
+}

+ 16 - 0
app/core/auth/classes/Group.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Core\Auth\Classes;
+
+use ORM\Entity as Entity;
+use App\Core\Auth\Classes\Permission as Permission;
+
+class Group extends Entity{
+    
+    const _tableName  = "auth_group";
+    
+    function permissions(){
+        return $this->belongsToMany(Permission::class, 'auth_permission_group', 'group_id', 'permission_id');
+    }
+    
+}

+ 17 - 0
app/core/auth/classes/Permission.php

@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+namespace App\Core\Auth\Classes;
+
+use ORM\Entity as Entity;
+
+class Permission extends Entity{
+
+    const _tableName  = "auth_permission";
+
+}

+ 33 - 0
app/core/auth/classes/SessionLog.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Core\Auth\Classes;
+
+use Singleton;
+
+/**
+ * Store the user auth and permissions on a singleton
+ * so this will be used on ws and web requests
+ */
+class SessionLog extends Singleton
+{
+    private static $session;
+    private static $logs = Array();
+
+    /**
+     * Opens a session object.
+     * The session will represent a request initiation
+     */
+    public static function openSession()
+    {
+
+    }
+
+    /**
+     * Add a log to the session
+     * A log will store a hasPermission request
+     */
+    public static function storeLog(Permission $permission)
+    {
+
+    }
+}

+ 22 - 0
app/core/auth/classes/Token.php

@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+namespace App\Core\Auth\Classes;
+
+use ORM\Entity as Entity;
+use App\Core\Auth\Classes\User as User;
+
+class Token extends Entity{
+
+    const _tableName  = "auth_token";
+
+    function user(){
+        return $this->belongsTo(User::class, 'user_id')->get();
+    }
+
+}

+ 74 - 0
app/core/auth/classes/User.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Core\Auth\Classes;
+
+use ORM\Entity as Entity;
+use App\Core\Auth\Classes\Group as Group;
+use App\Core\Auth\Classes\Permission as Permission;
+use ORM\DBInstance;
+
+class User extends Entity{
+
+    public $method = 'manual';
+    public $username = '';
+    public $name = '';
+    public $email = '';
+    public $password = '';
+
+    const _tableName  = "auth_user";
+    const _timestamps = true;
+    const _softdelete = true;
+
+    function groups(){
+        return $this->belongsToMany(Group::class, 'auth_group_user', 'user_id', 'group_id')->get();
+    }
+
+    function specificPermissions(){
+        return $this->belongsToManyExtended(Permission::class, 'auth_permission_user', 'user_id', 'permission_id');
+    }
+
+    function permissions(){
+        $permissions = [];
+
+        foreach ($this->groups() as $group){
+            foreach ($group->permissions()->get() as $permission){
+                $permissions[] = $permission->name;
+            }
+        }
+
+        foreach ($this->specificPermissions()->get() as $permission){
+            if($permission->action == 'a'){
+                $permissions[] = $permission->childElement->name;
+            }else{
+
+            }
+        }
+
+        return $permissions;
+
+    }
+
+    function groupsoptions(){
+        $groupList = Group::findAll()->get();
+
+        foreach($this->groups() as $group){
+            foreach($groupList as $key => $list){
+                if($group->id == $list->id){
+                    $groupList[$key]->selected = true;
+                }
+            }
+        }
+
+        return $groupList;
+    }
+
+    public function appendGroups($groups){
+
+        DBInstance::execute('DELETE FROM {auth_group_user} WHERE user_id = ?', [$this->id]);
+
+        foreach($groups as $group){
+            DBInstance::insertRecord('auth_group_user', ['user_id' => $this->id, 'group_id' => $group]);
+        }
+    }
+
+}

+ 61 - 0
app/core/auth/db/001_auth_seeding.sql

@@ -0,0 +1,61 @@
+--
+INSERT INTO {auth_user} (method, username, name, email, password) VALUES('manual', 'admin', 'Administrador',  'admin@admin.com', '21232f297a57a5a743894a0e4a801fc3');
+INSERT INTO {auth_user} (method, username, name, email, password) VALUES('manual', 'maria', 'Maria da Silva', 'maria@admin.com', '263bce650e68ab4e23f28263760b9fa5');
+INSERT INTO {auth_user} (method, username, name, email, password) VALUES('manual', 'joao', 'João dos Santos', 'joao@vendas.com', 'dccd96c256bc7dd39bae41a405f25e43');
+
+INSERT INTO {auth_group} (name) VALUES('admin');
+INSERT INTO {auth_group} (name) VALUES('administrative');
+INSERT INTO {auth_group} (name) VALUES('sales');
+
+INSERT INTO {auth_permission} (name) VALUES('sys:admin');
+INSERT INTO {auth_permission} (name) VALUES('sys:login');
+INSERT INTO {auth_permission} (name) VALUES('user:view');--
+INSERT INTO {auth_permission} (name) VALUES('user:create');
+INSERT INTO {auth_permission} (name) VALUES('user:edit');
+INSERT INTO {auth_permission} (name) VALUES('user:purge');
+INSERT INTO {auth_permission} (name) VALUES('product:view');--
+INSERT INTO {auth_permission} (name) VALUES('product:create');
+INSERT INTO {auth_permission} (name) VALUES('product:edit');
+INSERT INTO {auth_permission} (name) VALUES('product:purge');
+INSERT INTO {auth_permission} (name) VALUES('client:view');--
+INSERT INTO {auth_permission} (name) VALUES('client:create');
+INSERT INTO {auth_permission} (name) VALUES('client:edit');
+INSERT INTO {auth_permission} (name) VALUES('client:purge');
+INSERT INTO {auth_permission} (name) VALUES('sales:view');--
+INSERT INTO {auth_permission} (name) VALUES('sales:viewself');
+INSERT INTO {auth_permission} (name) VALUES('sales:create');
+INSERT INTO {auth_permission} (name) VALUES('sales:edit');
+INSERT INTO {auth_permission} (name) VALUES('sales:purge');
+INSERT INTO {auth_permission} (name) VALUES('sales:faturate');
+
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'admin'), (SELECT id FROM {auth_permission} WHERE name = 'user:view'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'admin'), (SELECT id FROM {auth_permission} WHERE name = 'user:create'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'admin'), (SELECT id FROM {auth_permission} WHERE name = 'user:edit'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'admin'), (SELECT id FROM {auth_permission} WHERE name = 'user:purge'));
+
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'product:view'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'product:create'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'product:edit'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'product:purge'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'client:view'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'client:create'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'client:edit'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'client:purge'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'sales:view'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'administrative'), (SELECT id FROM {auth_permission} WHERE name = 'sales:faturate'));
+
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'product:view'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'client:view'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'client:create'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'client:edit'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'sales:viewself'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'sales:create'));
+INSERT INTO {auth_permission_group} (group_id, permission_id) VALUES((SELECT id FROM {auth_group} WHERE name = 'sales'), (SELECT id FROM {auth_permission} WHERE name = 'sales:edit'));
+
+INSERT INTO {auth_group_user} (user_id, group_id) VALUES((SELECT id FROM {auth_user} WHERE username = 'maria'), (SELECT id FROM {auth_group} WHERE name = 'admin'));
+INSERT INTO {auth_group_user} (user_id, group_id) VALUES((SELECT id FROM {auth_user} WHERE username = 'maria'), (SELECT id FROM {auth_group} WHERE name = 'administrative'));
+INSERT INTO {auth_group_user} (user_id, group_id) VALUES((SELECT id FROM {auth_user} WHERE username = 'joao'),  (SELECT id FROM {auth_group} WHERE name = 'sales'));
+
+INSERT INTO {auth_permission_user} (user_id, permission_id, action) VALUES((SELECT id FROM {auth_user} WHERE username = 'admin'),  (SELECT id FROM {auth_permission} WHERE name = 'sys:admin'), 'a');
+INSERT INTO {auth_permission_user} (user_id, permission_id, action) VALUES((SELECT id FROM {auth_user} WHERE username = 'maria'),  (SELECT id FROM {auth_permission} WHERE name = 'sys:login'), 'a');
+INSERT INTO {auth_permission_user} (user_id, permission_id, action) VALUES((SELECT id FROM {auth_user} WHERE username = 'joao'),  (SELECT id FROM {auth_permission} WHERE name = 'sys:login'), 'a');

+ 96 - 0
app/core/auth/db/Migrate.php

@@ -0,0 +1,96 @@
+<?php
+
+use Schema\Wrapper as Wrapper;
+
+function core_auth_upgrade($pluginversion)
+{
+    if ($pluginversion < "0.0.1") {
+
+        $table = Wrapper::get_table("auth_user");
+        $table->addColumn("method", "string", array("null" => false, 'default' => 'manual'));
+        $table->addColumn("username", "string", array("null" => false));
+        $table->addColumn("name", "string", array("null" => false));
+        $table->addColumn("email", "string", array("null" => false));
+        $table->addColumn("password", "string", array("null" => true));
+        $table->addIndex(['username'], ['unique' => true]);
+        $table->addIndex(['email'],    ['unique' => true]);
+        $table->addTimestamps();
+        $table->addSoftDelete();
+        $table->create();
+
+        $table = Wrapper::get_table("auth_permission");
+        $table->addColumn("name", "string", array("null" => false, "limit" => 255));
+        $table->addColumn("description", "string", array("null" => true));
+        $table->create();
+
+        $table = Wrapper::get_table("auth_group");
+        $table->addColumn("name", "string", array("null" => false, "limit" => 255));
+        $table->addColumn("description", "string", array("null" => true));
+        $table->create();
+
+        $table = Wrapper::get_table("auth_group_user");
+        $table->addColumn("user_id",  "integer", array("null" => false));
+        $table->addColumn("group_id", "integer", array("null" => false));
+        $table->addForeignKey('user_id',  Wrapper::get_table("auth_user"),  'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->addForeignKey('group_id', Wrapper::get_table("auth_group"), 'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->create();
+
+        $table = Wrapper::get_table("auth_permission_group");
+        $table->addColumn("group_id", "integer", array("null" => false));
+        $table->addColumn("permission_id", "integer", array("null" => false));
+        $table->addForeignKey('group_id',       Wrapper::get_table("auth_group"),       'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->addForeignKey('permission_id',  Wrapper::get_table("auth_permission"),  'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->create();
+
+        $table = Wrapper::get_table("auth_permission_user");
+        $table->addColumn("user_id", "integer", array("null" => false));
+        $table->addColumn("permission_id", "integer", array("null" => false));
+        $table->addColumn("action", "string", array("null" => false, 'limit' => 1));
+        $table->addForeignKey('user_id',       Wrapper::get_table("auth_group"),      'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->addForeignKey('permission_id', Wrapper::get_table("auth_permission"), 'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->create();
+
+        Wrapper::exec(file_get_contents(__DIR__ . '/001_auth_seeding.sql'));
+
+        App\Core\Sanity\MigratorController::getInstance()->update_plugin_version("core_auth", "1.0.0");
+
+        return;
+    }
+
+    /**
+     * Create logs tables
+     */
+    if ($pluginversion < "1.0.1") {
+        $table = Wrapper::get_table("auth_log");
+        $table->addColumn("user_id",       "integer", array("null" => false));
+        $table->addColumn("permission_id", "integer", array("null" => false));
+        $table->addColumn("real_user_id",  "integer", array("null" => false));
+        $table->addForeignKey('user_id',      Wrapper::get_table("auth_user"), 'id');
+        $table->addForeignKey('real_user_id', Wrapper::get_table("auth_user"), 'id');
+        $table->create();
+
+        App\Core\Sanity\MigratorController::getInstance()->update_plugin_version("core_auth", "1.0.1");
+    }
+
+    /**
+     * Create token tables
+     */
+    if ($pluginversion < "1.0.2") {
+        $table = Wrapper::get_table("auth_token");
+        $table->addColumn("user_id", "integer", array("null" => false));
+        $table->addColumn("token", "string", array("null" => false, "limit" => 64));
+        $table->addForeignKey('user_id',  Wrapper::get_table("auth_user"),  'id', ['delete' => 'SET_NULL', 'update' => 'NO_ACTION']);
+        $table->create();
+
+        App\Core\Sanity\MigratorController::getInstance()->update_plugin_version("core_auth", "1.0.2");
+    }
+}
+
+function core_auth_rollback($pluginversion)
+{
+    if ($pluginversion > "0.1.0") {
+        $table = Wrapper::get_table("auth");
+        $table->drop();
+        return;
+    }
+}

+ 2 - 0
app/core/auth/lang/en.php

@@ -0,0 +1,2 @@
+<?php
+    $lang["auth"]["module_name"] = "Auth";

+ 2 - 0
app/core/auth/lang/pt_br.php

@@ -0,0 +1,2 @@
+<?php
+    $lang["auth"]["module_name"] = "Auth";

+ 6 - 0
app/core/auth/version.php

@@ -0,0 +1,6 @@
+<?php
+
+$plugin->name = "core_auth";
+$plugin->version = "1.0.2";
+
+//$plugin->require = Array( ["name" => "plugin_name", "version" => "x.x.x"] );

+ 1 - 0
app/core/auth/views/forbiden.mustache

@@ -0,0 +1 @@
+<h1>No permission to execute action {{action}}</h1>

+ 63 - 0
app/core/auth/views/form.mustache

@@ -0,0 +1,63 @@
+{{#id}}
+<form method="POST" action="/auth/{{id}}/edit">
+    <input type="hidden" name="id" value="{{id}}" />
+    <input type="hidden" name="_method" value="put" />
+    {{/id}}
+    {{^id}}
+    <form method="POST" action="/auth">
+        <input type="hidden" name="id" value="" />
+        {{/id}}
+
+        <div class="col-xs-12">
+         <div class="card">
+            <div class="card-body">
+               <div class="row">
+                  <div class="row g-3">
+                     <div class="col-md-4 col-xs-12">
+                         <label class="form-label">Nome de usuário</label>
+                         <input type="text" class="form-control" name="username" value="{{username}}" />
+                     </div>
+                     <div class="col-md-8 col-xs-12">
+                        <label class="form-label">Nome</label>
+                        <input type="text" class="form-control" name="name" value="{{name}}" />
+                    </div>
+                 </div>
+               </div>
+               <div class="row">
+                  <div class="row g-3">
+                     <div class="col-md-6 col-xs-12">
+                         <label class="form-label">Email</label>
+                         <input type="text" class="form-control" name="email" value="{{email}}" />
+                     </div>
+                     <div class="col-md-6 col-xs-12">
+                        <label class="form-label">Senha</label>
+                        <input type="password" class="form-control" name="password"/>
+                    </div>
+                 </div>
+               </div>
+               <div class="row">
+                  <div class="g-3">
+                     <select class="form-control" name="groups[]" multiple>
+                     {{#groupsoptions}}
+                        {{> core/auth/views/groups }}
+                     {{/groupsoptions}}
+                     </select>
+                  </div>
+               </div>
+
+            </div>
+         </div>
+      </div>
+
+
+        <div class="col-xs-12">
+            <div class="card">
+               <div class="card-body">
+                  <div class="row">
+                        <div class="col-md-6"> <input class="btn btn-success btn-block" type="submit" value="Salvar" /> </div>
+                        <div class="col-md-6"> <a href="/auth" class="btn btn-danger btn-block"> Calcelar </a> </div>
+                  </div>
+               </div>
+            </div>
+         </div>
+     </form>

+ 7 - 0
app/core/auth/views/groups.mustache

@@ -0,0 +1,7 @@
+{{#selected}}
+<option value="{{id}}" selected>{{name}}</option>
+{{/selected}}
+
+{{^selected}}
+<option value="{{id}}">{{name}}</option>
+{{/selected}}

+ 60 - 0
app/core/auth/views/index.mustache

@@ -0,0 +1,60 @@
+<style>
+   .search-array input { border-right: 0px; }
+   .search-array .label { border-left: 0px; border-right: 0px; }
+</style>
+
+<div class="input-group mb-3 search-array">
+   <a href='auth/form' class="btn btn-outline-secondary col-xs-hidden d-none d-sm-block">
+      {{#icons}} plus-circle {{/icons}} Adicionar
+   </a>
+   <button type="button" class="btn btn-outline-secondary dropdown-toggle-split d-none d-sm-block"
+      data-bs-toggle="dropdown">
+      {{#icons}} arrow-down {{/icons}}
+   </button>
+   <ul class="dropdown-menu">
+      <li> <a class="dropdown-item" href="#">Action</a> </li>
+      <li><a class="dropdown-item" href="#">Another action</a></li>
+      <li><a class="dropdown-item" href="#">Something else here</a></li>
+      <li>
+         <hr class="dropdown-divider">
+      </li>
+      <li><a class="dropdown-item" href="#">Separated link</a></li>
+   </ul>
+   <input type="text" class="form-control" placeholder="">
+   <button class="btn btn-outline-secondary label" type="button" disabled>
+      {{#icons}} search {{/icons}}
+   </button>
+   <button class="btn btn-outline-secondary" type="button">
+      {{#icons}} th {{/icons}}
+   </button>
+   <button class="btn btn-outline-secondary" type="button">
+      {{#icons}} filter {{/icons}}
+   </button>
+   <button class="btn btn-outline-secondary" type="button">
+      {{#icons}} eye {{/icons}}
+   </button>
+</div>
+
+<div class="table-responsive">
+   <table class='table'>
+      <thead>
+         <tr>
+            <th>Id</th>
+            <th>Nome</th>
+            <th>Actions</th>
+         </tr>
+      </thead>
+      {{#list}}
+      <tr class="" data-id='{{id}}'>
+         <td>{{id}}</td>
+         <td>{{name | case.lower}}</td>
+         <td>
+            <a href="auth/{{id}}/edit"> {{#icons}} pencil {{/icons}} </a>
+         </td>
+      </tr>
+      {{/list}}
+   </table>
+</div>
+
+{{#string}} module_name,produtos,en {{/string}}
+{{#misc}} {{list}} {{/misc}}

+ 41 - 0
app/core/auth/views/login.mustache

@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        <title>Start Bootstrap - SB Admin Version 2.0 Demo</title>
+        <link href="/plugins/bootstrap/bootstrap.min.css" rel="stylesheet" />
+        <link href="/plugins/font-awesome/css/font-awesome.min.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <div class="card col-sm-4 offset-sm-4" style='margin-top: 10%'>
+            <div class="card-header">
+                Login
+            </div>
+            <div class="card-body">
+                <div style="text-align: center">
+                    <img src="/media/logo_black.png" />
+                </div>
+                <br />
+                {{#errors}}
+                    <div class="alert alert-danger" role="alert">{{name}}</div>
+                {{/errors}}
+                <form role="form" method='POST' action='/auth/login'>
+                    <fieldset>
+                        <div class="form-group">
+                            <input class="form-control" placeholder="login" name="login" type="text" autofocus>
+                        </div>
+                        <br />
+                        <div class="form-group">
+                            <input class="form-control" placeholder="Password" name="password" type="password" value="">
+                        </div>
+                        <br />
+                        <input type='submit' class="btn btn-success" style="width: 100%">
+                    </fieldset>
+                </form>
+            </div>
+        </div>
+    </body>
+
+</html>