This commit is contained in:
count-null 2025-03-06 11:54:23 -05:00
parent 35971fd696
commit 1ed14b5549
7 changed files with 118 additions and 162 deletions

View file

@ -90,7 +90,7 @@ class account
$user_id = $_SESSION['user_id'];
$token = magic_links::add($email, $user_id);
users::updateReplaceEmailTokenById($user_id, $token);
header('Location: /account');
header('Location: /account/verify');
exit;
}
}
@ -98,30 +98,6 @@ class account
public static function verify($defaults)
{
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$code = $_POST['code'];
$link = magic_links::validateCode($code);
if ($link) {
$user = $link['user_id'] ? users::getById($link['user_id']) : users::getByEmail($link['email']);
if ($user) {
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user['id'];
if (! $user['verified']) {
users::verify($link['email']);
}
header('Location: /account');
exit;
} else {
$_SESSION['user_email'] = $link['email'];
header('Location: /account/signup');
exit;
}
} else {
$_SESSION['error'] = "Invalid or expired verification code.";
header('Location: /account/verify');
exit;
}
}
echo $GLOBALS['twig']->render('lib/pages/index.twig', array_merge($defaults, [
'child_template' => 'account/verify.twig',
'page_title' => $_ENV['APP_NAME'],
@ -303,9 +279,8 @@ class account
}
$existingUser = users::getByEmail($email);
if ($existingUser) {
$_SESSION['error'] = 'Email already exists. Please choose a different email or log in.';
$_SESSION['last_post'] = $_POST;
header('Location: /account/signup');
$token = magic_links::add($email, $user_id);
header("Location: /account/verify");
exit;
}
$useShipping = $_POST['use_shipping'] ?? false;
@ -368,7 +343,8 @@ class account
);
$_SESSION['user_id'] = $user_id;
if (! $verified) {
header("Location: /magic-link?email=$email&signup=1");
$token = magic_links::add($email, $user_id);
header("Location: /account/verify");
exit;
}
header('Location: /account');

View file

@ -106,32 +106,22 @@ class admin
$currency = $_POST['currency'];
$user_identifier = $_POST['user_identifier'] ?? null;
if (! $amount || ! $user_identifier) {
$_SESSION['error'] = ! $amount ? "Please enter an amount for the transaction." : "Please enter a user email or id for the transaction.";
$_SESSION['last_post'] = $_POST;
$_SESSION['error'] = ! $amount ? "Please enter an amount for the transaction." : "Please enter a user email or id for the transaction.";
} else {
if (strpos($user_identifier, '@') !== false && strpos($user_identifier, '.') !== false) {
$user = users::getByEmail($user_identifier);
} elseif (is_numeric($user_identifier)) {
$user = users::getById((int) $user_identifier);
} else {
$_SESSION['error'] = "Invalid user identifier. Please enter a valid email or user ID.";
$_SESSION['last_post'] = $_POST;
$_SESSION['error'] = "Invalid user identifier. Please enter a valid email or user ID.";
}
if (! $user) {
$_SESSION['error'] = "User not found. Please enter a valid email or user ID.";
$_SESSION['last_post'] = $_POST;
$_SESSION['error'] = "User not found. Please enter a valid email or user ID.";
} else {
if ($_POST['confirm']) {
// create the transaction
$txid = transactions::add($user['id'], $amount > 0 ? 'CREDIT' : 'REVOKE', $currency == 'cents' ? $amount : 0, $currency == 'sats' ? $amount : 0);
header('Location: /transaction/' . $txid);
exit;
} else {
$_SESSION['last_post'] = $_POST;
$_SESSION['last_post']['confirm'] = true;
$_SESSION['last_post']['email'] = $user['email'];
$_SESSION['last_post']['id'] = $user['id'];
}
// create the transaction
$txid = transactions::add($user['id'], $amount > 0 ? 'CREDIT' : 'REVOKE', $currency == 'cents' ? $amount : 0, $currency == 'sats' ? $amount : 0);
header('Location: /transaction/' . $txid);
exit;
}
}
}
@ -153,6 +143,7 @@ class admin
],
],
]));
exit;
}
public static function emails($defaults)

