First commit
This commit is contained in:
parent
815239516d
commit
61c79d48a6
|
@ -1 +1,6 @@
|
|||
|
||||
Parsedown.php
|
||||
credentials.csv
|
||||
pages/*
|
||||
public/font/*
|
||||
public/img/*
|
||||
!.gitkeep
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<div id="admin-bar">
|
||||
<h1>Accord's CMS</h1>
|
||||
<?php
|
||||
if (session_status() == PHP_SESSION_NONE) session_start();
|
||||
if (isset($_SESSION['loginUsername'])) {
|
||||
echo '<div id="logout">Welcome ' . $_SESSION['loginUsername'] . '<a class="button" href="/admin/logout.php">Logout</a></div>';
|
||||
} else {
|
||||
header('Location: /');
|
||||
}
|
||||
?>
|
||||
</div>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="/css/master.css">
|
||||
<link rel="stylesheet" href="/css/admin.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/admin-bar.php") ?>
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/tools.php") ?>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if (isset($_GET['page'])) {
|
||||
$page = new Page($_GET['page']);
|
||||
|
||||
if (isset($_GET['confirm'])) {
|
||||
$page->delete();
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
}
|
||||
|
||||
echo "<h2>Deletion of $page->title</h2>";
|
||||
echo "<p>Are you sure you want to delete this page?</p>";
|
||||
echo "<a class='button' href='/admin'>Cancel<a>";
|
||||
echo "<a class='button' href='/admin/delete.php?page=$page->slug&confirm=true'>Confirm<a>";
|
||||
}
|
||||
|
||||
?>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="/css/master.css">
|
||||
<link rel="stylesheet" href="/css/admin.css">
|
||||
<link rel="stylesheet" href="/css/edit.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/admin-bar.php") ?>
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/tools.php") ?>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
|
||||
$originalSlug = $_POST['originalSlug'];
|
||||
$newSlug = sluggify($_POST['slug']);
|
||||
|
||||
|
||||
|
||||
if (!$originalSlug) {
|
||||
// This is the creation of a new page
|
||||
$page = new Page();
|
||||
$page->title = $_POST['title'];
|
||||
$page->slug = $newSlug;
|
||||
$page->author = $_SESSION['loginUsername'];
|
||||
$page->cDate = time();
|
||||
$page->mDate = time();
|
||||
$page->content = $_POST['content'];
|
||||
|
||||
} else {
|
||||
// This is modification of an existing page
|
||||
$page = new Page($originalSlug);
|
||||
$page->title = $_POST['title'];
|
||||
$page->mDate = time();
|
||||
$page->content = $_POST['content'];
|
||||
if ($originalSlug !== $newSlug) {
|
||||
// The page needs to be moved
|
||||
$page->slug = $originalSlug;
|
||||
$page->rename($newSlug);
|
||||
}
|
||||
}
|
||||
|
||||
$page->write();
|
||||
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
|
||||
} else if (isset($_GET['page'])) {
|
||||
|
||||
$page = new Page($_GET['page']);
|
||||
|
||||
if ($page->slug) {
|
||||
echo "<h2>Editing $page->title</h2>";
|
||||
} else {
|
||||
echo "<h2>Editing a new page</h2>";
|
||||
}
|
||||
|
||||
echo "
|
||||
<form action='edit.php' method='post'>
|
||||
https://new.accords-library.com/<input type='text' name='slug' placeholder='' value='$page->slug' required><br>
|
||||
Title: <input type='text' name='title' placeholder='A great title...' value='$page->title' required><br>
|
||||
<textarea name='content' placeholder='Some awesome content...'>$page->content</textarea><br>
|
||||
<input type='hidden' name='originalSlug' value='" . $_GET['page'] . "'>
|
||||
<input class='button' type='submit'>
|
||||
</form>
|
||||
";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Accord's CMS</title>
|
||||
<link rel="stylesheet" href="/css/master.css">
|
||||
<link rel="stylesheet" href="/css/admin.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/admin-bar.php") ?>
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/tools.php") ?>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<div class="title">
|
||||
<h2>Pages</h2>
|
||||
<a class='button' href='/admin/edit.php?page='>Create a new page</a>
|
||||
</div>
|
||||
|
||||
<div class="page-list">
|
||||
|
||||
<p>Title</p>
|
||||
<p>Author</p>
|
||||
<p>Last edit</p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<?php
|
||||
|
||||
// Get all MD files
|
||||
foreach (getListSlugPages() as $pageSlug) {
|
||||
|
||||
$page = new Page($pageSlug);
|
||||
|
||||
echo "<p> - " . $page->title . "</p>";
|
||||
echo "<p>" . $page->author . "</p>";
|
||||
echo "<p>" . unixToDate($page->mDate) . "</p>";
|
||||
echo "<a class='button' href='/$page->slug'>View</a>";
|
||||
echo "<a class='button' href='/admin/edit.php?page=$page->slug'>Edit</a>";
|
||||
echo "<a class='button' href='/admin/delete.php?page=$page->slug'>Delete</a>";
|
||||
}
|
||||
echo '</div>';
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
session_start();
|
||||
session_destroy();
|
||||
header('Location: /login');
|
||||
?>
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
|
||||
{
|
||||
|
||||
$pagesFolder = $_SERVER["DOCUMENT_ROOT"] . '/../pages/';
|
||||
|
||||
class Page {
|
||||
public $title;
|
||||
public $slug;
|
||||
public $author;
|
||||
public $cDate;
|
||||
public $mDate;
|
||||
public $content;
|
||||
|
||||
function __construct($pageSlug = '') {
|
||||
if (existPage($pageSlug)) {
|
||||
$pageJSON = json_decode(file_get_contents(getPageJSONPath($pageSlug)));
|
||||
foreach ($pageJSON as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
$this->slug = $pageSlug;
|
||||
}
|
||||
}
|
||||
|
||||
function write() {
|
||||
$filePath = getPageJSONPath($this->slug);
|
||||
|
||||
// Remove attributes that should be serialized
|
||||
$slug = $this->slug;
|
||||
unset($this->slug);
|
||||
|
||||
$file = fopen($filePath, 'w');
|
||||
fwrite($file, json_encode($this));
|
||||
fclose($file);
|
||||
|
||||
// Add them back
|
||||
$this->slug = $slug;
|
||||
}
|
||||
|
||||
function delete() {
|
||||
$filePath = getPageJSONPath($this->slug);
|
||||
if (file_exists($filePath)) {
|
||||
unlink($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
function rename($newSlug) {
|
||||
rename(getPageJSONPath($this->slug), getPageJSONPath($newSlug));
|
||||
$this->slug = $newSlug;
|
||||
}
|
||||
|
||||
function parse() {
|
||||
require_once($_SERVER["DOCUMENT_ROOT"] . "/../Parsedown.php");
|
||||
$parsedown = new Parsedown();
|
||||
$parsedown->setSafeMode(true);
|
||||
return $parsedown->text($this->content);
|
||||
}
|
||||
}
|
||||
|
||||
function getListSlugPages() {
|
||||
global $pagesFolder;
|
||||
$pages = scandir($pagesFolder);
|
||||
$pages = array_slice($pages, 2);
|
||||
$result = array();
|
||||
foreach ($pages as $page) {
|
||||
if (substr($page, -5, 5) == '.json') {
|
||||
array_push($result, substr($page, 0, -5));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function existPage($pageSlug) {
|
||||
return file_exists(getPageJSONPath($pageSlug));
|
||||
}
|
||||
|
||||
function getPageJSONPath($pageSlug) {
|
||||
global $pagesFolder;
|
||||
return $pagesFolder . $pageSlug . '.json';
|
||||
}
|
||||
|
||||
function unixToDate($unixTime) {
|
||||
return date('Y-m-d', $unixTime);
|
||||
}
|
||||
|
||||
function sluggify($string) {
|
||||
$string = strtolower($string);
|
||||
$string = str_replace(' ', '-', $string);
|
||||
|
||||
$string = str_split($string);
|
||||
$result = "";
|
||||
$slugAcceptable = "abcdefghijklmnopqrstuvwxyz0123456789-";
|
||||
foreach ($string as $c) {
|
||||
if (stripos($slugAcceptable, $c) !== false) $result .= $c;
|
||||
}
|
||||
$result = trim($result, "-");
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,88 @@
|
|||
@font-face {
|
||||
font-family: customFont;
|
||||
src: url("/font/Quicksand-VariableFont_wght.ttf");
|
||||
}
|
||||
|
||||
:root {
|
||||
--break-point: 60em;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr var(--break-point) 1fr;
|
||||
place-content: center;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body > .container {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
border: var(--default-border);
|
||||
box-shadow: var(--default-box-shadow);
|
||||
grid-column: 2;
|
||||
transition: 1s margin-top;
|
||||
}
|
||||
|
||||
body > .container > .content {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
#admin-bar {
|
||||
max-width: var(--break-point);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--color-main-dark);
|
||||
color: var(--color-main-light);
|
||||
}
|
||||
|
||||
#admin-bar > #logout > .button {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.content > .title {
|
||||
display: grid;
|
||||
grid-gap: 1rem;
|
||||
grid-auto-flow: column;
|
||||
place-content: start;
|
||||
place-items: center start;
|
||||
}
|
||||
|
||||
.page-list {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 1fr auto auto auto;
|
||||
grid-row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.page-list > * {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.page-list > .button {
|
||||
place-self: center;
|
||||
}
|
||||
|
||||
.page-list p {
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 60em) {
|
||||
body {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
body > .container {
|
||||
grid-column: 1;
|
||||
margin-top: 0;
|
||||
border: unset;
|
||||
box-shadow: unset;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
body {
|
||||
display: grid;
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
textarea {
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
height: 30em;
|
||||
box-sizing: border-box;
|
||||
background-color: inherit;
|
||||
border: var(--default-border);
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
input[type = text] {
|
||||
background-color: inherit;
|
||||
border: var(--default-border);
|
||||
padding: 0.3em 1em;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
input[type = submit] {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
textarea:focus-visible, input:focus-visible {
|
||||
outline: unset;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
body {
|
||||
display: grid;
|
||||
place-content: center;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
font-size: 120%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#container {
|
||||
background: var(--color-main-light);
|
||||
border: var(--default-border);
|
||||
margin-bottom: 15vh;
|
||||
width: 20em;
|
||||
box-shadow: var(--default-box-shadow);
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
#container img {
|
||||
width: 50%;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
#myForm {
|
||||
display: inline-grid;
|
||||
grid-auto-flow: row;
|
||||
padding: 1em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myForm > input, #myForm > button {
|
||||
text-align: center;
|
||||
padding: 0.5em;
|
||||
border: solid 1px var(--color-main-dark);
|
||||
border-radius: 9999px;
|
||||
margin-top: 0.75em;
|
||||
font-size: 100%;
|
||||
font-family: customFont;
|
||||
color: var(--color_background);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#myForm > input:first-of-type {
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
#myForm > button {
|
||||
color: white;
|
||||
background: var(--color-main-dark);
|
||||
font-weight: 600;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
#answer {
|
||||
margin: 0;
|
||||
padding: 1em;
|
||||
border-radius: 0 0 var(--default_border_radius) var(--default_border_radius);
|
||||
background: var(--color_accent);
|
||||
font-size: 120%;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0% { transform: translate(0px, 0);}
|
||||
10% { transform: translate(1px, 0);}
|
||||
20% { transform: translate(3px, 0);}
|
||||
30% { transform: translate(5px, 0);}
|
||||
40% { transform: translate(3px, 0);}
|
||||
50% { transform: translate(1px, 0);}
|
||||
60% { transform: translate(-1px, 0);}
|
||||
70% { transform: translate(-3px, 0));}
|
||||
80% { transform: translate(-5px, 0);}
|
||||
90% { transform: translate(-3px, 0);}
|
||||
100% { transform: translate(-1px, 0));}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
@font-face {
|
||||
font-family: customFont;
|
||||
src: url("/font/Quicksand-VariableFont_wght.ttf");
|
||||
}
|
||||
|
||||
:root {
|
||||
--color-main-light: #FFF8E7;
|
||||
--color-main-base: #ffEBCD;
|
||||
--color-main-dark: #954535;
|
||||
--color-main-black: #1B1811;
|
||||
--default-border: solid 1px var(--color-main-dark);
|
||||
--default-box-shadow: #95453529 0 0 2em;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--color-main-light);
|
||||
color: var(--color-main-black);
|
||||
font-family: customFont;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
background: var(--color-main-light);
|
||||
padding: 0.3em 1.1em;
|
||||
color: var(--color-main-dark);
|
||||
transition: .1s background-color, .1s color, .1s border;
|
||||
border: solid 2px var(--color-main-dark);
|
||||
border-radius: 9999px;
|
||||
text-decoration-line: none;
|
||||
margin-left: 0.3em;
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: var(--color-main-dark);
|
||||
color: var(--color-main-light);
|
||||
border: solid 2px var(--color-main-dark);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php require_once($_SERVER["DOCUMENT_ROOT"] . "/admin/tools.php") ?>
|
||||
|
||||
<?php
|
||||
|
||||
if (isset($_GET['p'])) {
|
||||
$page = new Page($_GET['p']);
|
||||
echo $page->parse();
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Accord's Library - Login</title>
|
||||
<link rel="stylesheet" href="/css/master.css">
|
||||
<link rel="stylesheet" href="/css/login.css">
|
||||
</head>
|
||||
|
||||
<div id="container">
|
||||
<form method="POST" action="/login" id="myForm">
|
||||
<img src="/img/favicon.png" alt="">
|
||||
<h1>Accord's Library</h1>
|
||||
<input type="text" name="username" placeholder="Username" value="<?php if (isset($_POST['username'])) echo $_POST['username'] ?>" autocomplete="username" required>
|
||||
<input type="password" name="password" placeholder="Password" autocomplete="current-password" required>
|
||||
<button type="submit" name="submitButton" value="Submit">Sign In</button>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
function verifyKey($username, $password) {
|
||||
$csv = file_get_contents($_SERVER["DOCUMENT_ROOT"] . '/../credentials.csv');
|
||||
$hashes = explode(PHP_EOL, $csv);
|
||||
foreach ($hashes as $hash) {
|
||||
$hash = explode(';', $hash);
|
||||
if ($hash[0] == $username) {
|
||||
$hash = substr($hash[2], 0, -1);
|
||||
return password_verify($password, $hash);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($_POST['submitButton'] == "Submit") {
|
||||
|
||||
$username = filter_var($_POST["username"], FILTER_SANITIZE_STRING);
|
||||
$password = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
|
||||
|
||||
if (verifyKey($username, $password)) {
|
||||
$_SESSION['loginUsername'] = $username;
|
||||
header('Location: /admin');
|
||||
} else {
|
||||
unset($_SESSION['loginUsername']);
|
||||
echo '<p id="answer">The account name or password that you have entered is incorrect.</p>';
|
||||
echo '<style>body{animation: bw 1s;animation-fill-mode: forwards;}#container{animation: shake 0.2s;animation-iteration-count: 2;}</style>';
|
||||
}
|
||||
|
||||
//echo '<p>' . $username . ';' . password_hash($password, PASSWORD_DEFAULT) . '</p>';
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue