moved password recovery updates to beta
This commit is contained in:
parent
1c7fcd6664
commit
913dd3a57f
16 changed files with 569 additions and 101 deletions
|
@ -18,6 +18,7 @@ include "../brain/utility/DocTools.inc.php";
|
||||||
include "../brain/utility/Sorting.inc.php";
|
include "../brain/utility/Sorting.inc.php";
|
||||||
include "../brain/utility/Setup.inc.php";
|
include "../brain/utility/Setup.inc.php";
|
||||||
include "../brain/utility/Maintenance.inc.php";
|
include "../brain/utility/Maintenance.inc.php";
|
||||||
|
include "../brain/utility/Mailer.inc.php";
|
||||||
|
|
||||||
class App
|
class App
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,4 +60,14 @@ class AuthAPI
|
||||||
];
|
];
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
public static function requestSecret($body)
|
||||||
|
{
|
||||||
|
$result = Auth::findSecret($body);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
public static function resetPassword($body)
|
||||||
|
{
|
||||||
|
$result = Auth::makeNewPassword($body);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
26
brain/api/v1/MailerAPI.inc.php
Normal file
26
brain/api/v1/MailerAPI.inc.php
Normal file
|
@ -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/PagesAPI.inc.php";
|
||||||
include "../brain/api/v1/SettingsAPI.inc.php";
|
include "../brain/api/v1/SettingsAPI.inc.php";
|
||||||
include "../brain/api/v1/InitAPI.inc.php";
|
include "../brain/api/v1/InitAPI.inc.php";
|
||||||
|
include "../brain/api/v1/MailerAPI.inc.php";
|
||||||
|
|
||||||
class APIControl
|
class APIControl
|
||||||
{
|
{
|
||||||
|
@ -82,15 +83,15 @@ class APIControl
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (isset($args["third"]) ? $args["third"] : "none") {
|
switch (isset($args["third"]) ? $args["third"] : "none") {
|
||||||
case "restore":
|
case "restore": //move to 'api/auth'
|
||||||
case "init":
|
case "init": //move to 'api/auth'
|
||||||
$task = $args["third"];
|
$task = $args["third"];
|
||||||
$result = InitApi::handleInitTasks(
|
$result = InitApi::handleInitTasks(
|
||||||
$task,
|
$task,
|
||||||
$task == "init" ? $body : $request
|
$task == "init" ? $body : $request
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "backup":
|
case "backup": //move to 'api/auth'
|
||||||
$token = $request->getHeader("fipamo-access-token");
|
$token = $request->getHeader("fipamo-access-token");
|
||||||
//Verify token for admin tasks
|
//Verify token for admin tasks
|
||||||
if (Session::verifyToken($token[0])) {
|
if (Session::verifyToken($token[0])) {
|
||||||
|
@ -102,12 +103,18 @@ class APIControl
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "login":
|
case "login": //move to 'api/auth'
|
||||||
$result = AuthAPI::login($body);
|
$result = AuthAPI::login($body);
|
||||||
break;
|
break;
|
||||||
case "logout":
|
case "logout": //move to 'api/auth'
|
||||||
$result = AuthAPI::logout($body);
|
$result = AuthAPI::logout($body);
|
||||||
break;
|
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":
|
case "page":
|
||||||
$token = $request->getHeader("fipamo-access-token");
|
$token = $request->getHeader("fipamo-access-token");
|
||||||
//Verify token for admin tasks
|
//Verify token for admin tasks
|
||||||
|
@ -137,6 +144,9 @@ class APIControl
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "mailer":
|
||||||
|
$result = MailerAPI::handleMail($request, $body, $response);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$result = [
|
$result = [
|
||||||
"message" => "Oh, nothing to do. That's unfortunate",
|
"message" => "Oh, nothing to do. That's unfortunate",
|
||||||
|
|
|
@ -38,6 +38,7 @@ class DashControl
|
||||||
"currentTheme" => $settings["global"]["theme"],
|
"currentTheme" => $settings["global"]["theme"],
|
||||||
"themes" => $themes,
|
"themes" => $themes,
|
||||||
"mailOption" => $settings["email"]["active"],
|
"mailOption" => $settings["email"]["active"],
|
||||||
|
"mailConfig" => $settings["email"],
|
||||||
"status" => Session::active(),
|
"status" => Session::active(),
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
|
@ -116,9 +117,14 @@ class DashControl
|
||||||
header("Location: /dashboard");
|
header("Location: /dashboard");
|
||||||
die();
|
die();
|
||||||
break;
|
break;
|
||||||
|
case "reset-password":
|
||||||
|
$template = "dash/reset-password.twig";
|
||||||
|
$pageOptions = [
|
||||||
|
"title" => "Reset Password",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//$secret = ;
|
|
||||||
$template = "dash/start.twig";
|
$template = "dash/start.twig";
|
||||||
if (Session::active()) {
|
if (Session::active()) {
|
||||||
$pageOptions = [
|
$pageOptions = [
|
||||||
|
|
|
@ -5,70 +5,146 @@ use ReallySimpleJWT\Token;
|
||||||
|
|
||||||
class Auth
|
class Auth
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function sessionStatus()
|
public static function sessionStatus()
|
||||||
{
|
{
|
||||||
if (isset($_SESSION["member"])) {
|
if (isset($_SESSION["member"])) {
|
||||||
return true;
|
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 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"],
|
||||||
|
];
|
||||||
|
|
||||||
|
$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";
|
||||||
|
}
|
||||||
|
} 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 {
|
} else {
|
||||||
return false;
|
$result = [
|
||||||
|
"message" => "Valid email, but no email set up!",
|
||||||
|
"type" => "secretFound",
|
||||||
|
"secret" => $found["secret"],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
//return $this->secret;
|
} 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 status()
|
return $result;
|
||||||
{
|
}
|
||||||
$result = "";
|
|
||||||
if (Session::active()) {
|
public static function makeNewPassword($data)
|
||||||
$result = true;
|
{
|
||||||
} else {
|
//check if passwordsmatch
|
||||||
$result = false;
|
if ($data["newPass"] == $data["newPassConfirm"]) {
|
||||||
}
|
//verify secret
|
||||||
return $result;
|
$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",
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function login($who)
|
return $result;
|
||||||
{
|
}
|
||||||
//grab member list
|
|
||||||
$folks = (new Settings())->getFolks();
|
|
||||||
$found = find($folks, ["handle" => $who["handle"]]);
|
|
||||||
|
|
||||||
if ($found) {
|
public static function logout()
|
||||||
//name is found, verify password
|
{
|
||||||
if (password_verify($who["password"], $found["password"])) {
|
Session::kill();
|
||||||
$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);
|
|
||||||
|
|
||||||
$result = "good_login";
|
|
||||||
} else {
|
|
||||||
$result = "bad_pass";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//if name is not found
|
|
||||||
$result = "no_name";
|
|
||||||
}
|
|
||||||
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();
|
$folks = (new Settings())->getFolks();
|
||||||
$member = Session::get("member");
|
if (isset($secret)) {
|
||||||
$found = find($folks, ["handle" => $member["handle"]]);
|
$found = find($folks, ["secret" => $secret]);
|
||||||
|
} else {
|
||||||
|
$member = Session::get("member");
|
||||||
|
$found = find($folks, ["handle" => $member["handle"]]);
|
||||||
|
}
|
||||||
$found[$key] = $data;
|
$found[$key] = $data;
|
||||||
//record time updated
|
//record time updated
|
||||||
$updated = new \Moment\Moment();
|
$updated = new \Moment\Moment();
|
||||||
|
@ -22,12 +26,14 @@ class Member
|
||||||
DocTools::writeSettings("../config/folks.json", $newFolks);
|
DocTools::writeSettings("../config/folks.json", $newFolks);
|
||||||
//update member data in session
|
//update member data in session
|
||||||
|
|
||||||
$member = [
|
if (!isset($secret)) {
|
||||||
"handle" => $found["handle"],
|
$member = [
|
||||||
"email" => $found["email"],
|
"handle" => $found["handle"],
|
||||||
"role" => $found["role"],
|
"email" => $found["email"],
|
||||||
"avatar" => $found["avi"],
|
"role" => $found["role"],
|
||||||
];
|
"avatar" => $found["avi"],
|
||||||
Session::set("member", $member);
|
];
|
||||||
|
Session::set("member", $member);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
94
brain/utility/Mailer.inc.php
Normal file
94
brain/utility/Mailer.inc.php
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
120
brain/views/dash/email.twig
Normal file
120
brain/views/dash/email.twig
Normal file
|
@ -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-login">
|
||||||
<div id="dash-form" class="dash-form">
|
<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="text" name="handle" class="form-control" placeholder="Handle" required ">
|
||||||
<input type="password" name="password" class="form-control" placeholder="Password" 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
|
Let's see some ID
|
||||||
</button>
|
</button><br /><br />
|
||||||
|
<a href="/dashboard/reset-password"> Forgot Password?</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,31 +1,31 @@
|
||||||
{% if mailOption == "option-smtp" %}
|
{% if mailOption == "option-smtp" %}
|
||||||
<div id="mail-smtp" data-enabled='true'>
|
<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-domain' id='smtp-domain' placeholder='domain'value="{{mailConfig['smtp']['domain']}}"/>
|
||||||
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="settings.email.smtp.email" />
|
<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="settings.email.smtp.password"/>
|
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="{{mailConfig['smtp']['password']}}"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="mail-mg" data-enabled='false'>
|
<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-domain' id='mg-domain' placeholder='domain' value="{{mailConfig['mailgun']['domain']}}" />
|
||||||
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="settings.email.mailgun.key "/>
|
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="{{mailConfig['mailgun']['key']}}"/>
|
||||||
</div>
|
</div>
|
||||||
{% elseif(mailOption == 'option-mg') %}
|
{% elseif(mailOption == 'option-mg') %}
|
||||||
<div id="mail-smtp" data-enabled='false'>
|
<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-domain' id='smtp-domain' placeholder='domain'value="{{mailConfig['smtp']['domain']}}"/>
|
||||||
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="settings.email.smtp.email" />
|
<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="settings.email.smtp.password"/>
|
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="{{mailConfig['smtp']['password']}}"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="mail-mg" data-enabled='true'>
|
<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-domain' id='mg-domain' placeholder='domain' value="{{mailConfig['mailgun']['domain']}}" />
|
||||||
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="settings.email.mailgun.key "/>
|
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="{{mailConfig['mailgun']['key']}}"/>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div id="mail-smtp" data-enabled='false'>
|
<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-domain' id='smtp-domain' placeholder='domain'value="{{mailConfig['smtp']['domain']}}"/>
|
||||||
<input type='text' name='smtp-email' id='smtp-email' placeholder='email' value="settings.email.smtp.email" />
|
<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="settings.email.smtp.password"/>
|
<input type='text' name='smtp-pass' id='smtp-pass' placeholder='password' value="{{mailConfig['smtp']['password']}}"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="mail-mg" data-enabled='false'>
|
<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-domain' id='mg-domain' placeholder='domain' value="{{mailConfig['mailgun']['domain']}}" />
|
||||||
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="settings.email.mailgun.key "/>
|
<input type='text' name='mg-key' id='mg-key' placeholder='api key' value="{{mailConfig['mailgun']['key']}}"/>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
40
brain/views/dash/reset-password.twig
Normal file
40
brain/views/dash/reset-password.twig
Normal file
|
@ -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",
|
"lodash-php/lodash-php": "^0.0.7",
|
||||||
"rbdwllr/reallysimplejwt": "^4.0",
|
"rbdwllr/reallysimplejwt": "^4.0",
|
||||||
"fightbulc/moment": "^1.33",
|
"fightbulc/moment": "^1.33",
|
||||||
"tgalopin/html-sanitizer": "^1.4"
|
"tgalopin/html-sanitizer": "^1.4",
|
||||||
|
"phpmailer/phpmailer": "^6.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
78
composer.lock
generated
78
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "f829b5451dc7ceba4625d240a185b162",
|
"content-hash": "c511eb33107b993cbfe6dfd51465be02",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "erusev/parsedown",
|
"name": "erusev/parsedown",
|
||||||
|
@ -451,6 +451,82 @@
|
||||||
},
|
},
|
||||||
"time": "2018-02-13T20:26:39+00:00"
|
"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",
|
"name": "psr/container",
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
|
|
|
@ -2154,18 +2154,19 @@ svg.icons {
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin: 0 auto;
|
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;
|
width: 300px;
|
||||||
padding: 0.75em;
|
padding: 0.75em;
|
||||||
background: #374857;
|
background: #374857;
|
||||||
border-radius: 3px;
|
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;
|
width: 290px;
|
||||||
margin: 0 0 10px 0;
|
margin: 0 0 10px 0;
|
||||||
height: 30px;
|
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;
|
width: 300px;
|
||||||
}
|
}
|
||||||
#dash-index-content #dash-index #dash-index-wrapper #dash-menu {
|
#dash-index-content #dash-index #dash-index-wrapper #dash-menu {
|
||||||
|
|
8
public/assets/scripts/dash.min.js
vendored
8
public/assets/scripts/dash.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue