Initial commit for the blogging engine, contains SQLite authentication
This commit is contained in:
parent
82b42b2bda
commit
664544fea4
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>
|
80
header.php
Normal file
80
header.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
$varNavbarLinks = [
|
||||||
|
["Home", "/"],
|
||||||
|
["Sign in", "/user/signin"],
|
||||||
|
];
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Make the page's theme dark:
|
||||||
|
$("body").first().attr("data-bs-theme", "dark");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="offcanvas offcanvas-start">
|
||||||
|
<div class="offcanvas-body">
|
||||||
|
Hello world <span data-bs-dismiss="offcanvas">x</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
159
lib/BootstrapRender.php
Normal file
159
lib/BootstrapRender.php
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
<?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;
|
||||||
|
$strTag = $varOptions["tag"] ?? "input";
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?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">
|
||||||
|
<<?= $strTag; ?> type="<?= $strType; ?>"
|
||||||
|
class="form-control"
|
||||||
|
name="<?= $strName; ?>"
|
||||||
|
placeholder="Enter <?= $strLabel; ?>"
|
||||||
|
value="<?= $strValue; ?>"
|
||||||
|
<?= $intReadonly? "readonly": ""; ?>
|
||||||
|
<?= $intDisabled? "disabled": ""; ?>
|
||||||
|
|
||||||
|
<?php if ($strTag == "textarea"): ?>
|
||||||
|
><?= $strValue; ?></<?= $strTag; ?>>
|
||||||
|
<?php else: ?>
|
||||||
|
/>
|
||||||
|
<?php endif; ?>
|
||||||
|
</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">
|
||||||
|
<<?= $strTag; ?> type="<?= $strType; ?>"
|
||||||
|
class="form-control"
|
||||||
|
name="<?= $strName; ?>"
|
||||||
|
placeholder="Enter <?= $strLabel; ?>"
|
||||||
|
value="<?= $strValue; ?>"
|
||||||
|
<?= $intReadonly? "readonly": ""; ?>
|
||||||
|
<?= $intDisabled? "disabled": ""; ?>
|
||||||
|
|
||||||
|
<?php if ($strTag == "textarea"): ?>
|
||||||
|
><?= $strValue; ?></<?= $strTag; ?>>
|
||||||
|
<?php else: ?>
|
||||||
|
/>
|
||||||
|
<?php endif; ?>
|
||||||
|
</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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
1994
lib/Parsedown.php
Normal file
1994
lib/Parsedown.php
Normal file
File diff suppressed because it is too large
Load Diff
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
94
pages/edit/index.php
Normal file
94
pages/edit/index.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
global $c;
|
||||||
|
|
||||||
|
$strId = Request::getArg(0);
|
||||||
|
$strPath = "";
|
||||||
|
$strContent = "";
|
||||||
|
|
||||||
|
if (strlen($strId) > 0)
|
||||||
|
{
|
||||||
|
$varRows = $c->query("SELECT * from post where id = ?", $strId);
|
||||||
|
|
||||||
|
if (count($varRows) !== 1)
|
||||||
|
{
|
||||||
|
BootstrapRender::message("Zero or more than one row returned", "danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
$varRow = $varRows[0];
|
||||||
|
$strPath = $varRow["path"];
|
||||||
|
$strContent = $varRow["content"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (Request::posts("path", "content"))
|
||||||
|
{
|
||||||
|
$strPath = Request::getPosted("path");
|
||||||
|
$strContent = Request::getPosted("content");
|
||||||
|
|
||||||
|
if ($strId == null || strlen($strId) < 1)
|
||||||
|
{
|
||||||
|
$c->query(
|
||||||
|
"INSERT into post (author, path, content)
|
||||||
|
values (?, ?, ?)",
|
||||||
|
"caharkness@gmail.com",
|
||||||
|
$strPath,
|
||||||
|
$strContent);
|
||||||
|
|
||||||
|
$strId = $c->query("SELECT * from post where rowid = last_insert_rowid()")[0]["id"];
|
||||||
|
}
|
||||||
|
|
||||||
|
$c->query(
|
||||||
|
"UPDATE post
|
||||||
|
set
|
||||||
|
path = ?,
|
||||||
|
content = ?,
|
||||||
|
updated = current_timestamp",
|
||||||
|
$strPath,
|
||||||
|
$strContent);
|
||||||
|
|
||||||
|
Respond::redirect("/edit/{$strId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($strId) > 0)
|
||||||
|
{
|
||||||
|
$varRows = $c->query("SELECT * from post where id = ?", $strId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container my-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<?php BootstrapRender::message(); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
|
||||||
|
<?php BootstrapRender::input([
|
||||||
|
"name" => "path",
|
||||||
|
"label" => "Path",
|
||||||
|
"value" => $strPath
|
||||||
|
]); ?>
|
||||||
|
|
||||||
|
<?php BootstrapRender::input([
|
||||||
|
"name" => "content",
|
||||||
|
"label" => "Content",
|
||||||
|
"tag" => "textarea",
|
||||||
|
"value" => $strContent
|
||||||
|
]); ?>
|
||||||
|
|
||||||
|
<?php BootstrapRender::buttons([
|
||||||
|
"buttons" => [[
|
||||||
|
"label" => "Submit",
|
||||||
|
"icon" => "save"
|
||||||
|
]]
|
||||||
|
]); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
39
pages/index.php
Normal file
39
pages/index.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$strPath = "/";
|
||||||
|
$strPath .= implode("/", Request::getPathParts());
|
||||||
|
|
||||||
|
global $c;
|
||||||
|
|
||||||
|
$c->query(
|
||||||
|
"CREATE table if not exists post (
|
||||||
|
id integer primary key autoincrement,
|
||||||
|
author text not null,
|
||||||
|
path text not null,
|
||||||
|
content text not null,
|
||||||
|
created timestamp not null default current_timestamp,
|
||||||
|
updated timestamp not null default current_timestamp)");
|
||||||
|
|
||||||
|
$varPosts = $c->query(
|
||||||
|
"SELECT *
|
||||||
|
from post
|
||||||
|
where
|
||||||
|
path like ?
|
||||||
|
or path like '*'",
|
||||||
|
$strPath);
|
||||||
|
|
||||||
|
$varParsedown = new Parsedown();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php foreach ($varPosts as $p): ?>
|
||||||
|
<div class="container my-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<?php
|
||||||
|
$strContent = $varParsedown->text($p["content"]);
|
||||||
|
echo $strContent;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
29
pages/pd/index.php
Normal file
29
pages/pd/index.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
$varParsedown = new Parsedown();
|
||||||
|
$strText = $varParsedown->text("
|
||||||
|
# Hello world
|
||||||
|
|
||||||
|
1. Testing 123
|
||||||
|
2. Testing 456
|
||||||
|
|
||||||
|
```
|
||||||
|
if then else
|
||||||
|
```
|
||||||
|
");
|
||||||
|
|
||||||
|
if (Request::getArg(0) == "plain")
|
||||||
|
{
|
||||||
|
ob_clean();
|
||||||
|
echo $strText;
|
||||||
|
ob_end_flush();
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container my-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<?= $strText; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
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