Add Auth0, partial support
This commit is contained in:
parent
41853a7645
commit
4aa6e832c7
1
.gitignore
vendored
1
.gitignore
vendored
@ -259,3 +259,4 @@ src/environment.txt
|
||||
|
||||
# PHP ignore files
|
||||
src/vendor
|
||||
src/.env
|
||||
|
9
src/Caddyfile
Normal file
9
src/Caddyfile
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
frankenphp
|
||||
order php_server before file_server
|
||||
}
|
||||
http://localhost:3000 {
|
||||
root * ./public
|
||||
try_files {path} {path}.php
|
||||
php_server
|
||||
}
|
@ -1,16 +1,26 @@
|
||||
{
|
||||
"name": "bit-badger/my-prayer-journal",
|
||||
"minimum-stability": "dev",
|
||||
"minimum-stability": "beta",
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"ext-pdo": "*",
|
||||
"ext-sqlite3": "*",
|
||||
"bit-badger/pdo-document": "^1",
|
||||
"visus/cuid2": "^4"
|
||||
"visus/cuid2": "^4",
|
||||
"guzzlehttp/guzzle": "^7.8",
|
||||
"guzzlehttp/psr7": "^2.6",
|
||||
"http-interop/http-factory-guzzle": "^1.2",
|
||||
"auth0/auth0-php": "^8.11",
|
||||
"vlucas/phpdotenv": "^5.6"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyPrayerJournal\\": "lib/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2231
src/composer.lock
generated
2231
src/composer.lock
generated
File diff suppressed because it is too large
Load Diff
3
src/convert-from-v3.php
Normal file
3
src/convert-from-v3.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
// TODO: write migration
|
53
src/lib/Auth.php
Normal file
53
src/lib/Auth.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace MyPrayerJournal;
|
||||
|
||||
use Auth0\SDK\Auth0;
|
||||
use Auth0\SDK\Exception\ConfigurationException;
|
||||
|
||||
class Auth
|
||||
{
|
||||
private static ?Auth0 $auth0 = null;
|
||||
|
||||
public static function client(): Auth0
|
||||
{
|
||||
if (is_null(self::$auth0)) {
|
||||
self::$auth0 = new Auth0([
|
||||
'domain' => $_ENV['AUTH0_DOMAIN'],
|
||||
'clientId' => $_ENV['AUTH0_CLIENT_ID'],
|
||||
'clientSecret' => $_ENV['AUTH0_CLIENT_SECRET'],
|
||||
'cookieSecret' => $_ENV['AUTH0_COOKIE_SECRET']
|
||||
]);
|
||||
}
|
||||
return self::$auth0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a log on with Auth0
|
||||
*
|
||||
* @throws ConfigurationException If the Auth0 client is not configured correctly
|
||||
*/
|
||||
public static function logOn(): never
|
||||
{
|
||||
$params = match (true) {
|
||||
$_SERVER['PHP_SELF'] <> '/user/log-on.php' => ['redirectUri' => $_SERVER['PHP_SELF']],
|
||||
default => []
|
||||
};
|
||||
|
||||
self::client()->clear();
|
||||
header('Location: ' . self::client()->login($_ENV['AUTH0_BASE_URL'] . '/user/log-on/success', $params));
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log off from this application and Auth0
|
||||
*
|
||||
* @throws ConfigurationException If the Auth0 client is not configured correctly
|
||||
*/
|
||||
public static function logOff(): never
|
||||
{
|
||||
session_destroy();
|
||||
header('Location: ' . self::client()->logout($_ENV['AUTH0_BASE_URL']));
|
||||
exit;
|
||||
}
|
||||
}
|
117
src/lib/Layout.php
Normal file
117
src/lib/Layout.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace MyPrayerJournal;
|
||||
|
||||
class Layout
|
||||
{
|
||||
/**
|
||||
* Create the `DOCTYPE` declaration, `html`, and `head` tags for the page
|
||||
*
|
||||
* @param string $title The title of the page
|
||||
*/
|
||||
public static function htmlHead(string $title): void
|
||||
{
|
||||
if (is_htmx()) {
|
||||
echo "<!DOCTYPE html><html lang=en><head lang=en><title>$title « myPrayerJournal</title></head>";
|
||||
} else {
|
||||
echo <<<HEAD
|
||||
<!DOCTYPE html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta name=viewport content="width=device-width, initial-scale=1">
|
||||
<meta name=description content="Online prayer journal - free w/Google or Microsoft account">
|
||||
<title>$title « myPrayerJournal</title>
|
||||
<link href=https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css rel=stylesheet
|
||||
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
||||
crossorigin=anonymous>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel=stylesheet>
|
||||
<link href=/style/style.css rel=stylesheet>
|
||||
</head>
|
||||
HEAD;
|
||||
}
|
||||
}
|
||||
|
||||
private static function navLink(string $url, string $text): void
|
||||
{
|
||||
$classAttr = match (true) {
|
||||
str_starts_with($_SERVER['PHP_SELF'], $url) => ['class' => 'is-active-route'],
|
||||
default => []
|
||||
};
|
||||
echo '<li class=nav-item>';
|
||||
page_link($url, $text, $classAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default navigation bar, which will load the items on page load, and whenever a refresh event occurs
|
||||
*/
|
||||
public static function navBar(): void
|
||||
{ ?>
|
||||
<nav class="navbar navbar-dark" role="navigation">
|
||||
<div class=container-fluid><?php
|
||||
page_link('/', '<span class=m>my</span><span class=p>Prayer</span><span class=j>Journal</span>',
|
||||
['class' => 'navbar-brand']); ?>
|
||||
<ul class="navbar-nav me-auto d-flex flex-row"><?php
|
||||
if (key_exists('user_id', $_SESSION)) {
|
||||
self::navLink('/journal', 'Journal');
|
||||
self::navLink('/requests/active', 'Active');
|
||||
if (key_exists('has_snoozed', $_SESSION)) self::navLink('/requests/snoozed', 'Snoozed');
|
||||
self::navLink('/requests/answered', 'Answered'); ?>
|
||||
<li class=nav-item><a href=/user/log-off>Log Off</a><?php
|
||||
} else { ?>
|
||||
<li class=nav-item><a href=/user/log-on>Log On</a><?php
|
||||
}
|
||||
self::navLink('/docs', 'Docs'); ?>
|
||||
</ul>
|
||||
</div>
|
||||
</nav><?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop .0 or .0.0 from the end of the version to format it for display
|
||||
*
|
||||
* @return string The version of the application for user display
|
||||
*/
|
||||
private static function displayVersion(): string {
|
||||
[$major, $minor, $rev] = explode('.', MPJ_VERSION);
|
||||
$minor = $minor == '0' ? '' : ".$minor";
|
||||
$rev = match (true) {
|
||||
$rev == '0' => '',
|
||||
str_starts_with($rev, '0-') => substr($rev, 1),
|
||||
default => ".$rev"
|
||||
};
|
||||
return "v$major$minor$rev";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the footer
|
||||
*/
|
||||
public static function htmlFoot(): void
|
||||
{ ?>
|
||||
<footer class=container-fluid>
|
||||
<p class="text-muted text-end">
|
||||
myPrayerJournal <?=self::displayVersion();?><br>
|
||||
<em><small><?php
|
||||
page_link('/legal/privacy-policy', 'Privacy Policy');
|
||||
echo ' • ';
|
||||
page_link('/legal/terms-of-service', 'Terms of Service');
|
||||
echo ' • '; ?>
|
||||
<a href=https://git.bitbadger.solutions/bit-badger/myPrayerJournal target=_blank
|
||||
rel=noopener>Developed</a> and hosted by
|
||||
<a href=https://bitbadger.solutions target=_blank rel=noopener>Bit Badger Solutions</a>
|
||||
</small></em>
|
||||
<script src=https://unpkg.com/htmx.org@2.0.0 crossorigin=anonymous
|
||||
integrity="sha384-wS5l5IKJBvK6sPTKa2WZ1js3d947pvWXbPJ1OmWfEuxLgeHcEbjUUA5i9V5ZkpCw"></script>
|
||||
<script>if (!htmx) document.write('<script src=\"/script/htmx.min.js\"><\/script>')</script>
|
||||
<script async src=https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js
|
||||
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
||||
crossorigin=anonymous></script>
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
if (!bootstrap) document.write('<script src=\"/script/bootstrap.bundle.min.js\"><\/script>')
|
||||
}, 2000)
|
||||
</script>
|
||||
<script src=/script/mpj.js></script>
|
||||
</footer><?php
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace MyPrayerJournal;
|
||||
|
||||
use BitBadger\PDODocument\DocumentException;
|
||||
|
||||
/**
|
||||
* A note entered on a prayer request
|
||||
*/
|
||||
@ -12,4 +14,17 @@ class Note
|
||||
* @param string $text The text of the note
|
||||
*/
|
||||
public function __construct(public string $asOf, public string $text) { }
|
||||
// AFU2SCY5X2BNVRXP6W47D369
|
||||
/**
|
||||
* Retrieve notes for a given request
|
||||
*
|
||||
* @param string $id The ID of the request for which notes should be retrieved
|
||||
* @return array|Note[] The notes for the request, or an empty array if the request was not found
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byRequestId(string $id): array
|
||||
{
|
||||
$req = Request::byId($id);
|
||||
return $req ? $req->notes : [];
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace MyPrayerJournal;
|
||||
|
||||
use BitBadger\PDODocument\{DocumentException, Find};
|
||||
use Exception;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
@ -30,4 +31,17 @@ class Request
|
||||
$this->id = (new Cuid2())->toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a request by its ID
|
||||
*
|
||||
* @param string $id The ID of the request
|
||||
* @return Request|false The request if it is found and belongs to the current user, false if not
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byId(string $id): Request|false
|
||||
{
|
||||
$req = Find::byId(Table::REQUEST, $id, self::class);
|
||||
return ($req && $req->userId == $_SESSION['user_id']) ? $req : false;
|
||||
}
|
||||
}
|
||||
|
12
src/lib/Table.php
Normal file
12
src/lib/Table.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace MyPrayerJournal;
|
||||
|
||||
/**
|
||||
* Constants for table names
|
||||
*/
|
||||
class Table
|
||||
{
|
||||
/** @var string The prayer request table used by myPrayerJournal */
|
||||
const REQUEST = 'request';
|
||||
}
|
99
src/public/docs.php
Normal file
99
src/public/docs.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
require '../start.php';
|
||||
|
||||
page_head('Documentation'); ?>
|
||||
<article class="container mt-3">
|
||||
<h2 class=mb-3>Documentation</h2>
|
||||
|
||||
<h3 class="mb-3 mt-4">About myPrayerJournal</h3>
|
||||
<p>Journaling has a long history; it helps people remember what happened, and the act of writing helps people think
|
||||
about what happened and process it. A prayer journal is not a new concept; it helps you keep track of the
|
||||
requests for which you’ve prayed, you can use it to pray over things repeatedly, and you can write the
|
||||
result when the answer comes <em>(or it was “no”)</em>.
|
||||
<p>myPrayerJournal was borne of out of a personal desire
|
||||
<a href=https://daniel.summershome.org target=_blank rel=noopener>Daniel</a> had to have something that would
|
||||
help him with his prayer life. When it’s time to pray, it’s not really time to use an app, so the
|
||||
design goal here is to keep it simple and unobtrusive. It will also help eliminate some of the downsides to a
|
||||
paper prayer journal, like not remembering whether you’ve prayed for a request, or running out of room to
|
||||
write another update on one.
|
||||
|
||||
<h3 class="mb-3 mt-4">Signing Up</h3>
|
||||
<p>myPrayerJournal uses login services using Google or Microsoft accounts. The only information the application
|
||||
stores in its database is your user ID token it receives from these services, so there are no permissions you
|
||||
should have to accept from these provider other than establishing that you can log on with that account. Because
|
||||
of this, you’ll want to pick the same one each time; the tokens between the two accounts are different,
|
||||
even if you use the same e-mail address to log on to both.
|
||||
|
||||
<h3 class="mb-3 mt-4">Your Prayer Journal</h3>
|
||||
<p>Your current requests will be presented in columns (usually three, but it could be more or less, depending on the
|
||||
size of your screen or device). Each request is in its own card, and the buttons at the top of each card apply
|
||||
to that request. The last line of each request also tells you how long it has been since anything has been done
|
||||
on that request. Any time you see something like “a few minutes ago,” you can hover over that to see
|
||||
the actual date/time the action was taken.
|
||||
|
||||
<h3 class="mb-3 mt-4">Adding a Request</h3>
|
||||
<p>To add a request, click the “Add a New Request” button at the top of your journal. Then, enter the
|
||||
text of the request as you see fit; there is no right or wrong way, and you are the only person who will see the
|
||||
text you enter. When you save the request, it will go to the bottom of the list of requests.
|
||||
|
||||
<h3 class="mb-3 mt-4">Setting Request Recurrence</h3>
|
||||
<p>When you add or update a request, you can choose whether requests go to the bottom of the journal once they have
|
||||
been marked “Prayed” or whether they will reappear after a delay. You can set recurrence in terms of
|
||||
hours, days, or weeks, but it cannot be longer than 365 days. If you decide you want a request to reappear
|
||||
sooner, you can skip the current delay; click the “Active” menu link, find the request in the list
|
||||
(likely near the bottom), and click the “Show Now” button.
|
||||
|
||||
<h3 class="mb-3 mt-4">Praying for Requests</h3>
|
||||
<p>The first button for each request has a checkmark icon; clicking this button will mark the request as
|
||||
“Prayed” and move it to the bottom of the list (or off, if you’ve set a recurrence period for
|
||||
the request). This allows you, if you’re praying through your requests, to start at the top left (with the
|
||||
request that it’s been the longest since you’ve prayed) and click the button as you pray; when the
|
||||
request move below or away, the next-least-recently-prayed request will take the top spot.
|
||||
|
||||
<h3 class="mb-3 mt-4">Editing Requests</h3>
|
||||
<p>The second button for each request has a pencil icon. This allows you to edit the text of the request, pretty
|
||||
much the same way you entered it; it starts with the current text, and you can add to it, modify it, or
|
||||
completely replace it. By default, updates will go in with an “Updated” status; you have the option
|
||||
to also mark this update as “Prayed” or “Answered”. Answered requests will drop off the
|
||||
journal list.
|
||||
|
||||
<h3 class="mb-3 mt-4">Adding Notes</h3>
|
||||
<p>The third button for each request has an icon that looks like a speech bubble with lines on it; this lets you
|
||||
record notes about the request. If there is something you want to record that doesn’t change the text of
|
||||
the request, this is the place to do it. For example, you may be praying for a long-term health issue, and that
|
||||
person tells you that their status is the same; or, you may want to record something God said to you while you
|
||||
were praying for that request."
|
||||
|
||||
<h3 class="mb-3 mt-4">Snoozing Requests</h3>
|
||||
<p>There may be a time when a request does not need to appear. The fourth button, with the clock icon, allows you to
|
||||
snooze requests until the day you specify. Additionally, if you have any snoozed requests, a
|
||||
“Snoozed” menu item will appear next to the “Journal” one; this page allows you to see
|
||||
what requests are snoozed, and return them to your journal by canceling the snooze.
|
||||
|
||||
<h3 class="mb-3 mt-4">Viewing a Request and Its History</h3>
|
||||
<p>myPrayerJournal tracks all actions related to a request; from the “Active” and “Answered”
|
||||
menu links (and “Snoozed”, if it’s showing), there is a “View Full Request”
|
||||
button. That page will show the current text of the request; how many times it has been marked as prayed; how
|
||||
long it has been an active request; and a log of all updates, prayers, and notes you have recorded. That log is
|
||||
listed from most recent to least recent; if you want to read it chronologically, press the “End” key
|
||||
on your keyboard and read it from the bottom up.
|
||||
<p>The “Active” link will show all requests that have not yet been marked answered, including snoozed
|
||||
and recurring requests. If requests are snoozed, or in a recurrence period off the journal, there will be a
|
||||
button where you can return the request to the list (either “Cancel Snooze” or “Show
|
||||
Now”). The “Answered” link shows all requests that have been marked answered. The
|
||||
“Snoozed” link only shows snoozed requests.
|
||||
|
||||
<h3 class="mb-3 mt-4">Final Notes</h3>
|
||||
<ul>
|
||||
<li>If you encounter errors, please
|
||||
<a href=https://git.bitbadger.solutions/bit-badger/myPrayerJournal/issues target=_blank rel=noopener>file an
|
||||
issue</a> (or <a href="mailto:daniel@bitbadger.solutions?subject=myPrayerJournal+Issue">e-mail Daniel</a> if
|
||||
you do not have an account on that server) with as much detail as possible. You can also provide
|
||||
suggestions, or browse the list of currently open issues.
|
||||
<li>Prayer requests and their history are securely backed up nightly along with other Bit Badger Solutions data.
|
||||
<li>Prayer changes things - most of all, the one doing the praying. I pray that this tool enables you to deepen
|
||||
and strengthen your prayer life.
|
||||
</ul>
|
||||
</article><?php
|
||||
page_foot();
|
@ -2,7 +2,7 @@
|
||||
|
||||
require '../start.php';
|
||||
|
||||
html_head('Welcome'); ?>
|
||||
page_head('Welcome'); ?>
|
||||
<article class="container mt-3">
|
||||
<p>
|
||||
<p>myPrayerJournal is a place where individuals can record their prayer requests, record that they prayed for them,
|
||||
@ -12,4 +12,4 @@ html_head('Welcome'); ?>
|
||||
On” link above, and log on with either a Microsoft or Google account. You can also learn more about the
|
||||
site at the “Docs” link, also above.
|
||||
</article><?php
|
||||
html_foot();
|
||||
page_foot();
|
||||
|
69
src/public/legal/privacy-policy.php
Normal file
69
src/public/legal/privacy-policy.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
require '../../start.php';
|
||||
|
||||
page_head('Privacy Policy'); ?>
|
||||
<article class="container mt-3">
|
||||
<h2 class=mb-2>Privacy Policy</h2>
|
||||
<h6 class="text-muted pb-3">as of May 21<sup>st</sup>, 2018</h6>
|
||||
<p>The nature of the service is one where privacy is a must. The items below will help you understand the data we
|
||||
collect, access, and store on your behalf as you use this service.
|
||||
<div class=card>
|
||||
<div class="list-group list-group-flush">
|
||||
<div class=list-group-item>
|
||||
<h3>Third Party Services</h3>
|
||||
<p class=card-text>
|
||||
myPrayerJournal utilizes a third-party authentication and identity provider. You should familiarize
|
||||
yourself with the privacy policy for
|
||||
<a href=https://auth0.com/privacy target=_blank rel=noopener>Auth0</a>, as well as your chosen
|
||||
provider
|
||||
(<a href=https://privacy.microsoft.com/en-us/privacystatement target=_blank rel=noopener>Microsoft</a>
|
||||
or <a href=https://policies.google.com/privacy target=_blank rel=noopener>Google</a>).
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>What We Collect</h3>
|
||||
<h4>Identifying Data</h4>
|
||||
<ul>
|
||||
<li>The only identifying data myPrayerJournal stores is the subscriber (“sub”) field
|
||||
from the token we receive from Auth0, once you have signed in through their hosted service. All
|
||||
information is associated with you via this field.
|
||||
<li>While you are signed in, within your browser, the service has access to your first and last
|
||||
names, along with a URL to the profile picture (provided by your selected identity provider).
|
||||
This information is not transmitted to the server, and is removed when “Log Off” is
|
||||
clicked.
|
||||
</ul>
|
||||
<h4>User Provided Data</h4>
|
||||
<ul class=mb-0>
|
||||
<li>myPrayerJournal stores the information you provide, including the text of prayer requests,
|
||||
updates, and notes; and the date/time when certain actions are taken.
|
||||
</ul>
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>How Your Data Is Accessed / Secured</h3>
|
||||
<ul class=mb-0>
|
||||
<li>Your provided data is returned to you, as required, to display your journal or your answered
|
||||
requests. On the server, it is stored in a controlled-access database.
|
||||
<li>Your data is backed up, along with other Bit Badger Solutions hosted systems, in a rolling
|
||||
manner; backups are preserved for the prior 7 days, and backups from the 1<sup>st</sup> and
|
||||
15<sup>th</sup> are preserved for 3 months. These backups are stored in a private cloud data
|
||||
repository.
|
||||
<li>The data collected and stored is the absolute minimum necessary for the functionality of the
|
||||
service. There are no plans to “monetize” this service, and storing the minimum
|
||||
amount of information means that the data we have is not interesting to purchasers (or those who
|
||||
may have more nefarious purposes).
|
||||
<li>Access to servers and backups is strictly controlled and monitored for unauthorized access
|
||||
attempts.
|
||||
</ul>
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>Removing Your Data</h3>
|
||||
<p class=card-text>
|
||||
At any time, you may choose to discontinue using this service. Both Microsoft and Google provide
|
||||
ways to revoke access from this application. However, if you want your data removed from the
|
||||
database, please contact daniel at bitbadger.solutions (via e-mail, replacing at with @) prior to
|
||||
doing so, to ensure we can determine which subscriber ID belongs to you.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article><?php
|
||||
page_foot();
|
55
src/public/legal/terms-of-service.php
Normal file
55
src/public/legal/terms-of-service.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
require '../../start.php';
|
||||
|
||||
page_head('Terms of Service'); ?>
|
||||
<article class="container mt-3">
|
||||
<h2 class=mb-2>Terms of Service</h2>
|
||||
<h6 class="text-muted pb-3">as of May 21<sup>st</sup>, 2018</h6>
|
||||
<div class=card>
|
||||
<div class="list-group list-group-flush">
|
||||
<div class=list-group-item>
|
||||
<h3>1. Acceptance of Terms</h3>
|
||||
<p class=card-text>
|
||||
By accessing this web site, you are agreeing to be bound by these Terms and Conditions, and that you
|
||||
are responsible to ensure that your use of this site complies with all applicable laws. Your
|
||||
continued use of this site implies your acceptance of these terms.
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>2. Description of Service and Registration</h3>
|
||||
<p class=card-text>
|
||||
myPrayerJournal is a service that allows individuals to enter and amend their prayer requests. It
|
||||
requires no registration by itself, but access is granted based on a successful login with an
|
||||
external identity provider. See <?php page_link('/legal/privacy-policy', 'our privacy policy'); ?>
|
||||
for details on how that information is accessed and stored.
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>3. Third Party Services</h3>
|
||||
<p class=card-text>
|
||||
This service utilizes a third-party service provider for identity management. Review the terms of
|
||||
service for <a href=https://auth0.com/terms target=_blank rel=noopener>Auth0</a>, as well as those
|
||||
for the selected authorization provider
|
||||
(<a href=https://www.microsoft.com/en-us/servicesagreement target=_blank rel=noopener>Microsoft</a>
|
||||
or <a href=https://policies.google.com/terms target=_blank rel=noopener>Google</a>).
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>4. Liability</h3>
|
||||
<p class=card-text>
|
||||
This service is provided “as is”, and no warranty (express or implied) exists. The
|
||||
service and its developers may not be held liable for any damages that may arise through the use of
|
||||
this service.
|
||||
</div>
|
||||
<div class=list-group-item>
|
||||
<h3>5. Updates to Terms</h3>
|
||||
<p class=card-text>
|
||||
These terms and conditions may be updated at any time, and this service does not have the capability
|
||||
to notify users when these change. The date at the top of the page will be updated when any of the
|
||||
text of these terms is updated."
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class=pt-3>
|
||||
You may also wish to review our <?php page_link('/legal/privacy-policy', 'privacy policy'); ?> to learn how we
|
||||
handle your data.
|
||||
</article><?php
|
||||
page_foot();
|
7
src/public/user/log-off.php
Normal file
7
src/public/user/log-off.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use MyPrayerJournal\Auth;
|
||||
|
||||
require '../../start.php';
|
||||
|
||||
Auth::logOff();
|
7
src/public/user/log-on.php
Normal file
7
src/public/user/log-on.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use MyPrayerJournal\Auth;
|
||||
|
||||
require '../../start.php';
|
||||
|
||||
Auth::logOn();
|
11
src/public/user/log-on/success.php
Normal file
11
src/public/user/log-on/success.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use MyPrayerJournal\Auth;
|
||||
|
||||
require '../../../start.php';
|
||||
|
||||
Auth::client()->exchange($_ENV['AUTH0_BASE_URL'] . '/user/log-on/success');
|
||||
|
||||
// TODO: get the possible redirect URL
|
||||
header('Location: /');
|
||||
exit();
|
@ -1,55 +1,53 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
const MPJ_VERSION = '4.0.0';
|
||||
use Dotenv\Dotenv;
|
||||
use MyPrayerJournal\{Auth, Layout};
|
||||
|
||||
function html_head(string $title): void
|
||||
{ ?>
|
||||
<!DOCTYPE html>
|
||||
<head lang=en>
|
||||
<meta name=viewport content="width=device-width, initial-scale=1">
|
||||
<meta name=description content="Online prayer journal - free w/Google or Microsoft account">
|
||||
<title><?=$title?> « myPrayerJournal</title>
|
||||
<link href=https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css rel=stylesheet
|
||||
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin=anonymous>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel=stylesheet>
|
||||
<link href=/style/style.css rel=stylesheet>
|
||||
</head><?php
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
/** The version of this application */
|
||||
const MPJ_VERSION = '4.0.0-alpha1';
|
||||
|
||||
(Dotenv::createImmutable(__DIR__))->load();
|
||||
session_start();
|
||||
|
||||
$auth0_session = Auth::client()->getCredentials();
|
||||
if (!is_null($auth0_session)) {
|
||||
$_SESSION['user_id'] = $auth0_session->user['sub'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an htmx request?
|
||||
*
|
||||
* @return bool True if this is an htmx request, false if not
|
||||
*/
|
||||
function is_htmx(): bool
|
||||
{
|
||||
return key_exists('HTTP_HX_REQUEST', $_SERVER) && !key_exists('HTTP_HX_HISTORY_RESTORE_REQUEST', $_SERVER);
|
||||
}
|
||||
|
||||
function page_link(string $href, string $text, array $attrs = []): void
|
||||
{ ?>
|
||||
<a href="<?=$href?>" hx-get="<?=$href?>" hx-target="#top" hx-swap=innerHTML hx-push-url=true<?php
|
||||
foreach ($attrs as $key => $value) echo " $key=\"" . htmlspecialchars($value) . "\""; ?>><?=$text?></a><?php
|
||||
{
|
||||
echo '<a href="' . $href . '" hx-get="' . $href . '" hx-target="#top" hx-swap=innerHTML hx-push-url=true';
|
||||
foreach ($attrs as $key => $value) echo " $key=\"" . htmlspecialchars($value) . "\"";
|
||||
echo ">$text</a>";
|
||||
}
|
||||
|
||||
function html_foot(): void
|
||||
function page_head(string $title): void
|
||||
{
|
||||
$version = MPJ_VERSION;
|
||||
while (!str_ends_with($version, '.0')) $version = substr($version, 0, strlen($version) - 2); ?>
|
||||
<footer class=container-fluid>
|
||||
<p class="text-muted text-end">
|
||||
myPrayerJournal <?=$version?><br>
|
||||
<em>
|
||||
<small><?php
|
||||
page_link('/legal/privacy-policy', 'Privacy Policy');
|
||||
echo ' • ';
|
||||
page_link('/legal/terms-of-service', 'Terms of Service');
|
||||
echo ' • '; ?>
|
||||
<a href=https://git.bitbadger.solutions/bit-badger/myPrayerJournal target=_blank
|
||||
rel=noopener>Developed</a> and hosted by
|
||||
<a href=https://bitbadger.solutions target=_blank rel=noopener>Bit Badger Solutions</a>
|
||||
</small>
|
||||
</em>
|
||||
Htmx.Script.minified
|
||||
<script>if (!htmx) document.write('<script src=\"/script/htmx.min.js\"><\/script>')</script>
|
||||
<script async src=https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js
|
||||
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
||||
crossorigin=anonymous></script>
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
if (!bootstrap) document.write('<script src=\"/script/bootstrap.bundle.min.js\"><\/script>')
|
||||
}, 2000)
|
||||
</script>
|
||||
<script src=/script/mpj.js></script>
|
||||
</footer><?php
|
||||
}
|
||||
Layout::htmlHead($title);
|
||||
echo '<body>';
|
||||
if (!is_htmx()) echo '<section id=top aria-label="Top navigation">';
|
||||
Layout::navBar();
|
||||
echo '<main role=main>';
|
||||
}
|
||||
|
||||
function page_foot(): void
|
||||
{
|
||||
echo '</main>';
|
||||
if (!is_htmx()) {
|
||||
echo '</section>';
|
||||
Layout::htmlFoot();
|
||||
}
|
||||
echo '</body></html>';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user