Big Update Added Services and Admin
This commit is contained in:
		
							parent
							
								
									8f462953b7
								
							
						
					
					
						commit
						caca552cae
					
				
							
								
								
									
										20
									
								
								config/routes.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								config/routes.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
<?php
 | 
			
		||||
$framework_routes = [
 | 
			
		||||
    '/novaconium' => [ 
 | 
			
		||||
        'get' => 'NOVACONIUM/init'
 | 
			
		||||
    ],
 | 
			
		||||
    '/novaconium/create_admin' => [ 
 | 
			
		||||
        'post' => 'NOVACONIUM/create_admin'
 | 
			
		||||
    ],
 | 
			
		||||
    '/novaconium/login' => [
 | 
			
		||||
        'post' => 'NOVACONIUM/authenticate',
 | 
			
		||||
        'get' => 'NOVACONIUM/login'
 | 
			
		||||
    ],
 | 
			
		||||
    '/novaconium/dashboard' => [
 | 
			
		||||
        'get' => 'NOVACONIUM/dashboard'
 | 
			
		||||
    ],
 | 
			
		||||
    '/novaconium/logout' => [
 | 
			
		||||
        'post' => 'NOVACONIUM/logout',
 | 
			
		||||
        'get' => 'NOVACONIUM/logout'
 | 
			
		||||
    ]
 | 
			
		||||
];
 | 
			
		||||
							
								
								
									
										70
									
								
								controllers/authenticate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								controllers/authenticate.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
use Nickyeoman\Validation;
 | 
			
		||||
$v = new Nickyeoman\Validation\Validate();
 | 
			
		||||
 | 
			
		||||
$url_success = '/novaconium/dashboard';
 | 
			
		||||
$url_fail = '/novaconium/login';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Don't go  further if already logged in
 | 
			
		||||