View file

@ -9,39 +9,81 @@ class magic_link
{
public static function index()
{
$token = $_GET['token'] ?? null;
if (! $token) {
$_SESSION['error'] = "Invalid or expired link.";
header('Location: /account/login');
exit;
} else {
$link = magic_links::validateToken(token: $token);
if (! $link) {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { // using a 6-digit code
$code = $_POST['code'] ?? null;
if (! $code) {
$_SESSION['error'] = "Invalid or expired code.";
header('Location: /account/verify');
exit;
} else {
$link = magic_links::validateCode($code);
if ($link) { // the code is valid
$user = $link['user_id'] ? users::getById($link['user_id']) : users::getByEmail($link['email']);
if ($user) { // this email is registered or associated with a user
$user_replacing = users::getByReplaceEmailToken($link['token']);
if ($user_replacing) { // user is replacing their email
users::updateEmailById($user_replacing['id'], $link['email']);
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user_replacing['id'];
if (! $user_replacing['verified']) {
users::verify($link['email']);
}
header('Location: /account');
exit;
} else { // user is logging in
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user['id'];
if (! $user['verified']) {
users::verify($link['email']);
}
header('Location: /account');
exit;
}
} else { // new user signup
$_SESSION['user_email'] = $link['email'];
header('Location: /account/signup');
exit;
}
} else { // the code is not valid
$_SESSION['error'] = "Invalid or expired verification code.";
header('Location: /account/verify');
exit;
}
}
} else { // using a link with a token
$token = $_GET['token'] ?? null;
if (! $token) {
$_SESSION['error'] = "Invalid or expired link.";
header('Location: /account/login');
exit;
}
$user = $link['user_id'] ? users::getById($link['user_id']) : users::getByEmail($link['email']);
if ($user) { // user with this email exists, log them in
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user['id'];
if (! $user['verified']) {
users::verify($link['email']);
}
header('Location: /account');
exit;
} else { // no users with this email
$user_replacing_email = users::getByReplaceEmailToken($token);
if ($user_replacing_email) { // user is replacing their email
$user_id = $user_replacing_email['id'];
users::updateEmailById($user_id, $link['email']);
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user_id;
if (! $user['verified']) {
users::verify($link['email']);
}
header('Location: /account');
} else {
$link = magic_links::validateToken(token: $token);
if (! $link) {
$_SESSION['error'] = "Invalid or expired link.";
header('Location: /account/login');
exit;
}
$user = $link['user_id'] ? users::getById($link['user_id']) : users::getByEmail($link['email']);
if ($user) { // this email is registered or is associated with a user
$user_replacing = users::getByReplaceEmailToken($token);
if ($user_replacing) { // user is replacing their email
users::updateEmailById($user_replacing['id'], $link['email']);
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user_replacing['id'];
if (! $user_replacing['verified']) {
users::verify($link['email']);
}
header('Location: /account');
exit;
} else { // user is logging in
$_SESSION['user_email'] = $link['email'];
$_SESSION['user_id'] = $user['id'];
if (! $user['verified']) {
users::verify($link['email']);
}
header('Location: /account');
exit;
}
} else { // new user signup
$_SESSION['user_email'] = $link['email'];
header('Location: /account/signup');

View file

@ -72,12 +72,11 @@ class users
public static function updateEmailById($user_id, $email)
{
$query = "UPDATE users SET email = :email WHERE id = :user_id";
$query = "UPDATE users SET email = :email, replace_email_token = NULL WHERE id = :user_id";
$stmt = app::$db->prepare($query);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':user_id', $user_id);
$stmt->execute();
users::updateReplaceEmailTokenById($user_id, null);
}
public static function getByReplaceEmailToken($token)

View file

@ -11,7 +11,7 @@
</div>
{% include 'lib/alert.twig' %}
<form action="/account/verify" method="post" class="flex flex-col items-center gap-4">
<form action="/magic-link" method="post" class="flex flex-col items-center gap-4">
{% include 'lib/inputs/text.twig' with {
type: 'tel',
name: 'code',

View file

@ -1,67 +1,32 @@
<section class="flex flex-col gap-4">
{% include 'lib/alert.twig' %}
<form action="/admin/transactions/add" method="post" class="flex flex-col gap-4">
{% if session.last_post.confirm %}
Confirm
<input type="hidden" name="confirm" id="confirm" value="{{ session.last_post.confirm }}">
{% endif %}
{% if session.last_post.amount is defined %}
{{ session.last_post.amount }}
{{ session.last_post.currency }}
<input
type="hidden" name="amount" id="amount" value="{{ session.last_post.amount }}" />
{% else %}
{% include 'lib/inputs/number.twig' with {
id: 'amount',
name: 'amount',
label: 'Amount',
placeholder: 'Enter the amount',
value: session.last_post.amount,
required: true
} %}
{% endif %}
{% if session.last_post.currency %}
<input
type="hidden" name="currency" id="currency" value="{{ session.last_post.currency }}" />
{% else %}
{% include 'lib/inputs/select.twig' with {
id: 'currency',
name: 'currency',
label: 'Currency',
value: session.last_post.currency,
options: [
{ 'value': 'sats', 'text': 'Sats' },
{ 'value': 'cents', 'text': 'Cents' }
],
required: true
} %}
{% endif %}
{% if session.last_post.user_identifier is defined %}
{% if session.last_post.email is defined %}
{{ session.last_post.id }}
{{ session.last_post.email }}
{% endif %}
<input
type="hidden" name="user_identifier" id="user_identifier" value="{{ session.last_post.user_identifier }}" />
{% else %}
{% include 'lib/inputs/text.twig' with {
type: 'text',
name: 'user_identifier',
label: 'User Identifier',
placeholder: 'Enter email or user index',
value: session.last_post.user_identifier
} %}
{% endif %}
{% include 'lib/buttons/submit.twig' with {
label: 'Submit',
} %}
</form>
{% if session.last_post %}
<a href="/admin/transactions/reset">
{% include 'lib/buttons/default.twig' with {
label: 'Cancel'
} %}
</a>
{% endif %}
</section>
{% include 'lib/inputs/number.twig' with {
id: 'amount',
name: 'amount',
label: 'Amount',
placeholder: 'Enter the amount',
required: true
} %}
{% include 'lib/inputs/select.twig' with {
id: 'currency',
name: 'currency',
label: 'Currency',
options: [
{ 'value': 'sats', 'text': 'Sats' },
{ 'value': 'cents', 'text': 'Cents' }
],
required: true
} %}
{% include 'lib/inputs/text.twig' with {
type: 'text',
name: 'user_identifier',
label: 'User Identifier',
placeholder: 'Enter email or user index',
} %}
{% include 'lib/buttons/submit.twig' with {
label: 'Submit',
} %}
</form>
</section>

View file

@ -1,27 +1,10 @@
<section class="flex flex-col gap-4">
{% include 'lib/alert.twig' %}
<form action="/admin/transactions/add" method="post" class="flex flex-col gap-4">
{% include 'lib/inputs/number.twig' with {
id: 'amount',
name: 'amount',
label: 'Amount',
required: true
} %}
{% include 'lib/inputs/select.twig' with {
id: 'currency',
name: 'currency',
label: 'Currency',
options: [
{ value: 'cents', text: 'Cents' },
{ value: 'sats', text: 'Sats' }
],
required: true
} %}
<a href="/admin/transactions/add">
{% include 'lib/buttons/submit.twig' with {
label: 'Submit',
label: 'Create a New Transaction',
} %}
</form>
</a>
<h3 class="text-2xl font-semibold">
Liabilities
</h3>