Barebones user registration system with the Bootstrap front end
This commit is contained in:
parent
0b450c03c6
commit
cb95f54114
11
footer.php
Normal file
11
footer.php
Normal file
@ -0,0 +1,11 @@
|
||||
<hr />
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<div>
|
||||
Copyright © 2025 Your Company.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
10
head.php
Normal file
10
head.php
Normal file
@ -0,0 +1,10 @@
|
||||
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
||||
|
||||
<!-- -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" ></script>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/js/all.min.js"></script>
|
74
header.php
Normal file
74
header.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
$varNavbarLinks = [
|
||||
["Home", "/"],
|
||||
["Sign in", "/user/signin"],
|
||||
];
|
||||
|
||||
?>
|
||||
|
||||
<script>
|
||||
// Make the page's theme dark:
|
||||
$("body").first().attr("data-bs-theme", "dark");
|
||||
</script>
|
||||
|
||||
<div class="navbar navbar-expand bg-secondary d-flex px-3">
|
||||
|
||||
<div class="container justify-content-between">
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
<span class="navbar-brand">Home</span>
|
||||
|
||||
|
||||
<div class="dropdown d-lg-none">
|
||||
<a class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown">...</a>
|
||||
|
||||
<div class="dropdown-menu">
|
||||
<?php foreach ($varNavbarLinks as $varLink): ?>
|
||||
<a class="dropdown-item" href="<?= $varLink[1]; ?>"><i class="fa fa-fw fa-link pe-2"></i> <?= $varLink[0]; ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php foreach ($varNavbarLinks as $varLink): ?>
|
||||
<a class="nav-link d-none d-lg-inline" href="<?= $varLink[1]; ?>"><?= $varLink[0]; ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
|
||||
<div class="dropdown">
|
||||
|
||||
<?php
|
||||
$varUser = UserAuth::getUser();
|
||||
$strUserText = "User";
|
||||
|
||||
if ($varUser !== null)
|
||||
$strUserText = $varUser["user_name"] ?? $varUser["email"] ?? "User";
|
||||
?>
|
||||
|
||||
<a class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown">User</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-end">
|
||||
|
||||
<?php if ($varUser !== null): ?>
|
||||
|
||||
<a class="dropdown-item" href="/user/info"><i class="fa fa-fw fa-user pe-2"></i> <?= $strUserText; ?></a>
|
||||
|
||||
<a class="dropdown-item" href="/user/signout"><i class="fa fa-fw fa-right-from-bracket pe-2"></i> Sign Out</a>
|
||||
|
||||
<!--
|
||||
<a class="nav-link" href="/user/signin">Account</a>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<a class="dropdown-item" href="/user/signin"><i class="fa fa-fw fa-right-to-bracket pe-2"></i> Sign In</a>
|
||||
<a class="dropdown-item" href="/user/register"><i class="fa fa-fw fa-user-plus pe-2"></i> Register</a>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
99
init.php
Normal file
99
init.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
global $c;
|
||||
|
||||
$c = new DatabaseConnection(
|
||||
"sqlite",
|
||||
"sqlite.db");
|
||||
|
||||
class UserAuth
|
||||
{
|
||||
public static function getUser()
|
||||
{
|
||||
global $c;
|
||||
try
|
||||
{
|
||||
$strToken = Cookie::get("token");
|
||||
|
||||
if ($strToken !== null)
|
||||
if (strlen($strToken) > 0)
|
||||
{
|
||||
$varTokenUsers = $c->query(
|
||||
"SELECT *
|
||||
from tokens as t
|
||||
join user as u on u.email = t.email
|
||||
where
|
||||
t.token = ?
|
||||
and (
|
||||
t.expires is null
|
||||
or t.expires > current_timestamp
|
||||
)",
|
||||
$strToken);
|
||||
|
||||
$varUser = null;
|
||||
|
||||
if (count($varTokenUsers) == 1)
|
||||
$varUser = $varTokenUsers[0];
|
||||
else return null;
|
||||
|
||||
try
|
||||
{
|
||||
$varUserDetails = $c->query(
|
||||
"SELECT *
|
||||
from user_info as ui
|
||||
where
|
||||
ui.email = ?",
|
||||
$varUser["email"]);
|
||||
|
||||
if (count($varUserDetails) == 1)
|
||||
$varUser = array_merge($varUser, $varUserDetails[0]);
|
||||
}
|
||||
catch (Exception $x) {}
|
||||
return $varUser;
|
||||
}
|
||||
}
|
||||
catch (Exception $x) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function hasPermission($strPermission)
|
||||
{
|
||||
global $c;
|
||||
$varUser = UserAuth::getUser();
|
||||
|
||||
if ($varUser == null)
|
||||
return false;
|
||||
|
||||
$c->query(
|
||||
"CREATE table if not exists permission (
|
||||
id integer primary key autoincrement,
|
||||
email text not null,
|
||||
name text not null)");
|
||||
|
||||
$varPermissions = $c->query(
|
||||
"SELECT *
|
||||
from permission
|
||||
where
|
||||
email like ?
|
||||
and (
|
||||
name like ?
|
||||
or name like '*'
|
||||
)",
|
||||
$varUser["email"],
|
||||
$strPermission);
|
||||
|
||||
if (count($varPermissions) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function requirePermission($strPermission)
|
||||
{
|
||||
if (!UserAuth::hasPermission($strPermission))
|
||||
{
|
||||
BootstrapRender::message("You do not have permission to do that, please sign into an account that does.", "warning");
|
||||
Respond::redirect("/user/signin");
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
150
lib/BootstrapRender.php
Normal file
150
lib/BootstrapRender.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
class BootstrapRender
|
||||
{
|
||||
public static function message()
|
||||
{
|
||||
if (func_num_args() > 0)
|
||||
{
|
||||
Cookie::set("message", func_get_arg(0));
|
||||
|
||||
if (func_num_args() > 1)
|
||||
Cookie::set("messageClass", func_get_arg(1));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$strMessage = Cookie::get("message");
|
||||
$strMessageClass = Cookie::get("messageClass");
|
||||
|
||||
if (!isset($strMessageClass) || $strMessageClass == null || strlen($strMessageClass) < 1)
|
||||
$strMessageClass = "info";
|
||||
|
||||
?>
|
||||
<?php if (isset($strMessage) && $strMessage !== null && strlen($strMessage) > 0): ?>
|
||||
<div class="alert alert-<?= $strMessageClass; ?> d-none" id="page-message">
|
||||
<?= $strMessage; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$("#page-message")
|
||||
.hide()
|
||||
.removeClass("d-none")
|
||||
.fadeIn();
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
|
||||
Cookie::set("message");
|
||||
Cookie::set("messageClass");
|
||||
}
|
||||
|
||||
public static function input($varOptions)
|
||||
{
|
||||
$strName = $varOptions["name"];
|
||||
$strLabel = $varOptions["label"] ?? $strName;
|
||||
$strPlaceholder = $varOptions["placeholder"] ?? "Enter {$strLabel}";
|
||||
$strValue = $varOptions["value"] ?? "";
|
||||
$intReadonly = $varOptions["readonly"] ?? 0;
|
||||
$intDisabled = $varOptions["disabled"] ?? 0;
|
||||
$strType = $varOptions["type"] ?? "text";
|
||||
$intInline = $varOptions["inline"] ?? 0;
|
||||
|
||||
?>
|
||||
|
||||
<?php if ($intInline == 1): ?>
|
||||
|
||||
<div class="row g-3 align-items-center mb-3">
|
||||
<div class="col-3">
|
||||
<label class="col-form-label"><?= $strLabel; ?></label>
|
||||
</div>
|
||||
|
||||
<div class="col-8">
|
||||
<input type="<?= $strType; ?>"
|
||||
class="form-control"
|
||||
name="<?= $strName; ?>"
|
||||
placeholder="Enter <?= $strLabel; ?>"
|
||||
value="<?= $strValue; ?>"
|
||||
<?= $intReadonly? "readonly": ""; ?>
|
||||
<?= $intDisabled? "disabled": ""; ?> />
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<span class="form-text">test</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?= $strLabel; ?></label>
|
||||
<div class="input-group">
|
||||
|
||||
|
||||
<input type="<?= $strType; ?>"
|
||||
class="form-control"
|
||||
name="<?= $strName; ?>"
|
||||
placeholder="Enter <?= $strLabel; ?>"
|
||||
value="<?= $strValue; ?>"
|
||||
<?= $intReadonly? "readonly": ""; ?>
|
||||
<?= $intDisabled? "disabled": ""; ?> />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function buttons($varOptions)
|
||||
{
|
||||
$strLabel = $varOptions["label"] ?? "Actions";
|
||||
$intInputGroup = $varOptions["input_group"] ?? 0;
|
||||
$varButtons = $varOptions["buttons"] ?? [];
|
||||
$strButtonClass = $intInputGroup == 0? "me-1 mb-2": "";
|
||||
|
||||
?>
|
||||
<?php if (count($varButtons) > 0): ?>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?= $strLabel; ?></label>
|
||||
<div class="<?= $intInputGroup == 1? "input-group": ""; ?>">
|
||||
<?php foreach ($varButtons as $varButton): ?>
|
||||
|
||||
<?php
|
||||
$strLabel = $varButton["label"];
|
||||
$strIcon = $varButton["icon"] ?? null;
|
||||
|
||||
$strType = $varButton["type"] ?? null;
|
||||
$strOnclick = $varButton["onclick"] ?? null;
|
||||
$strHref = $varButton["href"] ?? null;
|
||||
|
||||
$strClass = $varButton["class"] ?? "outline-secondary";
|
||||
$strTag = "button";
|
||||
|
||||
if ($strHref !== null)
|
||||
$strTag = "a";
|
||||
?>
|
||||
|
||||
<<?= $strTag; ?>
|
||||
class="btn btn-<?= $strClass; ?> <?= $strButtonClass; ?>"
|
||||
<?= $strType !== null? "type=\"{$strType}\"": ""; ?>
|
||||
<?= $strOnclick !== null? "onclick=\"{$strOnclick}\"": ""; ?>
|
||||
<?= $strHref !== null? "href=\"{$strHref}\"": ""; ?>>
|
||||
|
||||
<?php if ($strIcon !== null): ?>
|
||||
<i class="fa fa-fw fa-<?= $strIcon; ?>"></i>
|
||||
<?php endif; ?>
|
||||
|
||||
<span><?= $strLabel; ?></span>
|
||||
</<?= $strTag; ?>>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
224
lib/TableEditor.php
Normal file
224
lib/TableEditor.php
Normal file
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
class TableEditor
|
||||
{
|
||||
public static function render($strTableName, $varColumns)
|
||||
{
|
||||
global $c;
|
||||
|
||||
$varRows = $c->query("SELECT * from {$strTableName}");
|
||||
$varKeys = [];
|
||||
|
||||
$strInput = file_get_contents("php://input");
|
||||
|
||||
if (strlen($strInput) > 0)
|
||||
{
|
||||
$a = json_decode($strInput, true);
|
||||
$output = [];
|
||||
|
||||
foreach ($a as $r)
|
||||
{
|
||||
$strColumns = "";
|
||||
$strQMarks = "";
|
||||
$strSetLns = "";
|
||||
$varValues = [];
|
||||
|
||||
foreach ($varColumns as $strCol)
|
||||
{
|
||||
$strColumns .= "{$strCol}, ";
|
||||
$strQMarks .= "?, ";
|
||||
$strSetLns .= "{$strCol} = ?, ";
|
||||
$varValues[] = $r[$strCol];
|
||||
}
|
||||
|
||||
$strColumns = preg_replace("/, $/", "", $strColumns);
|
||||
$strQMarks = preg_replace("/, $/", "", $strQMarks);
|
||||
$strSetLns = preg_replace("/, $/", "", $strSetLns);
|
||||
|
||||
|
||||
|
||||
if (strlen($r["id"]) < 1)
|
||||
{
|
||||
$c->query(
|
||||
"INSERT into {$strTableName} ({$strColumns}) values ({$strQMarks})",
|
||||
$varValues);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intval($r["delete"]) == 1)
|
||||
{
|
||||
$c->query("DELETE from {$strTableName} where id = ?", $r["id"]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$c->query(
|
||||
"UPDATE {$strTableName}
|
||||
set {$strSetLns}
|
||||
where id = ?",
|
||||
$varValues,
|
||||
$r["id"]);
|
||||
|
||||
$output[] = $r;
|
||||
}
|
||||
|
||||
Respond::json(["message" => "success", "output" => $output]);
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
||||
|
||||
<div class="container justify-content-between">
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
<span class="navbar-brand">Options</span>
|
||||
<a class="btn btn-outline-success" onclick="fnSave();"><i class="fa fa-fw fa-save"></i> Save</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* https://github.com/twbs/bootstrap/issues/37184 */
|
||||
.dropdown-menu {
|
||||
z-index: 1040 !important;
|
||||
}
|
||||
|
||||
/*
|
||||
th:first-child,
|
||||
th:last-child {
|
||||
width: 7.5%;
|
||||
background: #F00 !important;
|
||||
}*/
|
||||
|
||||
.table-responsive {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.w-input {
|
||||
width: 15em !important;
|
||||
}
|
||||
|
||||
tr td:first-child input[type="text"]
|
||||
{
|
||||
width: 5em !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-5">
|
||||
<div class="col-lg-12">
|
||||
|
||||
<?php if (count($varRows) > 0): ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach($varRows[0] as $k => $v): ?>
|
||||
<?php
|
||||
$varKeys[] = $k;
|
||||
?>
|
||||
<th><?= $k; ?></th>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<?php foreach ($varRows as $r): ?>
|
||||
<tr>
|
||||
<?php foreach ($varKeys as $k): ?>
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control w-input" name="<?= $k; ?>" value="<?= $r[$k]; ?>" />
|
||||
</div>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<td class="align-middle text-nowrap">
|
||||
<input type="hidden" name="delete" value="0" />
|
||||
<a class="" onclick="fnCloneRow(this);"><i class="fa fa-fw fa-copy"></i></a>
|
||||
<a class="" onclick="fnDeleteRow(this);"><i class="fa fa-fw fa-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
fnSerialize = function() {
|
||||
var a = [];
|
||||
|
||||
$("table tbody tr").each(function(i, x) {
|
||||
x = $(x);
|
||||
|
||||
var inputs = x.find("input");
|
||||
var o = {};
|
||||
|
||||
inputs.each(function(i2, x2) {
|
||||
x2 = $(x2);
|
||||
var key = x2.attr("name");
|
||||
var value = x2.val();
|
||||
o[key] = value;
|
||||
});
|
||||
|
||||
a.push(o);
|
||||
});
|
||||
|
||||
console.log(a);
|
||||
return a;
|
||||
};
|
||||
|
||||
fnSave = function()
|
||||
{
|
||||
var data = fnSerialize();
|
||||
|
||||
$.ajax({
|
||||
url: "",
|
||||
method: "post",
|
||||
data: JSON.stringify(data),
|
||||
success: function(r)
|
||||
{
|
||||
console.log(r);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
fnCloneRow = function(x)
|
||||
{
|
||||
x = $(x);
|
||||
var row = x.parents("tr").first();
|
||||
|
||||
var rowCopy = row.clone();
|
||||
|
||||
rowCopy.insertAfter(row);
|
||||
|
||||
rowCopy.find("input").each(function(i, x2) {
|
||||
x2 = $(x2);
|
||||
x2.val("");
|
||||
});
|
||||
};
|
||||
|
||||
fnDeleteRow = function(x)
|
||||
{
|
||||
x = $(x);
|
||||
var row = x.parents("tr").first();
|
||||
row.hide();
|
||||
row.find("[name='delete']").first().val("1");
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
92
pages/user/info.php
Normal file
92
pages/user/info.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
global $c;
|
||||
$strError = null;
|
||||
|
||||
$c->query(
|
||||
"CREATE table if not exists user_info (
|
||||
id integer primary key autoincrement,
|
||||
email text not null unique,
|
||||
user_name text null,
|
||||
display_name text null)");
|
||||
|
||||
$varUser = UserAuth::getUser();
|
||||
$strUsername = $varUser["user_name"] ?? "";
|
||||
$strDisplayName = $varUser["display_name"] ?? "";
|
||||
|
||||
if ($varUser == null)
|
||||
Respond::redirect("/");
|
||||
|
||||
try
|
||||
{
|
||||
if (Request::posts("user_name", "display_name"))
|
||||
{
|
||||
$strUsername = Request::getPosted("user_name");
|
||||
$strDisplayName = Request::getPosted("display_name");
|
||||
|
||||
if (!preg_match("/^[A-Za-z0-9]{1,}$/", $strUsername))
|
||||
throw new Exception("Username must be alphanumeric characters only");
|
||||
|
||||
$c->query(
|
||||
"INSERT or replace into user_info (email, user_name, display_name)
|
||||
select
|
||||
?,
|
||||
?,
|
||||
?",
|
||||
$varUser["email"],
|
||||
$strUsername,
|
||||
$strDisplayName);
|
||||
|
||||
BootstrapRender::message("Profile updated", "success");
|
||||
}
|
||||
}
|
||||
catch (Exception $x)
|
||||
{
|
||||
BootstrapRender::message($x->getMessage(), "danger");
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-5">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">Edit your account details here.</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
|
||||
<?php BootstrapRender::message(); ?>
|
||||
|
||||
<form method="post">
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "email",
|
||||
"label" => "E-Mail Address",
|
||||
"value" => $varUser["email"],
|
||||
"disabled" => 1,
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "user_name",
|
||||
"label" => "Username",
|
||||
"value" => $strUsername,
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "display_name",
|
||||
"label" => "Display Name",
|
||||
"value" => $strDisplayName,
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::buttons([
|
||||
"input_group" => 0,
|
||||
"buttons" => [[
|
||||
"icon" => "save",
|
||||
"label" => "Save",
|
||||
"type" => "submit",
|
||||
"class" => "outline-success"
|
||||
]]]); ?>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
6
pages/user/list.php
Normal file
6
pages/user/list.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
global $c;
|
||||
UserAuth::requirePermission("hello_world");
|
||||
TableEditor::render("user", ["email", "hash"]);
|
||||
?>
|
||||
|
5
pages/user/permissions.php
Normal file
5
pages/user/permissions.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
global $c;
|
||||
UserAuth::requirePermission("hello_world");
|
||||
TableEditor::render("permission", ["email", "name"]);
|
||||
?>
|
100
pages/user/register.php
Normal file
100
pages/user/register.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
global $c;
|
||||
|
||||
try
|
||||
{
|
||||
if (Request::posts("email", "password", "repeat"))
|
||||
{
|
||||
$strEmail = Request::getPosted("email");
|
||||
$strPassword = Request::getPosted("password");
|
||||
$strRepeat = Request::getPosted("repeat");
|
||||
|
||||
if (!preg_match("/^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$/", $strEmail))
|
||||
throw new Exception("Not a valid e-mail address");
|
||||
|
||||
if (Request::getPosted("password") !== Request::getPosted("repeat"))
|
||||
throw new Exception("Passwords do not match");
|
||||
|
||||
if (strlen($strPassword) < 6)
|
||||
throw new Exception("Password must be at least 6 characters");
|
||||
|
||||
$c->query(
|
||||
"CREATE table if not exists user (
|
||||
id integer primary key autoincrement,
|
||||
email text not null unique,
|
||||
hash text not null)");
|
||||
|
||||
$varUsers = $c->query("SELECT * from user where email like ?", $strEmail);
|
||||
|
||||
if (count($varUsers) > 0)
|
||||
throw new Exception("E-mail address in use");
|
||||
|
||||
$strHash = sha1($strPassword);
|
||||
|
||||
$c->query(
|
||||
"INSERT into user (email, hash) values (?, ?)",
|
||||
$strEmail,
|
||||
$strHash);
|
||||
|
||||
BootstrapRender::message("Registration was a success, please sign in to continue.");
|
||||
|
||||
Respond::redirect("/user/signin");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception $x)
|
||||
{
|
||||
BootstrapRender::message($x->getMessage(), "danger");
|
||||
}
|
||||
?>
|
||||
|
||||
<script>
|
||||
$(".app-header").hide();
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-5">
|
||||
<div class="col-md-4 offset-md-4">
|
||||
|
||||
<?php BootstrapRender::message(); ?>
|
||||
|
||||
<form method="post">
|
||||
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "email",
|
||||
"label" => "E-Mail Address",
|
||||
"value" => Request::getPosted("email")
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "password",
|
||||
"label" => "Password",
|
||||
"value" => Request::getPosted("password"),
|
||||
"type" => "password",
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "repeat",
|
||||
"label" => "Repeat Password",
|
||||
"value" => Request::getPosted("repeat"),
|
||||
"type" => "password",
|
||||
]); ?>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Actions</label>
|
||||
<div class="input-group">
|
||||
<button class="btn btn-outline-primary" type="submit">
|
||||
<i class="fa fa-fw fa-right-to-bracket"></i>
|
||||
<span>Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<a class="text-decoration-none" href="/user/signin">Already have an account?</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
88
pages/user/signin.php
Normal file
88
pages/user/signin.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
global $c;
|
||||
|
||||
try
|
||||
{
|
||||
if (Request::posts("email", "password"))
|
||||
{
|
||||
$strEmail = Request::getPosted("email");
|
||||
$strPassword = Request::getPosted("password");
|
||||
$strHash = sha1($strPassword);
|
||||
$varUsers = $c->query(
|
||||
"SELECT *
|
||||
from user
|
||||
where
|
||||
email like ?
|
||||
and hash = ?",
|
||||
$strEmail,
|
||||
$strHash);
|
||||
|
||||
if (count($varUsers) !== 1)
|
||||
throw new Exception("Zero or more than one user returned for credentials provided");
|
||||
|
||||
$strToken = sha1(microtime());
|
||||
|
||||
$c->query("CREATE table if not exists tokens (
|
||||
id integer primary key autoincrement,
|
||||
email text not null,
|
||||
token text not null,
|
||||
expires timestamp null)");
|
||||
|
||||
$c->query(
|
||||
"INSERT into tokens (email, token) values (?, ?)",
|
||||
$strEmail,
|
||||
$strToken);
|
||||
|
||||
Cookie::set("token", $strToken);
|
||||
|
||||
BootstrapRender::message(
|
||||
"Successfully signed in",
|
||||
"info");
|
||||
|
||||
Respond::redirect("/user/info");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception $x)
|
||||
{
|
||||
BootstrapRender::message($x->getMessage(), "danger");
|
||||
}
|
||||
?>
|
||||
|
||||
<script>
|
||||
$(".app-header").hide();
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-5">
|
||||
<div class="col-md-4 offset-md-4">
|
||||
<?php BootstrapRender::message(); ?>
|
||||
|
||||
<form method="post">
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "email",
|
||||
"label" => "E-Mail Address",
|
||||
"value" => Request::getPosted("email")
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::input([
|
||||
"name" => "password",
|
||||
"label" => "Password",
|
||||
"value" => Request::getPosted("password"),
|
||||
"type" => "password",
|
||||
]); ?>
|
||||
|
||||
<?php BootstrapRender::buttons([
|
||||
"input_group" => 0,
|
||||
"buttons" => [
|
||||
["icon" => "right-to-bracket", "label" => "Continue", "type" => "submit", "class" => "outline-primary"],
|
||||
["icon" => "home", "label" => "Home", "href" => "/"]
|
||||
]]); ?>
|
||||
|
||||
<div class="mb-3">
|
||||
<a class="text-decoration-none" href="/user/register">Don't have an account?</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
29
pages/user/signout.php
Normal file
29
pages/user/signout.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
global $c;
|
||||
$varUser = UserAuth::getUser();
|
||||
|
||||
if ($varUser !== null)
|
||||
{
|
||||
if (Request::getArg(0) == "all")
|
||||
{
|
||||
$c->query(
|
||||
"UPDATE tokens
|
||||
set
|
||||
expires = current_timestamp
|
||||
where email = ?",
|
||||
$varUser["email"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$c->query(
|
||||
"UPDATE tokens
|
||||
set
|
||||
expires = current_timestamp
|
||||
where token = ?",
|
||||
$varUser["token"]);
|
||||
}
|
||||
}
|
||||
|
||||
BootstrapRender::message("You have successfully signed out");
|
||||
Respond::redirect("/user/signin");
|
||||
?>
|
Loading…
Reference in New Issue
Block a user