if ( !empty($session->get('username')) ) {
 | 
			
		||||
    $redirect->url($url_success);
 | 
			
		||||
    makeitso();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Make sure Session Token is correct
 | 
			
		||||
if ($session->get('token') != $post->get('token')) {
 | 
			
		||||
    $messages->addMessage('error', "Invalid Session.");
 | 
			
		||||
    $log->error("Login Authentication - Invalid Session Token");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handle Username
 | 
			
		||||
$rawUsername = $post->get('username', null);
 | 
			
		||||
$cleanUsername = $v->clean($rawUsername); // Clean the input
 | 
			
		||||
$username = strtolower($cleanUsername); // Convert to lowercase
 | 
			
		||||
if (!$username) {
 | 
			
		||||
    $messages->addMessage('error', "No Username given.");
 | 
			
		||||
} 
 | 
			
		||||
 | 
			
		||||
// Handle Password
 | 
			
		||||
$password = $v->clean($post->get('password', null));
 | 
			
		||||
if ( empty($password) ) {
 | 
			
		||||
    $messages->addMessage('error', "Password Empty.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*************************************************************************************************************
 | 
			
		||||
 * Query Database
 | 
			
		||||
 ************************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
if ($messages->count('error') === 0) {
 | 
			
		||||
    $query = "SELECT id, username, email, password, blocked FROM users WHERE username = ? OR email = ?";
 | 
			
		||||
    $matched = $db->getRow($query, [$username, $username]);  
 | 
			
		||||
    if (empty($matched)) {
 | 
			
		||||
        $messages->addMessage('error', "User or Password incorrect.");
 | 
			
		||||
        $log->warning("Login Authentication - Login Error, user doesn't exist");
 | 
			
		||||
    }    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if ($messages->count('error') === 0) {
 | 
			
		||||
    // Re-apply pepper
 | 
			
		||||
    $peppered = hash_hmac('sha3-512', $password, $config['secure_key']);
 | 
			
		||||
 | 
			
		||||
    // Verify hashed password
 | 
			
		||||
    if (!password_verify($peppered, $matched['password'])) {
 | 
			
		||||
        $messages->addMessage('error', "User or Password incorrect.");
 | 
			
		||||
        $log->warning("Login Authentication - Login Error, password wrong");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Process Login or Redirect
 | 
			
		||||
if ($messages->count('error') === 0) {
 | 
			
		||||
    $query = "SELECT groupName FROM user_groups WHERE user_id = ?";
 | 
			
		||||
    $groups = $db->getRow($query, [$matched['id']]);
 | 
			
		||||
    $session->set('username', $cleanUsername);
 | 
			
		||||
    $session->set('group', $groups['groupName']);
 | 
			
		||||
    $redirect->url($url_success);
 | 
			
		||||
    $log->info("Login Authentication - Login Success);
 | 
			
		||||
} else {
 | 
			
		||||
    $redirect->url($url_fail);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										58
									
								
								controllers/create_admin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								controllers/create_admin.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
use Nickyeoman\Validation;
 | 
			
		||||
 | 
			
		||||
$validate = new Validation\Validate();
 | 
			
		||||
$valid = true;
 | 
			
		||||
$p = $post->all();
 | 
			
		||||
 | 
			
		||||
// Check secure key
 | 
			
		||||
if (empty($p['secure_key']) || $p['secure_key'] !== $config['secure_key']) {
 | 
			
		||||
    $valid = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Username
 | 
			
		||||
$name = $validate->clean($p['username']);
 | 
			
		||||
if (!$validate->minLength($name, 1)) {
 | 
			
		||||
    $valid = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Email
 | 
			
		||||
if (empty($p['email'])) {
 | 
			
		||||
    $valid = false;
 | 
			
		||||
} elseif (!$validate->isEmail($p['email'])) {
 | 
			
		||||
    $valid = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Password
 | 
			
		||||
if (empty($p['password'])) {
 | 
			
		||||
    $valid = false;
 | 
			
		||||
} else {
 | 
			
		||||
    // Use pepper + Argon2id
 | 
			
		||||
    $peppered = hash_hmac('sha3-512', $p['password'], $config['secure_key']);
 | 
			
		||||
    $hashed_password = password_hash($peppered, PASSWORD_ARGON2ID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if ($valid) {
 | 
			
		||||
    // Insert user
 | 
			
		||||
    $query = <<<EOSQL
 | 
			
		||||
    INSERT INTO `users`
 | 
			
		||||
        (`username`, `password`, `email`, `validate`, `confirmationToken`, `reset`, `created`, `updated`, `confirmed`, `blocked`) 
 | 
			
		||||
    VALUES 
 | 
			
		||||
        (?, ?, ?, NULL, NULL, NULL, NOW(), NOW(), 1, 0);
 | 
			
		||||
EOSQL;
 | 
			
		||||
 | 
			
		||||
    $params = [$name, $hashed_password, $p['email']];
 | 
			
		||||
    $db->query($query, $params);
 | 
			
		||||
    $userid = $db->lastid();
 | 
			
		||||
 | 
			
		||||
    // Assign admin group
 | 
			
		||||
    $groupInsertQuery = <<<EOSQL
 | 
			
		||||
    INSERT INTO `user_groups` (`user_id`, `groupName`) VALUES (?, ?);
 | 
			
		||||
EOSQL;
 | 
			
		||||
 | 
			
		||||
    $db->query($groupInsertQuery, [$userid, 'admin']);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Always redirect at end
 | 
			
		||||
$redirect->url('/novaconium');
 | 
			
		||||
							
								
								
									
										10
									
								
								controllers/dashboard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								controllers/dashboard.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<?php
 | 
			
		||||
$data['title'] = 'Novaconium Dashboard Page';
 | 
			
		||||
 | 
			
		||||
if ( empty($session->get('username'))) {
 | 
			
		||||
    $redirect->url('/novaconium/login');
 | 
			
		||||
    $messages->error('You are not loggedin');
 | 
			
		||||
    makeitso();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
view('@novacore/dashboard', $data);
 | 
			
		||||
							
								
								
									
										128
									
								
								controllers/init.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								controllers/init.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
$data = [
 | 
			
		||||
    'secure_key' => false,
 | 
			
		||||
    'gen_key' => NULL,
 | 
			
		||||
    'users_created' => false,
 | 
			
		||||
    'empty_users' => false,
 | 
			
		||||
    'show_login' => false,
 | 
			
		||||
    'token' => $session->get('token'),
 | 
			
		||||
    'title' => 'Novaconium Admin'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
// Check if SECURE KEY is Set in 
 | 
			
		||||
if ($config['secure_key'] !== null && strlen($config['secure_key']) === 64) {
 | 
			
		||||
    $data['secure_key'] = true;
 | 
			
		||||
} else {
 | 
			
		||||
    $data['gen_key'] = substr(bin2hex(random_bytes(32)), 0, 64);
 | 
			
		||||
    $log->warn('secure_key not detected');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check if user table exists
 | 
			
		||||
$query = <<<EOSQL
 | 
			
		||||
SELECT TABLE_NAME
 | 
			
		||||
FROM information_schema.tables
 | 
			
		||||
WHERE table_schema = DATABASE()
 | 
			
		||||
  AND TABLE_NAME = 'users';
 | 
			
		||||
EOSQL;
 | 
			
		||||
$result = $db->query($query);
 | 
			
		||||
 | 
			
		||||
if ($result->num_rows === 0) {
 | 
			
		||||
    $query = <<<EOSQL
 | 
			
		||||
    CREATE TABLE `users` (
 | 
			
		||||
        `id` int(11) NOT NULL AUTO_INCREMENT,
 | 
			
		||||
        `username` varchar(30) NOT NULL,
 | 
			
		||||
        `password` varchar(255) NOT NULL,
 | 
			
		||||
        `email` varchar(255) NOT NULL,
 | 
			
		||||
        `validate` varchar(32) DEFAULT NULL,
 | 
			
		||||
        `confirmationToken` varchar(255) DEFAULT NULL,
 | 
			
		||||
        `reset` varchar(32) DEFAULT NULL,
 | 
			
		||||
        `created` datetime NOT NULL,
 | 
			
		||||
        `updated` datetime DEFAULT NULL,
 | 
			
		||||
        `confirmed` tinyint(1) NOT NULL DEFAULT 0,
 | 
			
		||||
        `blocked` tinyint(1) NOT NULL DEFAULT 0,
 | 
			
		||||
        PRIMARY KEY (`id`)
 | 
			
		||||
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
 | 
			
		||||
EOSQL;
 | 
			
		||||
 | 
			
		||||
    $db->query($query);
 | 
			
		||||
    $data['users_created'] = true;
 | 
			
		||||
    $log->info('Users Table Created');
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check Usergroup
 | 
			
		||||
$query = <<<EOSQL
 | 
			
		||||
SELECT TABLE_NAME
 | 
			
		||||
FROM information_schema.tables
 | 
			
		||||
WHERE table_schema = DATABASE()
 | 
			
		||||
  AND TABLE_NAME = 'user_groups';
 | 
			
		||||
EOSQL;
 | 
			
		||||
$result = $db->query($query);
 | 
			
		||||
 | 
			
		||||
if ($result->num_rows === 0) {
 | 
			
		||||
    $query = <<<EOSQL
 | 
			
		||||
        CREATE TABLE `user_groups` (
 | 
			
		||||
            `id` INT(11) NOT NULL AUTO_INCREMENT,
 | 
			
		||||
            `user_id` INT(11) UNSIGNED NOT NULL,
 | 
			
		||||
            `groupName` VARCHAR(40) NOT NULL,
 | 
			
		||||
            PRIMARY KEY (`id`)
 | 
			
		||||
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 | 
			
		||||
EOSQL;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    $db->query($query);
 | 
			
		||||
    $log->info('User_groups Table Created');
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check Pages Table
 | 
			
		||||
$query = <<<EOSQL
 | 
			
		||||
SELECT TABLE_NAME
 | 
			
		||||
FROM information_schema.tables
 | 
			
		||||
WHERE table_schema = DATABASE()
 | 
			
		||||
  AND TABLE_NAME = 'pages';
 | 
			
		||||
EOSQL;
 | 
			
		||||
$result = $db->query($query);
 | 
			
		||||
 | 
			
		||||
if ($result->num_rows === 0) {
 | 
			
		||||
    $query = <<<EOSQL
 | 
			
		||||
    CREATE TABLE `pages` (
 | 
			
		||||
        `id` int(11) NOT NULL,
 | 
			
		||||
        `title` varchar(255) NOT NULL,
 | 
			
		||||
        `heading` varchar(255) NOT NULL,
 | 
			
		||||
        `description` varchar(255) NOT NULL,
 | 
			
		||||
        `keywords` varchar(255) NOT NULL,
 | 
			
		||||
        `author` varchar(255) NOT NULL,
 | 
			
		||||
        `slug` varchar(255) NOT NULL,
 | 
			
		||||
        `path` varchar(255) DEFAULT NULL,
 | 
			
		||||
        `intro` text DEFAULT NULL,
 | 
			
		||||
        `body` text DEFAULT NULL,
 | 
			
		||||
        `notes` text DEFAULT NULL,
 | 
			
		||||
        `created` datetime NOT NULL,
 | 
			
		||||
        `updated` datetime DEFAULT NULL,
 | 
			
		||||
        `draft` tinyint(1) NOT NULL DEFAULT 1,
 | 
			
		||||
        `changefreq` varchar(7) NOT NULL DEFAULT 'monthly',
 | 
			
		||||
        `priority` float(4,1) NOT NULL DEFAULT 0.0
 | 
			
		||||
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
 | 
			
		||||
EOSQL;
 | 
			
		||||
 | 
			
		||||
    $db->query($query);
 | 
			
		||||
    $log->info('Pages Table Created');
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check if a user exists
 | 
			
		||||
$result = $db->query("SELECT COUNT(*) as total FROM users");
 | 
			
		||||
$row = $result->fetch_assoc();
 | 
			
		||||
 | 
			
		||||
if ($row['total'] < 1) {
 | 
			
		||||
  $data['empty_users'] = true;
 | 
			
		||||
} else {
 | 
			
		||||
    $log->info('Init Run complete, all sql tables exist with a user.');
 | 
			
		||||
    // Everything is working, send them to login page
 | 
			
		||||
    $redirect->url('/novaconium/login');
 | 
			
		||||
    makeitso();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
view('@novacore/init', $data);
 | 
			
		||||
							
								
								
									
										9
									
								
								controllers/login.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								controllers/login.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<?php
 | 
			
		||||
$data['title'] = 'Novaconium Login Page';
 | 
			
		||||
 | 
			
		||||
// Don't come here if logged in
 | 
			
		||||
if ($session->get('username')) {
 | 
			
		||||
    $redirect->url('/novaconium/dashboard');
 | 
			
		||||
    makeitso();
 | 
			
		||||
}
 | 
			
		||||
view('@novacore/login');
 | 
			
		||||
							
								
								
									
										5
									
								
								controllers/logout.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								controllers/logout.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<?php
 | 
			
		||||
$session->kill();
 | 
			
		||||
$log->info("Logout - Logout Success - " . $_SERVER['REMOTE_ADDR']);
 | 
			
		||||
$redirect->url('/');
 | 
			
		||||
makeitso();
 | 
			
		||||
							
								
								
									
										19
									
								
								docs/Logs.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docs/Logs.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
# Logging
 | 
			
		||||
 | 
			
		||||
You can use the logging class to output to a file.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
use ```$log->info(The Message');```1
 | 
			
		||||
 | 
			
		||||
Logging levels are:
 | 
			
		||||
```
 | 
			
		||||
'DEBUG' => 0,
 | 
			
		||||
        'INFO' => 1,
 | 
			
		||||
        'WARNING' => 2,
 | 
			
		||||
        'ERROR' => 3,
 | 
			
		||||
    ];
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
It's recommended that production is set to ERROR. 
 | 
			
		||||
You set the log level in /App/config.php under 'loglevel' => 'ERROR'
 | 
			
		||||
If you are using CORXN a health check is run every 30 seconds which would fill the log file with info.
 | 
			
		||||
							
								
								
									
										3
									
								
								docs/Messages.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/Messages.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
# Messages
 | 
			
		||||
 | 
			
		||||
Messages is $messages.
 | 
			
		||||
							
								
								
									
										5
									
								
								docs/Post.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								docs/Post.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
# Post
 | 
			
		||||
 | 
			
		||||
There is a post class.
 | 
			
		||||
It cleans the post.
 | 
			
		||||
You can access it with $post.
 | 
			
		||||
							
								
								
									
										6
									
								
								docs/Redirect.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								docs/Redirect.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
# Redirect
 | 
			
		||||
 | 
			
		||||
How to use redirect class.
 | 
			
		||||
 | 
			
		||||
$redirect->url;
 | 
			
		||||
it's called on every page, if you set it more than once the last one is used.
 | 
			
		||||
							
								
								
									
										5
									
								
								docs/Session.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								docs/Session.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
# Sessions
 | 
			
		||||
 | 
			
		||||
There is a sessions handler built into Novaconium.
 | 
			
		||||
 | 
			
		||||
$session
 | 
			
		||||
							
								
								
									
										21
									
								
								docs/Twig-Views.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								docs/Twig-Views.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
# Twig 
 | 
			
		||||
 | 
			
		||||
## Overrides
 | 
			
		||||
 | 
			
		||||
You can override twig templates by creating the same file in the templates directory.
 | 
			
		||||
 | 
			
		||||
## Calling View
 | 
			
		||||
 | 
			
		||||
There is a $data that the system uses to store arrays for twig you can save to this array:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$data['newinfo'] = 'stuff';
 | 
			
		||||
view('templatename');
 | 
			
		||||
```
 | 
			
		||||
and that will automotically go to twig.
 | 
			
		||||
or you can create a new array and pass it in:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$anotherArr['newinfo'] = 'stuff';
 | 
			
		||||
view('templatename',$anotherArr);
 | 
			
		||||
```
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
# Twig Overrides
 | 
			
		||||
 | 
			
		||||
You can override twig templates by creating the same file in the templates directory.
 | 
			
		||||
							
								
								
									
										9
									
								
								services/Auth.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								services/Auth.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<?php
 | 
			
		||||
class Auth
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,2 +1,2 @@
 | 
			
		||||
MYSQL_ROOT_PASSWORD: random
 | 
			
		||||
MYSQL_PASSWORD: random
 | 
			
		||||
MYSQL_ROOT_PASSWORD=random
 | 
			
		||||
MYSQL_PASSWORD=random
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								skeleton/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								skeleton/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
data/
 | 
			
		||||
novaconium/vendor/
 | 
			
		||||
novaconium/logs/
 | 
			
		||||
@ -7,5 +7,8 @@ $config = [
 | 
			
		||||
        'pass' => '',
 | 
			
		||||
        'port' => 3306
 | 
			
		||||
    ],
 | 
			
		||||
    'base_url' => 'http://localhost:8000'
 | 
			
		||||
    'base_url' => 'http://localhost:8000',
 | 
			
		||||
    'secure_key' => '', //64 alphanumeric characters
 | 
			
		||||
    'logfile' => '/logs/novaconium.log',
 | 
			
		||||
    'loglevel' => 'ERROR' // 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'NONE'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@ -31,3 +31,17 @@ code {
 | 
			
		||||
h2 {
 | 
			
		||||
    margin-top: 40px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.error, div#debug {
 | 
			
		||||
    border: 1px solid red;
 | 
			
		||||
    padding: 30px;
 | 
			
		||||
    background-color: pink;
 | 
			
		||||
    color: darkred;
 | 
			
		||||
    margin: 0 auto;
 | 
			
		||||
    width: 900px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div#debug {
 | 
			
		||||
    margin-top: 100px;
 | 
			
		||||
    margin-bottom: 100px;
 | 
			
		||||
}
 | 
			
		||||
@ -3,6 +3,7 @@
 | 
			
		||||
class Database {
 | 
			
		||||
 | 
			
		||||
    private $conn;
 | 
			
		||||
    public $lastid;
 | 
			
		||||
 | 
			
		||||
    public function __construct($dbinfo) {
 | 
			
		||||
        $this->conn = new mysqli($dbinfo['host'], $dbinfo['user'], $dbinfo['pass'], $dbinfo['name']);
 | 
			
		||||
@ -13,43 +14,90 @@ class Database {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function query($query, $params = []) {
 | 
			
		||||
        // Prepare the SQL query
 | 
			
		||||
        if ($stmt = $this->conn->prepare($query)) {
 | 
			
		||||
            // Bind parameters to the prepared statement (if any)
 | 
			
		||||
        // Clean up pending results to avoid "commands out of sync"
 | 
			
		||||
        while ($this->conn->more_results() && $this->conn->next_result()) {
 | 
			
		||||
            if ($res = $this->conn->use_result()) {
 | 
			
		||||
                $res->free();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Prepare the SQL statement
 | 
			
		||||
        $stmt = $this->conn->prepare($query);
 | 
			
		||||
        if (!$stmt) {
 | 
			
		||||
            throw new Exception("Query preparation failed: " . $this->conn->error);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Bind parameters if needed
 | 
			
		||||
        if (!empty($params)) {
 | 
			
		||||
                $types = str_repeat('s', count($params)); // Assuming all params are strings
 | 
			
		||||
            $types = str_repeat('s', count($params)); // Use 's' for all types, or detect types dynamically
 | 
			
		||||
            $stmt->bind_param($types, ...$params);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Execute the statement
 | 
			
		||||
        if (!$stmt->execute()) {
 | 
			
		||||
            $stmt->close();
 | 
			
		||||
            throw new Exception("Query execution failed: " . $stmt->error);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // Return the statement result
 | 
			
		||||
            return $stmt;
 | 
			
		||||
        // Save last insert id if it's an INSERT query
 | 
			
		||||
        if (preg_match('/^\s*INSERT/i', $query)) {
 | 
			
		||||
            $this->lastid = $this->conn->insert_id;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new Exception("Query preparation failed: " . $this->conn->error);
 | 
			
		||||
            $this->lastid = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Decide what to return
 | 
			
		||||
        // For SELECT/SHOW etc., return result set
 | 
			
		||||
        if (preg_match('/^\s*(SELECT|SHOW|DESCRIBE|EXPLAIN)/i', $query)) {
 | 
			
		||||
            $result = $stmt->get_result();
 | 
			
		||||
            $stmt->close();
 | 
			
		||||
            return $result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // For INSERT/UPDATE/DELETE, return success status
 | 
			
		||||
        $success = $stmt->affected_rows;
 | 
			
		||||
        $stmt->close();
 | 
			
		||||
        return $success;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function lastid() {
 | 
			
		||||
        return $this->lastid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getRow($query, $params = []) {
 | 
			
		||||
        try {
 | 
			
		||||
            // Perform the query using prepared statement
 | 
			
		||||
            $stmt = $this->query($query, $params);
 | 
			
		||||
            // Prepare the SQL statement
 | 
			
		||||
            $stmt = $this->conn->prepare($query);
 | 
			
		||||
            if (!$stmt) {
 | 
			
		||||
                throw new Exception("Query preparation failed: " . $this->conn->error);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Get the result of the query
 | 
			
		||||
            // Bind parameters
 | 
			
		||||
            if (!empty($params)) {
 | 
			
		||||
                $types = str_repeat('s', count($params)); // You may improve this with actual type detection
 | 
			
		||||
                $stmt->bind_param($types, ...$params);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Execute the statement
 | 
			
		||||
            if (!$stmt->execute()) {
 | 
			
		||||
                $stmt->close();
 | 
			
		||||
                throw new Exception("Query execution failed: " . $stmt->error);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Get result
 | 
			
		||||
            $result = $stmt->get_result();
 | 
			
		||||
            $row = $result->fetch_assoc();
 | 
			
		||||
 | 
			
		||||
            $stmt->close();
 | 
			
		||||
            return $row;
 | 
			
		||||
 | 
			
		||||
            // Fetch the first row from the result
 | 
			
		||||
            return $result->fetch_assoc();
 | 
			
		||||
        } catch (Exception $e) {
 | 
			
		||||
            // Handle the exception (log it, display a message, etc.)
 | 
			
		||||
            echo "An error occurred: " . $e->getMessage();
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function getRows($query, $params = []) {
 | 
			
		||||
        $stmt = $this->conn->prepare($query);
 | 
			
		||||
        if (!$stmt) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								src/Logger.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/Logger.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
<?php
 | 
			
		||||
class Logger {
 | 
			
		||||
    protected string $logFile;
 | 
			
		||||
    protected int $logLevelThreshold;
 | 
			
		||||
 | 
			
		||||
    const LEVELS = [
 | 
			
		||||
        'DEBUG' => 0,
 | 
			
		||||
        'INFO' => 1,
 | 
			
		||||
        'WARNING' => 2,
 | 
			
		||||
        'ERROR' => 3,
 | 
			
		||||
        'NONE' => 999
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public function __construct(string $logFile, string $minLevel = 'DEBUG') {
 | 
			
		||||
        $this->logFile = $logFile;
 | 
			
		||||
        $minLevel = strtoupper($minLevel);
 | 
			
		||||
        $this->logLevelThreshold = self::LEVELS[$minLevel] ?? 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function log(string $level, string $message): void {
 | 
			
		||||
        $level = strtoupper($level);
 | 
			
		||||
        if (!isset(self::LEVELS[$level]) || self::LEVELS[$level] < $this->logLevelThreshold) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $time = date('Y-m-d H:i:s');
 | 
			
		||||
        $ip = $_SERVER['REMOTE_ADDR'];
 | 
			
		||||
        $logEntry = "[$time] [$ip] [$level] $message" . PHP_EOL;
 | 
			
		||||
 | 
			
		||||
        file_put_contents($this->logFile, $logEntry, FILE_APPEND | LOCK_EX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function debug(string $msg): void {
 | 
			
		||||
        $this->log('DEBUG', $msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function info(string $msg): void {
 | 
			
		||||
        $this->log('INFO', $msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function warning(string $msg): void {
 | 
			
		||||
        $this->log('WARNING', $msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function error(string $msg): void {
 | 
			
		||||
        $this->log('ERROR', $msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -8,6 +8,16 @@ class MessageHandler {
 | 
			
		||||
        'success' => []
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public function __construct(array $sessionMessages = [])
 | 
			
		||||
    {
 | 
			
		||||
        // Merge existing session messages into the default structure
 | 
			
		||||
        foreach ($this->messages as $type => $_) {
 | 
			
		||||
            if (isset($sessionMessages[$type]) && is_array($sessionMessages[$type])) {
 | 
			
		||||
                $this->messages[$type] = $sessionMessages[$type];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Add a message of a specific type
 | 
			
		||||
    public function addMessage($type, $message) {
 | 
			
		||||
        if (!isset($this->messages[$type])) {
 | 
			
		||||
@ -16,11 +26,22 @@ class MessageHandler {
 | 
			
		||||
        $this->messages[$type][] = $message;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function error($message){
 | 
			
		||||
        $this->addMessage('error', $message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get all messages of a specific type
 | 
			
		||||
    public function getMessages($type) {
 | 
			
		||||
        return $this->messages[$type] ?? [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get all messages of a specific type
 | 
			
		||||
    public function showMessages($type) {
 | 
			
		||||
        $result = $this->messages[$type] ?? [];
 | 
			
		||||
        $this->messages[$type] = []; // Clear messages after showing
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get all messages of all types
 | 
			
		||||
    public function getAllMessages() {
 | 
			
		||||
        return $this->messages;
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Use 
 | 
			
		||||
 * $redirect->to('/login');
 | 
			
		||||
 * $redirect->url('/login');
 | 
			
		||||
 * to trigger a redirect
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,12 +19,13 @@ class Router {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function loadRoutes() {
 | 
			
		||||
        require_once(FRAMEWORKPATH . '/config/routes.php');
 | 
			
		||||
        // Check if Path exists
 | 
			
		||||
        if (file_exists(BASEPATH . '/App/routes.php')) {
 | 
			
		||||
            require_once( BASEPATH . '/App/routes.php');
 | 
			
		||||
        } else {
 | 
			
		||||
            require_once(FRAMEWORKPATH . '/defaults/App/routes.php');
 | 
			
		||||
        }
 | 
			
		||||
        $routes = array_merge((array)$routes, (array)$framework_routes);
 | 
			
		||||
 | 
			
		||||
        return $routes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -67,8 +68,10 @@ class Router {
 | 
			
		||||
 | 
			
		||||
        // one to one match
 | 
			
		||||
        if (array_key_exists($this->path, $this->routes)) {
 | 
			
		||||
            if (!empty($this->routes[$this->path][$this->requestType])) {
 | 
			
		||||
                return $this->routes[$this->path][$this->requestType];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ($this->routes as $key => $value) {
 | 
			
		||||
            // Check if key contains a curly bracket, if not continue.  We already checked above.
 | 
			
		||||
@ -104,7 +107,12 @@ class Router {
 | 
			
		||||
    // checks if the file exists, sets file path
 | 
			
		||||
    private function setRouteFile() {
 | 
			
		||||
        
 | 
			
		||||
        if (str_starts_with($this->controller, 'NOVACONIUM')) {
 | 
			
		||||
            $trimmed = substr($this->controller, strlen('NOVACONIUM/'));
 | 
			
		||||
            $cp = FRAMEWORKPATH . '/controllers/' . $trimmed . '.php';
 | 
			
		||||
        } else {
 | 
			
		||||
            $cp = BASEPATH . '/App/controllers/' . $this->controller . '.php';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (file_exists($cp)) {
 | 
			
		||||
            return $cp;
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,7 @@ class Session {
 | 
			
		||||
 | 
			
		||||
    public function __construct() {
 | 
			
		||||
        session_start();
 | 
			
		||||
        if (!isset($_SESSION)) {
 | 
			
		||||
            $this->session = $_SESSION;
 | 
			
		||||
        if (!isset($_SESSION['token'])) {
 | 
			
		||||
            $this->setToken();
 | 
			
		||||
            $this->session['messages'] = [];
 | 
			
		||||
        } else {
 | 
			
		||||
@ -51,6 +50,7 @@ class Session {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function kill() {
 | 
			
		||||
        $_SESSION = [];
 | 
			
		||||
        session_destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ function dd(...$vars) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function makeitso() {
 | 
			
		||||
    global $session, $db, $redirect, $config, $messages;
 | 
			
		||||
    global $session, $db, $redirect, $config, $messages, $log;
 | 
			
		||||
 | 
			
		||||
    if (!empty($config['database']['host'])) {
 | 
			
		||||
        $db->close();
 | 
			
		||||
 | 
			
		||||
@ -10,19 +10,32 @@ if (file_exists(BASEPATH . '/App/config.php')) {
 | 
			
		||||
    require_once(FRAMEWORKPATH . '/defaults/App/config.php');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Logging
 | 
			
		||||
require_once(FRAMEWORKPATH . '/src/Logger.php');
 | 
			
		||||
$log = new Logger(BASEPATH . $config['logfile'], $config['loglevel']);
 | 
			
		||||
 | 
			
		||||
// Global Functions
 | 
			
		||||
require_once(FRAMEWORKPATH . '/src/functions.php');
 | 
			
		||||
 | 
			
		||||
// Creates the view() function using twig
 | 
			
		||||
$data = array();
 | 
			
		||||
require_once(FRAMEWORKPATH . '/src/twig.php');
 | 
			
		||||
 | 
			
		||||
// Messages
 | 
			
		||||
require_once(FRAMEWORKPATH . '/src/MessageHandler.php');
 | 
			
		||||
$messages = new MessageHandler;
 | 
			
		||||
 | 
			
		||||
// Start a Session
 | 
			
		||||
require_once(FRAMEWORKPATH . '/src/Session.php');
 | 
			
		||||
$session = new Session();
 | 
			
		||||
$data['token'] = $session->get('token');
 | 
			
		||||
if ($config['loglevel'] == 'DEBUG') {
 | 
			
		||||
    $data['debug'] = nl2br(print_r($session->debug(), true));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Messages
 | 
			
		||||
require_once(FRAMEWORKPATH . '/src/MessageHandler.php');
 | 
			
		||||
$messages = new MessageHandler($session->flash('messages'));
 | 
			
		||||
 | 
			
		||||
foreach (['error','notice'] as $key){
 | 
			
		||||
   $data[$key] = $messages->showMessages($key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Load Database Class
 | 
			
		||||
if (!empty($config['database']['host'])) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								src/twig.php
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/twig.php
									
									
									
									
									
								
							@ -1,11 +1,16 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
//Twig
 | 
			
		||||
function view($name = '', $data = []) {
 | 
			
		||||
    global $config; // Use the globally included $config
 | 
			
		||||
function view($name = '', $moreData = []) {
 | 
			
		||||
    global $config, $data; // Use the globally included $config
 | 
			
		||||
 | 
			
		||||
    if (!empty($moreData)){
 | 
			
		||||
        $data = array_merge($data, $moreData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $loader = new Twig\Loader\FilesystemLoader(BASEPATH . '/App/views/');
 | 
			
		||||
    $loader->addPath(BASEPATH . '/vendor/4lt/novaconium/twig', 'novaconium');
 | 
			
		||||
    $loader->addPath(FRAMEWORKPATH . '/twig', 'novaconium');
 | 
			
		||||
    $loader->addPath(FRAMEWORKPATH . '/views', 'novacore');
 | 
			
		||||
    $loader->addPath(BASEPATH . '/App/templates', 'override');
 | 
			
		||||
 | 
			
		||||
    $twig = new Twig\Environment($loader);
 | 
			
		||||
@ -15,7 +20,10 @@ function view($name = '', $data = []) {
 | 
			
		||||
 | 
			
		||||
    // Check if the template exists
 | 
			
		||||
    if (file_exists(BASEPATH . '/App/views/' . $name . '.html.twig')) {
 | 
			
		||||
        echo $twig->render("$name.html.twig", $data);
 | 
			
		||||
        echo $twig->render($name . '.html.twig', $data);
 | 
			
		||||
        return true;
 | 
			
		||||
    } elseif (str_starts_with($name, '@')) { // Check if using framework
 | 
			
		||||
        echo $twig->render($name . '.html.twig', $data);
 | 
			
		||||
        return true;
 | 
			
		||||
    } else {
 | 
			
		||||
        echo "Error: Twig Template ($name) Not Found.";
 | 
			
		||||
 | 
			
		||||
@ -48,5 +48,12 @@
 | 
			
		||||
      {% block footerafter %}{% endblock %}
 | 
			
		||||
    </footer>
 | 
			
		||||
 | 
			
		||||
    {% if debug is not empty %}
 | 
			
		||||
      <div id="debug">
 | 
			
		||||
          <h2>Debugging Information</h2>
 | 
			
		||||
          {{ debug|raw }}
 | 
			
		||||
      </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
  
 | 
			
		||||
{% include ['@override/foot.html.twig', '@novaconium/foot.html.twig'] %}
 | 
			
		||||
</body></html>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								views/dashboard.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								views/dashboard.html.twig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
{% extends '@novaconium/master.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    <h1>{{title}}</h1>
 | 
			
		||||
    <p>Dashboard page</p>
 | 
			
		||||
    <p><a href="/">Homepage</a></p>
 | 
			
		||||
    <p><a href="/novaconium/logout">logout</p>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
							
								
								
									
										67
									
								
								views/init.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								views/init.html.twig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
			
		||||
{% extends '@novaconium/master.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    <h1>{{title}}</h1>
 | 
			
		||||
 | 
			
		||||
    {% if not secure_key %}
 | 
			
		||||
        <div id="secure_key">
 | 
			
		||||
            <h2>Secure Key</h2>
 | 
			
		||||
            <p>Please set the <code>secure_key</code> in <code>App/config.php</code> to an alphanumeric code that is 64 characters in length.</p>
 | 
			
		||||
            <p>You can generate a secure key like this:</p>
 | 
			
		||||
            <pre><code>pwgen -sB 64 1</code></pre>
 | 
			
		||||
            <p>Or use this one:</p>
 | 
			
		||||
            <pre><code>{{gen_key}}</code></pre>
 | 
			
		||||
        </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% if users_created %}
 | 
			
		||||
        <div id="users_created">
 | 
			
		||||
            <h2>Users Table Created</h2>
 | 
			
		||||
            <p>There was no users table in the database.  One was created.</p>
 | 
			
		||||
        </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% if empty_users and secure_key %}
 | 
			
		||||
        <div id="users_created">
 | 
			
		||||
            <h2>Create Admin</h2>
 | 
			
		||||
            <p>No admin users exist, make an admin user now.</p>
 | 
			
		||||
 | 
			
		||||
            <form method="post" action="/novaconium/create_admin">
 | 
			
		||||
                <input type="hidden" name="token" value="{{ token }}" />
 | 
			
		||||
                
 | 
			
		||||
                <label for="username">Username:</label><br>
 | 
			
		||||
                <input type="text" id="username" name="username" required><br><br>
 | 
			
		||||
 | 
			
		||||
                <label for="email">Email:</label><br>
 | 
			
		||||
                <input type="text" id="email" name="email" required><br><br>
 | 
			
		||||
 | 
			
		||||
                <label for="password">Password:</label><br>
 | 
			
		||||
                <input type="password" id="password" name="password" required><br><br>
 | 
			
		||||
 | 
			
		||||
                <label for="secure_key">Secure Key <i>The <code>secure_key</code> from your config.php file</i>:</label><br>
 | 
			
		||||
                <input type="text" id="secure_key" name="secure_key" required><br><br>
 | 
			
		||||
 | 
			
		||||
                <button type="submit">Create User</button>
 | 
			
		||||
            </form>
 | 
			
		||||
        </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% if show_login %}
 | 
			
		||||
        <div id="users_created">
 | 
			
		||||
            <h2>Administrator Login</h2>
 | 
			
		||||
            
 | 
			
		||||
            <form method="post" action="/novaconium/login">
 | 
			
		||||
                <input type="hidden" name="token" value="{{ token }}" />
 | 
			
		||||
                
 | 
			
		||||
                <label for="username">Username:</label><br>
 | 
			
		||||
                <input type="text" id="username" name="username" required><br><br>
 | 
			
		||||
 | 
			
		||||
                <label for="password">Password:</label><br>
 | 
			
		||||
                <input type="password" id="password" name="password" required><br><br>
 | 
			
		||||
 | 
			
		||||
                <button type="submit">Login</button>
 | 
			
		||||
            </form>
 | 
			
		||||
        </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
							
								
								
									
										23
									
								
								views/login.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								views/login.html.twig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
{% extends '@novaconium/master.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    <h1>{{title}}</h1>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <div id="login_form">
 | 
			
		||||
        
 | 
			
		||||
        <form method="post" action="/novaconium/login">
 | 
			
		||||
            <input type="hidden" name="token" value="{{ token }}" />
 | 
			
		||||
            
 | 
			
		||||
            <label for="username">Username:</label><br>
 | 
			
		||||
            <input type="text" id="username" name="username" required><br><br>
 | 
			
		||||
 | 
			
		||||
            <label for="password">Password:</label><br>
 | 
			
		||||
            <input type="password" id="password" name="password" required><br><br>
 | 
			
		||||
 | 
			
		||||
            <button type="submit">Login</button>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user