Basic user signup for web site working.

This commit is contained in:
Scott Duensing 2021-12-29 16:46:27 -06:00
parent 9489d1732a
commit ff205469cb
35 changed files with 820 additions and 37 deletions

1
.gitattributes vendored
View file

@ -2,3 +2,4 @@
*.gif filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text
*.odg filter=lfs diff=lfs merge=lfs -text
*.xlsx filter=lfs diff=lfs merge=lfs -text

3
.gitignore vendored
View file

@ -13,4 +13,5 @@ kanga.world/.htaccess
kanga.world/README.md
kanga.world/composer.json
kanga.world/index.php
kanga.world/site/config/config.php
kanga.world/content/home/*/

BIN
Multiplayer DOS Games.xlsx (Stored with Git LFS) Normal file

Binary file not shown.

BIN
SystemDiagram.odg (Stored with Git LFS)

Binary file not shown.

BIN
SystemDiagram.png (Stored with Git LFS)

Binary file not shown.

View file

@ -4,7 +4,15 @@ Title: Welcome!
Text:
(image: kangaworld.png imgclass:imagecenter width: 400)
(image: onlinegamingnetwork.png imgclass:imagecenter width: 400)
(image: kangaworldlogo.png imgclass:imagecenter width: 400)
(image: comingsoon.png imgclass:imagecenter width: 400)
(columns...)
[newshere]
++++
(image: kangaworld.png imgclass:imagecenter width: 300)
(image: onlinegamingnetwork.png imgclass:imagecenter width: 300)
(image: kangaworldlogo.png imgclass:imagecenter width: 300)
(image: comingsoon.png imgclass:imagecenter width: 300)
(...columns)

View file

@ -0,0 +1,17 @@
Title: Login
----
Alert: Invalid email or password
----
Email: Email
----
Password: Password
----
Button: Login

View file

@ -0,0 +1,17 @@
Title: Register
----
Alert: Invalid email or password
----
Email: Email
----
Password: Password
----
Button: Register

View file

@ -1 +1,17 @@
Title: Kanga World
----
Login: Login
----
Logout: Logout
----
Register: Register
----
User: User Settings

View file

@ -0,0 +1,34 @@
Title: User Settings
----
Alert: Invalid email or password
----
Email: New Email
----
Password: New Password
----
Button: Update User
----
Export: Export and download YOUR data:
----
Danger: Danger Zone
----
Delete_Button: Delete Account
----
Delete_Warning: Are you sure? This action cannot be reversed!

View file

@ -0,0 +1,8 @@
title: File
icon: file
sections:
content:
type: fields
fields:
description:
type: text

View file

@ -0,0 +1,4 @@
title: Image
icon: image
accept:
type: image

View file

@ -0,0 +1,29 @@
title: News
icon: document
columns:
left:
width: 1/2
fields:
text:
type: textarea
size: large
right:
width: 1/2
sections:
drafts:
extends: sections/news
headline: Drafts
status: draft
unlisted:
extends: sections/news
headline: In Review
status: unlisted
listed:
extends: sections/news
headline: Published
status: listed
layout: cards

View file

@ -0,0 +1,16 @@
title: Login
icon: 🔐
fields:
alert:
label: Alert text
type: text
email:
label: Label for email
type: email
password:
label: Label for password
type: text
button:
label: Button text
type: text

View file

@ -0,0 +1,44 @@
title: News Article
icon: document
num: '{{ page.date }}'
options:
changeTemplate: news
columns:
left:
width: 1/2
sections:
content:
type: fields
fields:
date:
type: date
display: DD-MMM-YYYY
default: today
required: true
text:
type: textarea
size: large
required: true
right:
width: 1/2
sections:
image:
type: files
required: true
layout: cards
ratio: 1/1
max: 1
accept:
extension: jpg, png, gif
meta:
type: fields
fields:
author:
type: users
multiple: false
default: '{{ kirby.user }}'
query: kirby.users.filterBy("role", "admin")
tags:
type: tags

View file

@ -0,0 +1,22 @@
title: Register
icon: 🔐
fields:
alert:
label: Alert text
type: text
email:
label: Label for email
type: email
email_info:
label: GDPR info for email
type: text
password:
label: Label for password
type: text
password_info:
label: GDPR info for password
type: text
button:
label: Button text
type: text

View file

@ -0,0 +1,6 @@
type: pages
headline: News Articles
info: "{{ page.date.toDate('d-M-Y') }}"
template: news
empty: No news yet
sortBy: date desc

View file

@ -1 +1,4 @@
title: User
permissions:
access:
panel: false

View file

@ -1,27 +0,0 @@
<?php
return [
'debug' => true,
'markdown' => [
'extra' => false
],
// For: https://github.com/getkirby/kql
'api' => [
'basicAuth' => true,
'allowInsecure' => true
],
'hooks' => [
// See: https://getkirby.com/docs/cookbook/extensions/subpage-builder
'route:after' => function ($route, $path, $method) {
$uid = explode('/', $path);
$uid = end($uid);
$uid = str_replace('+', '/', $uid);
$page = kirby()->page($uid);
if ($page && $page->children()->isEmpty()) {
buildPageTree($page);
}
}
]
];

View file

@ -0,0 +1,84 @@
<?php
return [
'debug' => true,
'markdown' => [
'extra' => false
],
// For REST APIs.
'api' => [
'basicAuth' => true,
'allowInsecure' => true
],
'hooks' => [
// See: https://getkirby.com/docs/cookbook/extensions/subpage-builder
'route:after' => function ($route, $path, $method) {
$uid = explode('/', $path);
$uid = end($uid);
$uid = str_replace('+', '/', $uid);
$page = kirby()->page($uid);
if ($page && $page->children()->isEmpty()) {
buildPageTree($page);
}
}
],
'email' => [
'transport' => [
'type' => 'smtp',
'host' => 'mail.jaegertech.com',
'port' => 465,
'security' => true,
'auth' => true,
'username' => '...',
'password' => '...'
]
],
'user.email.activation' => true,
'user.email.activation.sender' => 'noreply@kangaroopunch.com',
'user.email.activation.subject' => 'Kanga World Account Activation',
'routes' => [
[
'pattern' => 'logout',
'action' => function() {
if ($user = kirby()->user()) {
$user->logout();
}
go('/');
}
],
[
'pattern' => 'user/activate/(:alphanum)',
'action' => function($token) {
if (option('user.email.activation', false) === false) {
go();
}
$kirby = kirby();
$kirby->impersonate('kirby');
if ($user = $kirby->users()->findBy('emailActivationToken', $token)) {
if ($user->emailActivationToken()->toString() === Str::toType($token, 'string')) {
$user->update(['emailActivation' => true]);
go('user');
//go('CUSTOM_SUCCESSFUL_ACTIVATION_PAGE');
} else {
return false;
//go('CUSTOM_ERROR_ACTIVATION_PAGE');
//return page('CUSTOM_ERROR_ACTIVATION_PAGE');
}
}
$kirby->impersonate();
}
]
]
];

View file

@ -0,0 +1,69 @@
<?php
return function ($kirby) {
if ($kirby->user()) {
go('/');
}
$error = null;
$alert = null;
if ($kirby->request()->is('POST') && get('login')) {
$data = [
'email' => esc(get('email')),
'password' => esc(get('password'))
];
$rules = [
'email' => ['required', 'email'],
'password' => ['required']
];
$messages = [
'email' => 'Please enter a valid email adress',
'password' => 'Please enter a password'
];
// INVALID DATA
if($invalid = invalid($data, $rules, $messages)) {
$alert = $invalid;
$error = true;
// VALID DATA
} else {
// LOGIN USER
try {
$kirby->auth()->login($data['email'], $data['password']);
} catch (Exception $e) {
if(option('debug')) {
$alert['error'] = 'Invalid email or password: ' . $e->getMessage();
}
else {
$alert['error'] = 'Invalid email or password!';
}
}
// SUCCESSFUL
if (empty($alert) === true) {
$data = [];
go();
}
}
}
return [
'error' => $error,
'alert' => $alert,
'data' => $data ?? false
];
};

View file

@ -0,0 +1,111 @@
<?php
return function ($kirby) {
if($kirby->user()) {
go('/');
}
$error = null;
$alert = null;
// TOKEN FOR ACCOUNT ACTIVATION
$token = Str::random(16);
if($kirby->request()->is('post') && get('register')) {
$data = [
'email' => esc(get('email')),
'password' => esc(get('password'))
];
$rules = [
'email' => ['required', 'email'],
'password' => ['required', 'minLength' => 8]
];
$messages = [
'email' => 'Please enter a valid email adress',
'password' => 'Please enter a valid password'
];
// INVALID DATA
if($invalid = invalid($data, $rules, $messages)) {
$alert = $invalid;
$error = true;
// VALID DATA
} else {
$kirby = kirby();
$kirby->impersonate('kirby');
try {
// CREATE USER
$user = $kirby->users()->create([
'email' => $data['email'],
'role' => 'user',
'language' => 'en',
'password' => $data['password']
]);
// CHECK EMAIL ACTIVATION
if (option('user.email.activation', false) === true) {
$user->update([
'emailActivation' => false,
'emailActivationToken' => $token
]);
}
$kirby->impersonate();
} catch(Exception $e) {
if(option('debug')) {
$alert['error'] = 'The user could not be created: ' . $e->getMessage();
}
else {
$alert['error'] = 'The user could not be created!';
}
}
// SUCCESSFUL
if (empty($alert) === true && $user) {
// ACTIVATE ACCOUNT BY EMAIL IF ENABLED
if (option('user.email.activation', false) === true) {
$link = $kirby->site()->url() . "/user/activate/" . $token;
$email = $kirby->email([
'to' => $data['email'],
'from' => option('user.email.activation.sender'),
'subject' => option('user.email.activation.sender', 'Account Activation Link'),
'template' => 'account-activation',
'data' => [
'link' => $link,
]
]);
}
// LOGIN USER
if($user->login($data['password'])) {
go();
}
$data = [];
}
}
};
return [
'error' => $error,
'alert' => $alert,
'data' => $data ?? false
];
};

View file

@ -0,0 +1,146 @@
<?php
return function ($kirby, $page) {
if(!$kirby->user()) {
go('/');
}
$error = null;
$alert = null;
// CHECK ACCOUNT ACTIVATION
if(option('user.email.activation', false) === true && $kirby->user()->emailActivation()->toString() === '' || $kirby->user()->emailActivation() != true) {
$alert['error'] = 'Please check your emails to activate the account.';
}
// UPDATE USER
if($kirby->request()->is('post') && get('update')) {
$data = [
'email' => esc(get('email')),
'password' => esc(get('password'))
];
$rules = [
'email' => ['email'],
'password' => ['minLength' => 8]
];
$messages = [
'email' => 'Please enter a valid email adress',
'password' => 'Please enter an eight character password'
];
// INVALID DATA
if($invalid = invalid($data, $rules, $messages)) {
$alert = $invalid;
$error = true;
// VALID DATA
} else {
// EMAIL
if (V::email($data['email']) && !get('password')) {
try {
$kirby->user()->changeEmail($data['email']);
$success = 'Your email has been changed!';
// TOKEN FOR ACCOUNT RE-ACTIVATION
$token = Str::random(16);
$kirby->user()->update([
'emailActivation' => false,
'emailActivationToken' => $token
]);
// ACTIVATE ACCOUNT BY EMAIL IF ENABLED
if (option('user.email.activation', false) === true) {
$link = $kirby->site()->url() . "/user/activate/" . $token;
$email = $kirby->email([
'to' => $data['email'],
'from' => option('user.email.activation.sender'),
'subject' => option('user.email.activation.sender', 'Account Activation Link'),
'template' => 'account-activation',
'data' => [
'link' => $link,
]
]);
}
} catch(Exception $e) {
if(option('debug')) {
$alert['error'] = 'The user email could not be changed: ' . $e->getMessage();
}
else {
$alert['error'] = 'The user email could not be changed!';
}
}
}
// PASSWORD
if ($data['password']) {
try {
$kirby->user()->changePassword($data['password']);
$success = 'Your password has been changed!';
} catch(Exception $e) {
if(option('debug')) {
$alert['error'] = 'The user password could not be changed: ' . $e->getMessage();
}
else {
$alert['error'] = 'The user password could not be changed!';
}
}
}
// SUCCESSFUL
if (empty($alert) === true) {
$error = null;
}
}
}
// DELETE USER
if($kirby->request()->is('post') && get('delete')) {
try {
$kirby->user()->delete();
go('/');
} catch(Exception $e) {
if(option('debug')) {
$alert['error'] = 'The user could not be deleted: ' . $e->getMessage();
}
else {
$alert['error'] = 'The user could not be deleted!';
}
}
}
return [
'error' => $error,
'alert' => $alert,
'data' => $data ?? false,
'success' => $success ?? false
];
};

View file

@ -13,4 +13,5 @@
<body>
<script src="/assets/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="/assets/slick/slick.min.js"></script>
<?php snippet('menu') ?>
<div class="container mainpage">

View file

@ -0,0 +1,27 @@
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle Navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<?php foreach($site->children()->listed() as $item): ?>
<?php if ($item->hasListedChildren() && strcasecmp($item->title(), "Home")) { ?>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?= $item->title() ?></a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<?php foreach($item->children()->listed()->flip() as $child): ?>
<li><a class="dropdown-item" href="<?= $child->url() ?>"><?= $child->year() ?> - <?= $child->title() ?></a></li>
<?php endforeach ?>
</ul>
</li>
<?php } else { ?>
<li class="nav-item">
<a class="nav-link" href="<?= $item->url() ?>"><?= $item->title() ?></a>
</li>
<?php } ?>
<?php endforeach ?>
</ul>
</div>
</div>
</nav>

View file

@ -0,0 +1,4 @@
<div>
<p><?= isset($error) ? $page->alert()->html() : '' ?></p>
<p><?= isset($alert['error']) ? html($alert['error']) : '' ?></p>
</div>

View file

@ -0,0 +1,7 @@
<?php if ($user = $kirby->user()): ?>
<a <?php e($page->is('user'), 'aria-current ') ?> href="<?= url('user') ?>"><?= $site->user()->html
<a href="<?= url('logout') ?>"><?= $site->logout()->html() ?></a>
<?php else: ?>
<a <?php e($page->is('login'), 'aria-current ') ?> href="<?= url('login') ?>"><?= $site->login()->htm
<a <?php e($page->is('register'), 'aria-current ') ?> href="<?= url('register') ?>"><?= $site->regist
<?php endif ?>

View file

@ -0,0 +1,2 @@
<h1>Welcome</h1>
<p>Please click the link to activate your Account: <a href="<?= $link ?>"><?= $link ?></a></p>

View file

@ -0,0 +1,3 @@
Welcome,
Please click the link to activate your Account: <?= $link ?>

View file

@ -0,0 +1,30 @@
<?php
snippet('header');
// Display news entries where [newshere] appears in the kirbytext.
$marker = '<p>[newshere]</p>';
$left = strstr($page->text()->kirbytext(), $marker, true);
$right = substr($page->text()->kirbytext(), strlen($left) + strlen($marker));
print $left;
foreach($page->children()->listed()->flip() as $article):
?>
<article class="news">
<h3><?= $article->title()->html() ?></h3>
<?php if ($article->image()) { ?>
<img src="<?= $article->image()->resize(100, 100)->url() ?>" class="imageright"/>
<?php } ?>
<p class="newspublished">Published: <span class="newsdate"><?= $article->date()->toDate('d-M-Y') ?></span></p>
<p><?= $article->text()->excerpt(300) ?></p>
<a href="<?= $article->url() ?>">Read more...</a>
</article>
<?php
endforeach;
print $right;
snippet('footer');
?>

View file

@ -0,0 +1,27 @@
<?php snippet('header') ?>
<?php snippet('notification') ?>
<form method="post" action="<?= $page->url() ?>">
<fieldset>
<legend><?= $page->title()->html() ?></legend>
<section>
<label for="email"><?= $page->email()->html() ?></label>
<input type="email" id="email" name="email" value="<?= $data['email'] ?? '' ?>" autocomplete="email" autofocus required>
<?= isset($alert['email']) ? html($alert['email']) : '' ?>
</section>
<section>
<label for="password"><?= $page->password()->html() ?></label>
<input type="password" id="password" name="password" value="<?= $data['password'] ?? '' ?>" autocomplete="current-password" required>
<?= isset($alert['password']) ? html($alert['password']) : '' ?>
</section>
<section>
<input type="submit" name="login" value="<?= $page->button()->html() ?>">
</section>
</fieldset>
</form>
<?php snippet('footer') ?>

View file

@ -0,0 +1,9 @@
<?php snippet('header') ?>
<h3><?= $page->title() ?></h3>
<img src="<?= $page->image()->resize(250, 250)->url() ?>" class="imageright"/>
<p class="newspublished">Published: <span class="newsdate"><?= $page->date()->toDate('d-M-Y') ?></span></p>
<?= $page->text()->kirbytext() ?>
<a href="<?= url('home') ?>">Back...</a>
<?php snippet('footer') ?>

View file

@ -0,0 +1,5 @@
<html>
<head>
<meta http-equiv="refresh" content="0; url=<?= $page->redirect() ?>" />
</head>
</html>

View file

@ -0,0 +1,27 @@
<?php snippet('header') ?>
<?php snippet('notification') ?>
<form method="post" action="<?= $page->url() ?>">
<fieldset>
<legend><?= $page->title()->html() ?></legend>
<section>
<label for="email"><?= $page->email()->html() ?></label>
<input type="email" id="email" name="email" value="<?= $data['email'] ?? '' ?>" autocomplete="email" autofocus required>
<?= isset($alert['email']) ? html($alert['email']) : '' ?>
</section>
<section>
<label for="password"><?= $page->password()->html() ?></label>
<input type="password" id="password" name="password" value="<?= $data['password'] ?? '' ?>" minlength="8" autocomplete="new-password" required>
<?= isset($alert['password']) ? html($alert['password']) : '' ?>
</section>
<section>
<input type="submit" name="register" value="<?= $page->button()->html() ?>">
</section>
</fieldset>
</form>
<?php snippet('footer') ?>

View file

@ -0,0 +1,29 @@
<?php snippet('header') ?>
<?php snippet('notification') ?>
<?= $success ?? '' ?>
<form method="post" action="<?= $page->url() ?>">
<fieldset>
<legend><?= $data['email'] ?? $kirby->user()->email() ?></legend>
<section>
<label for="email"><?= $page->email()->html() ?></label>
<input type="text" id="email" name="email" value="<?= $data['email'] ?? '' ?>" placeholder="<?= $data['email'] ?? $kirby->user()->email() ?>" autocomplete="email">
<?= isset($alert['email']) ? html($alert['email']) : '' ?>
</section>
<section>
<label for="password"><?= $page->password()->html() ?></label>
<input type="password" id="password" name="password" value="<?= $data['password'] ?? '' ?>" placeholder="<?= $page->password()->html() ?>" autocomplete="new-password">
<?= isset($alert['password']) ? html($alert['password']) : '' ?>
</section>
<section>
<input type="submit" name="update" value="<?= $page->button()->html() ?>">
</section>
</fieldset>
</form>
<?php snippet('footer') ?>