taeluf / user-gui
a user system for PHP, built on Liaison
Requires
- taeluf/cli: v0.1.x-dev
- taeluf/liaison: v0.6.x-dev
Requires (Dev)
- taeluf/code-scrawl: v0.8.x-dev
- taeluf/lildb: v0.1.x-dev
- taeluf/phtml: v0.1.x-dev
- taeluf/server: v0.2.x-dev
- taeluf/tester: v0.3.x-dev
This package is auto-updated.
Last update: 2024-10-10 21:14:58 UTC
README
User Login
A User login system built with Liaison, which can be plugged into any existing website, whether you use Liaison or not.
UPGRADE NOTICE: v0.3 is abandoned. You should use v0.4
Warning: The documentation is ... incomplete & just kinda bad right now.
Legal: YOU ARE RESPONSIBLE FOR TERMS & CONDITIONS & legal stuff! If you use this software, you must read & understand them. If you do not agree with them or do not want to use them, then you must replace them. If what i've written is not legally sufficient, YOU ARE STILL LIABLE & I take no responsibility for any legal matters pertaining to your use of this software, user privacy, etc.
Status: Alpha, not feature complete (May 6, 2022)
This library has the essentials for user login: login, password reset, registration. It also has necessary features like terms & conditions & security stuff. It has CSRF, XSS prevention, honeypots, throttling, and security logs.
A big drawback currently is the lack of a GUI for user management, administration, and roles/permissions. This must be done in code, unfortunately. Though the back-end API is pretty easy to use so it's not that bad.
There are robust tests for most of the library. However, my CSRF is minimal & honeypot testing is non-existent (aside from trying it in the browser).
Setup is a bit cumbersome. Documentation is currently poor.
I plan to add some new cli commands & a convenience method for standard setups on your server.
Install
composer require taeluf/user-gui v0.3.x-dev
or in your composer.json
{"require":{ "taeluf/user-gui": "v0.3.x-dev"}}
Sever Setup
This is a simple setup for a Liaison server.
If you wish to use this on a non-liaison website, then instead of $liaison->deliver()
, call $liaison->getResponse()
, get the content & headers from the response & do with them as you need.
<?php
// the root dir of your server
$dir = dirname(__DIR__,2);
require($dir.'/vendor/autoload.php');
// optional if you have other setup to do
require(__DIR__.'/bootstrap.php');
// $user_lib_dir = $dir.'/vendor/taeluf/user-gui/code/';
$user_lib_dir = $dir.'/code/';
// initialize Liaison
$lia = new \Lia();
$main = \Lia\Package\Server::main($lia);
// set the base url for the user pages
$lia->set('user.base_url', '/user/');
// init the user server
$user_package = new \Lia\Package\Server($lia, 'user', $user_lib_dir);
// load db settings from env file & make pdo
$settings = json_decode(file_get_contents(dirname(__DIR__).'/db-env.json'),true);
$pdo = new \PDO("mysql:dbname=".$settings['db'], $settings['user'], $settings['password']);
// configure the user login library
$lib = new \Tlf\User\Lib($pdo);
$lib->config = [
'web_address'=>'https://example.com',
'email_from'=>'notauser@example.com',
];
// uncomment this line, run once, then re-comment this line
// $lib->init_db();
// log the user in
$current_user = $lib->user_from_cookie();
// if there was no cookie, we'll use an unregistered user
if ($current_user===false)$current_user = new \Tlf\User($pdo);
// passes the user & library to user pages (login, register, etc)
$user_package->public_file_params = [
'user'=>$current_user,
'lib'=>$lib
];
$lia->deliver();
Database setup
Uncomment the $lib->init_db()
line in the deliver script above, then run the deliver script, then re-comment the init_db
line
Permissions and Roles
Permissions can be added to users and to roles. Roles can then be added to users to grant a group of permissions. See permissions source code at code/class/Permissions.php.
Examples:
<?php
$pdo = $this->pdo();
$lib = new \Tlf\User\Lib($pdo);
$user = $lib->user_from_email('reed@document.permissions');
//user must already be registered!
// allow a user to create blog posts
$user->allow('blog:create');
// allow user to edit a blog post with id = 37
$user->allow('blog:edit-37');
$this->is_true( // an assertion with my test lib
// check if user can create a blog post
$user->can('blog:create')
);
// remove permission
$user->deny('blog:create');
$this->is_false( // assertion to ensure the permission was removed
$user->can('blog:create')
);
/////
// roles
/////
// add a role to the user
$user->add_role('admin');
// add a permission to the role
$lib->role_allow('admin', 'blog:delete');
$this->is_true(
$user->can('blog:delete')
);
// remove a specific permission from a role
$lib->role_deny('admin', 'blog:delete');
// delete a role alltogether
$lib->role_delete('admin');
Database Schema
This is the file: code/db/create.sql.
CREATE TABLE IF NOT EXISTS `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` tinyint(1) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE(`email`)
) ;
CREATE TABLE IF NOT EXISTS `code` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`type` varchar(30),
`code` varchar(255) NOT NULL,
`is_active` tinyint(1) NOT NULL DEFAULT '0',
`activated_at` datetime NULL DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`expires_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ;
CREATE TABLE IF NOT EXISTS `permissions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`action` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
INDEX(`action`)
) ;
CREATE TABLE IF NOT EXISTS `user_role` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`role` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
INDEX(`role`)
) ;
CREATE TABLE IF NOT EXISTS `role_permission` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`role` varchar(255) NOT NULL,
`action` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
INDEX(`role`),
INDEX(`action`)
) ;
CREATE TABLE IF NOT EXISTS `throttle` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(255) NOT NULL,
`actor` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`expires_at` timestamp(6) NOT NULL,
PRIMARY KEY (`id`)
) ;
CREATE TABLE IF NOT EXISTS `security_log` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
`action` varchar(255) NOT NULL,
`ip` varchar(255) NOT NULL,
`user_agent` varchar(500) NOT NULL,
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY(`id`)
);