<?php
namespace Tlf\User;
use Tlf\User\Configurations as C;
class Package extends \Lia\Package\Server {
public string $fqn = 'taeluf:user';
public string $name = 'user';
public readonly \Tlf\User\Lib $lib;
public readonly ?string $config_file;
protected bool $use_risky_web_initialization = false;
protected bool $enable_admin_dashboard = false;
/** key is name to show to user. value is a view name */
protected array $dashboard_items;
public function __construct(\Lia $lia, \PDO $pdo, array $configs){
$configs = array_merge(
[ // defaults
C::base_url => '/user/',
C::web_address => null,
C::email_from => null,
C::disabled_pages => [],// One of 'login', 'register', 'reset-password', 'logout', or 'terms'
C::mail_service => \Tlf\User\MailService::PHP_MAIL->value,
C::mail_service_callable => null,
],
$configs
);
parent::__construct($lia,$this->fqn,dirname(__DIR__),$configs[C::base_url]);
$lib = new \Tlf\User\Lib($pdo);
$this->lib = $lib;
$this->public_file_params = [
'lib' => $lib,
];
$lia->addMethod('addUserDashboard', [$this, 'add_user_dashboard']);
$lia->hook(\Tlf\User\Hooks::DASHBOARD_WILL_DISPLAY, [$this, 'add_main_dashboards']);
$this->update_configs($configs);
}
/**
* Get the html for a link within this library.
* @throws if link name not set
*/
public function link(string $link_name): string {
$link = $this->lia->view('user:Links',['links'=>[$link_name]]);
return $link."";
}
/**
* Get the html for a list of links within this lib.
* @throws if link name not set
*/
public function links(...$links): string {
$link = $this->lia->view('user:Links',['links'=>[...$links]]);
return $link."";
}
/**
* Updates the configs, but does not change the base_url, which is configured during instantiation.
*
* @param $configs array of configs. Only writes keys found in this array. If this configs array does not contain a key, it will not erase an existing config.
*/
public function update_configs(array $configs){
$lib = $this->lib;
$lib->config = array_merge($lib->config, $configs);
$configs = $lib->config;
$lib->mail_service = \Tlf\User\MailService::from($configs[C::mail_service]);
$lib->mail_service_callable = $configs[C::mail_service_callable];
$lib->disabled_pages = [
$configs[C::disabled_pages],
];
}
/**
* Load configs from the named config file. This config file will also be used by the risky_web_initialization() to store configs. Alternatively, just pass an array to the constructor of this class.
*
* If file does not exist, program continues as normal
*
* @param $json_path absolute path to a json file
*/
public function use_config_file(string $json_path){
$this->config_file = $json_path;
if (file_exists($json_path)){
$configs = json_decode(file_get_contents($json_path), true, 10, JSON_THROW_ON_ERROR);
$this->update_configs($configs);
} else if ($this->enable_admin_dashboard){
error_log("Config file '$json_path' does not exist");
} else {
throw new \Exception("Config file '$json_path' does not exist. Either create the file or call 'enable_admin_dashboard()' prior to 'use_config_file()'");
}
}
/**
* The easiest way to initialize configs for your user library. This gives you a web page to input your mail server settings and to initialize the database.
*
* There are several security measures to prevent unauthorized access, BUT this should not be called in production BECAUSE it exposes administrative functionality that, if exploited, could cause real problems.
*
* You don't want some unexpected error or hack to let somebody change your mail server credentials. This could expose all your users to phishing attacks.
*
* So you should push to test or production, do the initial setup via the gui, then comment out the method call & push the updated code to the server after things are initialized. Be sure to delete the local initialization pin file before pushing changes.
*
* @param $initialization_pin_file absolute path to a .txt file that contains a pin that's 20-40 characters long
*/
public function enable_risky_web_initialization(string $initialization_pin_file){
$init_url = $this->url('/initialize/');
if ($init_url !== $_SERVER['REQUEST_URI']){
throw new \Exception("risky_web_initialization is active, so you CANNOT visit any page other than '$init_url' until you remove the call to 'enable_risky_web_initialization()'.");
}
if (!is_file($initialization_pin_file)){
throw new \Exception("Initialization pin file does not exit. The file is automatically deleted when initialization is complete. If you've already initialized, then remove the call to 'enable_risky_web_initialization()'. Otherwise, create the file.");
}
$content = file_get_contents($initialization_pin_file);
if (strlen($content)<20 || strlen($content) > 40){
throw new \Exception("Initialization pin file must contain a string that is 20-40 characters long.");
}
error_log("WARNING: User Library Risy Web Initialization is enabled. This should NOT be enabled in production.");
error_log("WARNING: User Library Risy Web Initialization is enabled. This should NOT be enabled in production.");
error_log("WARNING: User Library Risy Web Initialization is enabled. This should NOT be enabled in production.");
$this->use_risky_web_initialization = true;
$this->public_file_params['initialization_pin_file'] = $initialization_pin_file;
$init_addon = new \Tlf\User\InitializationAddon($this);
}
/**
* Enables views for the admin dasbhoard, which allows configuration of the mail server & some other settings that would otherwise be configured through code.
*
*/
public function enable_admin_dashboard(){
//if (!isset($this->config_file)){
//throw new \Exception("You MUST call `use_config_file(string \$json_path)` prior to enabling the admin dashboard.");
//}
$this->enable_admin_dashboard = true;
$init_addon = new \Tlf\User\AdminDashboardAddon($this);
}
/**
* Get the current user.
* If there is no active login, a user is returned that is neither registered nor logged in and is not in the database.
* @return \Tlf\User, whether there is a login or not.
*/
public function get_user(): \Tlf\User {
// log the user in
$current_user = $this->lib->user_from_cookie();
// if there was no cookie, we'll use an unregistered user
if ($current_user===false)$current_user = new \Tlf\User($this->lib->pdo);
//$this->public_file_params['user'] = $current_user;
return $current_user;
}
public function get_dashboards(){
return $this->dashboard_items;
}
/** DASHBOARD_WILL_DISPLAY hook to setup dashboards */
public function add_main_dashboards(){
$lia = $this->lia;
$this->add_user_dashboard('Main', 'user:dashboard/main');
$this->add_user_dashboard('Your Permissions', 'user:dashboard/permissions',);
$this->add_user_dashboard('Security Logs', 'user:dashboard/security_logs');
}
public function add_user_dashboard(string $name, string $view_name){
$this->dashboard_items[$name] = $view_name;
}
}