moved password recovery updates to beta

beta
Ro 4 years ago
parent 1c7fcd6664
commit 913dd3a57f

@ -18,6 +18,7 @@ include "../brain/utility/DocTools.inc.php";
include "../brain/utility/Sorting.inc.php";
include "../brain/utility/Setup.inc.php";
include "../brain/utility/Maintenance.inc.php";
include "../brain/utility/Mailer.inc.php";
class App
{

@ -60,4 +60,14 @@ class AuthAPI
];
return $result;
}
public static function requestSecret($body)
{
$result = Auth::findSecret($body);
return $result;
}
public static function resetPassword($body)
{
$result = Auth::makeNewPassword($body);
return $result;
}
}

@ -0,0 +1,26 @@
<?php
class MailerAPI
{
public function __construct()
{
}
public static function handleMail($request, $body, $response)
{
//if testing, verify session is active
if ($body["mail_task"] == "TESTING") {
if (Session::active()) {
$result = Mailer::sendmail($body);
} else {
$result = [
"message" => "You need to be logged in for this, champ.",
"type" => "MAILER_ERROR",
];
}
} else {
}
return $result;
}
}

@ -7,6 +7,7 @@ include "../brain/api/v1/ImagesAPI.inc.php";
include "../brain/api/v1/PagesAPI.inc.php";
include "../brain/api/v1/SettingsAPI.inc.php";
include "../brain/api/v1/InitAPI.inc.php";
include "../brain/api/v1/MailerAPI.inc.php";
class APIControl
{
@ -82,15 +83,15 @@ class APIControl
}
switch (isset($args["third"]) ? $args["third"] : "none") {
case "restore":
case "init":
case "restore": //move to 'api/auth'
case "init": //move to 'api/auth'
$task = $args["third"];
$result = InitApi::handleInitTasks(
$task,
$task == "init" ? $body : $request
);
break;
case "backup":
case "backup": //move to 'api/auth'
$token = $request->getHeader("fipamo-access-token");
//Verify token for admin tasks
if (Session::verifyToken($token[0])) {
@ -102,12 +103,18 @@ class APIControl
];
}
break;
case "login":
case "login": //move to 'api/auth'
$result = AuthAPI::login($body);
break;
case "logout":
case "logout": //move to 'api/auth'
$result = AuthAPI::logout($body);
break;
case "get-secret": //move to 'api/auth'
$result = AuthAPI::requestSecret($body);
break;
case "reset-password": //move to 'api/auth'
$result = AuthAPI::resetPassword($body);
break;
case "page":
$token = $request->getHeader("fipamo-access-token");
//Verify token for admin tasks
@ -137,6 +144,9 @@ class APIControl
];
}
break;
case "mailer":
$result = MailerAPI::handleMail($request, $body, $response);
break;
default:
$result = [
"message" => "Oh, nothing to do. That's unfortunate",

@ -38,6 +38,7 @@ class DashControl
"currentTheme" => $settings["global"]["theme"],
"themes" => $themes,
"mailOption" => $settings["email"]["active"],
"mailConfig" => $settings["email"],
"status" => Session::active(),
];
} else {
@ -116,9 +117,14 @@ class DashControl
header("Location: /dashboard");
die();
break;
case "reset-password":
$template = "dash/reset-password.twig";
$pageOptions = [
"title" => "Reset Password",
];
break;
default:
//$secret = ;
$template = "dash/start.twig";
if (Session::active()) {
$pageOptions = [

@ -5,70 +5,146 @@ use ReallySimpleJWT\Token;
class Auth
{
public function __construct()
{
}
public function __construct()
{
}
public static function sessionStatus()
{
if (isset($_SESSION["member"])) {
return true;
} else {
return false;
}
//return $this->secret;
public static function sessionStatus()
{
if (isset($_SESSION["member"])) {
return true;
} else {
return false;
}
//return $this->secret;
}
public static function status()
{
$result = "";
if (Session::active()) {
$result = true;
} else {
$result = false;
}
return $result;
public static function status()
{
$result = "";
if (Session::active()) {
$result = true;
} else {
$result = false;
}
return $result;
}
public static function login($who)
{
//grab member list
$folks = (new Settings())->getFolks();
$found = find($folks, ["handle" => $who["handle"]]);
public static function login($who)
{
//grab member list
$folks = (new Settings())->getFolks();
$found = find($folks, ["handle" => $who["handle"]]);
if ($found) {
//name is found, verify password
if (password_verify($who["password"], $found["password"])) {
$member = [
"handle" => $found["handle"],
"email" => $found["email"],
"role" => $found["role"],
"avatar" => $found["avi"],
];
if ($found) {
//name is found, verify password
if (password_verify($who["password"], $found["password"])) {
$member = [
"handle" => $found["handle"],
"email" => $found["email"],
"role" => $found["role"],
"avatar" => $found["avi"],
];
$token = Token::create(
$found["id"],
$found["secret"],
time() + 3600,
"localhost"
); //expires in an hour
Session::start();
Session::set("member", $member);
Session::set("token", $token);
$token = Token::create(
$found["id"],
$found["secret"],
time() + 3600,
"localhost"
); //expires in an hour
Session::start();
Session::set("member", $member);
Session::set("token", $token);
$result = "good_login";
} else {
$result = "bad_pass";
}
$result = "good_login";
} else {
$result = "bad_pass";
}
} else {
//if name is not found
$result = "no_name";
}
return $result;
}
public static function findSecret($data)
{
$result = [];
$folks = (new Settings())->getFolks();
if (
!empty($data["email"]) &&
filter_var($data["email"], FILTER_VALIDATE_EMAIL)
) {
$found = find($folks, ["email" => $data["email"]]);
if ($found) {
//if email is cool, check mail relay status
//if set up, send secret there, if not just return it
$config = new Settings();
$settings = $config->getSettings();
$email = $settings["email"]["active"];
if ($email != "option-none") {
$data["mail_task"] = "SEND_SECRET";
$data["secret"] = $found["secret"];
$result = Mailer::sendmail($data);
} else {
//if name is not found
$result = "no_name";
$result = [
"message" => "Valid email, but no email set up!",
"type" => "secretFound",
"secret" => $found["secret"],
];
}
return $result;
} else {
$result = [
"message" => "No valid email, no goodies, pleighboi",
"type" => "secretNotFound",
];
}
} else {
$result = [
"message" => "Aye, this address is not right, slick.",
"type" => "secretNotFound",
];
}
public static function logout()
{
Session::kill();
return $result;
}
public static function makeNewPassword($data)
{
//check if passwordsmatch
if ($data["newPass"] == $data["newPassConfirm"]) {
//verify secret
$folks = (new Settings())->getFolks();
$found = find($folks, ["secret" => $data["secret"]]);
if ($found) {
//create new pass and secret key, then update file
$hash = password_hash($data["newPass"], PASSWORD_DEFAULT);
$freshSecret = StringTools::randomString(12);
Member::updateData("password", $hash, $data["secret"]);
Member::updateData("secret", $freshSecret, $data["secret"]);
$result = [
"message" => "Password Updated. Very nice!",
"type" => "passCreated",
];
} else {
$result = [
"message" => "Secret key is invalid. Try to retrieve it again",
"type" => "passNotCreated",
];
}
} else {
$result = [
"message" => "Passwords don't match. Try it again.",
"type" => "passNotCreated",
];
}
return $result;
}
public static function logout()
{
Session::kill();
}
}

@ -7,11 +7,15 @@ class Member
{
}
public static function updateData(string $key, string $data)
public static function updateData(string $key, string $data, $secret = null)
{
$folks = (new Settings())->getFolks();
$member = Session::get("member");
$found = find($folks, ["handle" => $member["handle"]]);
if (isset($secret)) {
$found = find($folks, ["secret" => $secret]);
} else {
$member = Session::get("member");
$found = find($folks, ["handle" => $member["handle"]]);
}
$found[$key] = $data;
//record time updated
$updated = new \Moment\Moment();
@ -22,12 +26,14 @@ class Member
DocTools::writeSettings("../config/folks.json", $newFolks);
//update member data in session
$member = [
"handle" => $found["handle"],
"email" => $found["email"],
"role" => $found["role"],
"avatar" => $found["avi"],
];
Session::set("member", $member);
if (!isset($secret)) {
$member = [
"handle" => $found["handle"],
"email" => $found["email"],
"role" => $found["role"],
"avatar" => $found["avi"],
];
Session::set("member", $member);
}
}
}

@ -0,0 +1,94 @@
<?php
use Slim\Views\Twig;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
class Mailer
{
public static function sendMail($body)
{
$config = new Settings();
$settings = $config->getSettings();
$mailConfig = $settings["email"];
$mail = new PHPMailer();
switch ($body["mail_task"]) {
case "TESTING":
$html =
"<h1>Hi! It's Fipamo!</h1><br>" .
"<strong>It's just a test</strong><br>" .
$body["content"];
$member = Session::get("member");
$mail->addAddress($member["email"], ""); //pull email address from current user
$mail->Subject = "A test email";
break;
case "SEND_SECRET":
$html =
"<h1>Hi! It's Fipamo!</h1><br>" .
"<strong>This is your secret key.</strong><br><br>" .
"<h3>" .
$body["secret"] .
"</h3>" .
"<br> Use this key to reset your password.";
$mail->addAddress($body["email"], ""); //pull email address from current user
$mail->Subject = "Shhhh! It's a secret!";
break;
default:
return $result = [
"type" => "noMailService",
"message" => "Mail task is undefined. What are you doing??",
];
break;
}
//set values based on current active protocol
switch ($mailConfig["active"]) {
case "option-smtp":
$mail->setFrom($mailConfig["smtp"]["email"], "System Email");
$mail->Host = "playvicio.us";
$mail->Username = $mailConfig["smtp"]["email"];
$mail->Password = $mailConfig["smtp"]["password"];
break;
case "option-mg":
$mail->setFrom($mailConfig["mailgun"]["domain"], "No Reply");
$mail->Host = "smtp.mailgun.org";
$mail->Username = $mailConfig["mailgun"]["domain"];
$mail->Password = $mailConfig["mailgun"]["key"];
break;
default:
//no mail service
return $result = [
"type" => "noMailService",
"message" => "Mail is not configured. Handle that.",
];
break;
}
$mail->Body = $html;
$mail->IsHTML(true);
$mail->isSMTP();
$mail->SMTPAuth = true;
$mail->SMTPSecure = "ssl";
$mail->Port = 465;
// Uncomment for debug info
//$mail->SMTPDebug = 4;
/* Finally send the mail. */
try {
$mail->send();
$result = ["type" => "mailSent", "message" => "Message Away!"];
} catch (Exception $e) {
//echo $e->errorMessage();
$result = [
"type" => "mailNotSent",
"message" => "Message Not Away!",
"error" => $e->errorMessage(),
];
}
return $result;
}
}

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<title>
{{title}}
</title>
<style type="text/css">
/* reset */
#outlook a {
padding: 0;
}
/* Force Outlook to provide a "view in browser" menu link. */
.ExternalClass {
width: 100%;
}
/* Force Hotmail to display emails at full width */
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
/* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
p {
margin: 0;
padding: 0;
font-size: 0px;
line-height: 0px;
}
/* squash Exact Target injected paragraphs */
table td {
border-collapse: collapse;
}
/* Outlook 07, 10 padding issue fix */
table {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
/* remove spacing around Outlook 07, 10 tables */
/* bring inline */
img {
display: block;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
a img {
border: none;
}
a {
text-decoration: none;
color: #000001;
}
/* text link */
a.phone {
text-decoration: none;
color: #000001 !important;
pointer-events: auto;
cursor: default;
}
/* phone link, use as wrapper on phone numbers */
span {
font-size: 13px;
line-height: 17px;
font-family: monospace;
color: #000001;
}
</style>
</head>
<body>
<table cellpadding='0' cellspacing='0' border='0' style="margin:0; padding:0; width:100%; line-height: 100% !important;">
<tr>
<td valign='top'>
{# edge wrapper #}
<table cellpadding='0' cellspacing='0' border='0' align='center' width='600' style='background: #374857;'>
<tr>
<td valign='top' style='vertical-align: top;')>
{# info table start #}
<table cellpadding='0' cellspacing='0' border='0' align='center' style='width:100%'>
<tr>
<td valign='top' style='vertical-align: top;text-align: center; padding: 10px'>
<span style='font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#f5ab35; font-size:20px; font-weight: bold;'>
{{ header }}
</span>
</td>
</tr>
<tr>
<td valign='top' style='vertical-align: top; background: #161d23; padding:10px;'>
<span style='font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#cecece; font-size:16px;'>
{{ content }}
</span>
</td>
</tr>
<tr>
<td valign='top' style='vertical-align: top; padding: 10px;'>
<span style='font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#b2cce5; font-size:12px;'>
{{ footer }}
</span>
</td>
</tr>
</table>
{# info table end #}
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

@ -1,11 +1,12 @@
<div id="dash-login">
<div id="dash-form" class="dash-form">
<form id="login" class='login' , name="login" action="/@/dashboard/login" method="POST">
<form id="login" class='login' name="login" action="/@/dashboard/login" method="POST">
<input type="text" name="handle" class="form-control" placeholder="Handle" required ">
<input type="password" name="password" class="form-control" placeholder="Password" required">
<button id="login-btn" , class='login-btn' , type='submit'>
<button id="login-btn" class='login-btn' type='submit'>
Let's see some ID
</button>
</button><br /><br />
<a href="/dashboard/reset-password"> Forgot Password?</a>
</form>
</div>
</div>

@ -1,31 +1,31 @@
{% if mailOption == "option-smtp" %}
<div id="mail-smtp" data-enabled='true'>
<input type='text' name='smtp-domain' id='smtp-domain' placeholder='domain'value="settings.email.smtp.domain"/>
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="settings.email.smtp.email" />
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="settings.email.smtp.password"/>
<input type='text' name='smtp-domain' id='smtp-domain' placeholder='domain'value="{{mailConfig['smtp']['domain']}}"/>
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="{{mailConfig['smtp']['email']}}" />
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="{{mailConfig['smtp']['password']}}"/>
</div>
<div id="mail-mg" data-enabled='false'>
<input type='text' name='mg-domain' id='mg-domain' placeholder='domain' value="settings.email.mailgun.domain" />
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="settings.email.mailgun.key "/>
<input type='text' name='mg-domain' id='mg-domain' placeholder='domain' value="{{mailConfig['mailgun']['domain']}}" />
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="{{mailConfig['mailgun']['key']}}"/>
</div>
{% elseif(mailOption == 'option-mg') %}
<div id="mail-smtp" data-enabled='false'>
<input type='text' name='smtp-domain' id='smtp-domain' placeholder='domain'value="settings.email.smtp.domain"/>
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="settings.email.smtp.email" />
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="settings.email.smtp.password"/>
<input type='text' name='smtp-domain' id='smtp-domain' placeholder='domain'value="{{mailConfig['smtp']['domain']}}"/>
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="{{mailConfig['smtp']['email']}}" />
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="{{mailConfig['smtp']['password']}}"/>
</div>
<div id="mail-mg" data-enabled='true'>
<input type='text' name='mg-domain' id='mg-domain' placeholder='domain' value="settings.email.mailgun.domain" />
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="settings.email.mailgun.key "/>
<input type='text' name='mg-domain' id='mg-domain' placeholder='domain' value="{{mailConfig['mailgun']['domain']}}" />
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="{{mailConfig['mailgun']['key']}}"/>
</div>
{% else %}
<div id="mail-smtp" data-enabled='false'>
<input type='text' name='smtp-domain' id='smtp-domain' placeholder='domain'value="settings.email.smtp.domain"/>
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="settings.email.smtp.email" />
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="settings.email.smtp.password"/>
<input type='text' name='smtp-domain' id='smtp-domain' placeholder='domain'value="{{mailConfig['smtp']['domain']}}"/>
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="{{mailConfig['smtp']['email']}}" />
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="{{mailConfig['smtp']['password']}}"/>
</div>
<div id="mail-mg" data-enabled='false'>
<input type='text' name='mg-domain' id='mg-domain' placeholder='domain' value="settings.email.mailgun.domain" />
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="settings.email.mailgun.key "/>
<input type='text' name='mg-domain' id='mg-domain' placeholder='domain' value="{{mailConfig['mailgun']['domain']}}" />
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="{{mailConfig['mailgun']['key']}}"/>
</div>
{% endif %}

@ -0,0 +1,40 @@
{% extends "dash/_frame.twig" %}
{% block title %}
{{ title }}
{% endblock %}
{% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfdfdf">
{% endblock %}
{% block mainContent %}
<div id="dash-index">
<div id="dash-index-wrapper">
<div id="dash-login">
<div id="dash-reset" class="dash-reset">
<form id="reset" class='login' name="reset" action="/@/dashboard/login" method="POST">
<input type="password" id="new_password"name="new_password" class="form-control" placeholder="New Password" required">
<input type="password" id="new_password2" name="new_password2" class="form-control" placeholder="New Password Confirm" required">
<input type="password" id="secret" name="secret" class="form-control" placeholder="Account Secret" required">
<button id="reset-btn" class='login-btn' type='submit'>
Update Password
</button><br /><br />
<p>
Use this to get your secret to verify it's you. If your email is set up, the secret will be sent there. If not, the form will be updated automatically(but please set up your email, once you reset your password).
</p>
<input type="text"id="email" name="email" class="form-control" placeholder="Verify Email" required">
<button id="get-secret-btn" class='login-btn' type='submit'>
Retrieve Secret
</button><br /><br />
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="/assets/scripts/dash.min.js" type="text/javascript"></script>
{% endblock %}

@ -8,6 +8,7 @@
"lodash-php/lodash-php": "^0.0.7",
"rbdwllr/reallysimplejwt": "^4.0",
"fightbulc/moment": "^1.33",
"tgalopin/html-sanitizer": "^1.4"
"tgalopin/html-sanitizer": "^1.4",
"phpmailer/phpmailer": "^6.4"
}
}

78
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f829b5451dc7ceba4625d240a185b162",
"content-hash": "c511eb33107b993cbfe6dfd51465be02",
"packages": [
{
"name": "erusev/parsedown",
@ -451,6 +451,82 @@
},
"time": "2018-02-13T20:26:39+00:00"
},
{
"name": "phpmailer/phpmailer",
"version": "v6.4.1",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-filter": "*",
"ext-hash": "*",
"php": ">=5.5.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5.6",
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPMailer\\PHPMailer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-only"
],
"authors": [
{
"name": "Marcus Bointon",
"email": "phpmailer@synchromedia.co.uk"
},
{
"name": "Jim Jagielski",
"email": "jimjag@gmail.com"
},
{
"name": "Andy Prevost",
"email": "codeworxtech@users.sourceforge.net"
},
{
"name": "Brent R. Matzelle"
}
],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.4.1"
},
"funding": [
{
"url": "https://github.com/Synchro",
"type": "github"
}
],
"time": "2021-04-29T12:25:04+00:00"
},
{
"name": "psr/container",
"version": "1.1.1",

@ -2154,18 +2154,19 @@ svg.icons {
max-width: 900px;
margin: 0 auto;
}
#dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-form {
#dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-form, #dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-reset {
width: 300px;
padding: 0.75em;
background: #374857;
border-radius: 3px;
color: #f2f1ef;
}
#dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-form input {
#dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-form input, #dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-reset input {
width: 290px;
margin: 0 0 10px 0;
height: 30px;
}
#dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-form button {
#dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-form button, #dash-index-content #dash-index #dash-index-wrapper #dash-login #dash-reset button {
width: 300px;
}
#dash-index-content #dash-index #dash-index-wrapper #dash-menu {

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save