diff --git a/app/Helpers/StringHelpers.php b/app/Helpers/StringHelpers.php
index d674b2c..b4f84ed 100644
--- a/app/Helpers/StringHelpers.php
+++ b/app/Helpers/StringHelpers.php
@@ -40,3 +40,18 @@ function safeString($string)
)
);
}
+
+function randomString(int $length)
+{
+ $alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ $special = '*&!@%^#$';
+ $alphabet = $alphanum . $special;
+ $random = openssl_random_pseudo_bytes($length);
+ $alphabet_length = strlen($alphabet);
+ $string = '';
+ for ($i = 0; $i < $length; ++$i) {
+ $string .= $alphabet[ord($random[$i]) % $alphabet_length];
+ }
+
+ return $string;
+}
diff --git a/app/Http/Controllers/API/InitAPIController.php b/app/Http/Controllers/API/InitAPIController.php
new file mode 100644
index 0000000..4cc1059
--- /dev/null
+++ b/app/Http/Controllers/API/InitAPIController.php
@@ -0,0 +1,24 @@
+init = $initService;
+ }
+
+ //init stuff
+ public function setupFresh(Request $request)
+ {
+ $result = $this->init->fresh(json_decode($request->getContent()));
+ return response()->json($result)->header('Content-Type', 'application/json');
+ }
+}
diff --git a/app/Http/Controllers/API/SettingsAPIController.php b/app/Http/Controllers/API/SettingsAPIController.php
index 24a73d7..79e8ae7 100644
--- a/app/Http/Controllers/API/SettingsAPIController.php
+++ b/app/Http/Controllers/API/SettingsAPIController.php
@@ -61,4 +61,11 @@ class SettingsAPIController extends Controller
return response()->download('../content/backups/' . $file, $file, ['Content-Type: application/zip']);
}
}
+
+ //init stuff
+ public function setupFresh(Request $request)
+ {
+ $body = json_decode($request->getContent());
+ dd($body);
+ }
}
diff --git a/app/Http/Controllers/Front/StartController.php b/app/Http/Controllers/Front/StartController.php
index e99b954..a0c5ddf 100644
--- a/app/Http/Controllers/Front/StartController.php
+++ b/app/Http/Controllers/Front/StartController.php
@@ -6,12 +6,19 @@ use App\Http\Controllers\Controller;
class StartController extends Controller
{
+ protected $settings;
+
public function __construct()
{
}
public function index()
{
- return response()->file('../public/index.html');
+ //check if configs are present
+ if (file_exists(env('FOLKS_PATH')) && file_exists(env('SETTINGS_PATH'))) {
+ return response()->file('../public/index.html');
+ } else {
+ return view('back.init', ["status" => false, "title" => "Set Up"]);
+ }
}
}
diff --git a/app/Providers/FipamoServiceProvider.php b/app/Providers/FipamoServiceProvider.php
index 69d3d33..4ee4b58 100644
--- a/app/Providers/FipamoServiceProvider.php
+++ b/app/Providers/FipamoServiceProvider.php
@@ -16,6 +16,7 @@ use App\Services\RenderService;
use App\Services\SortingService;
use App\Services\AssetService;
use App\Services\MaintenanceService;
+use App\Services\InitService;
class FipamoServiceProvider extends ServiceProvider
{
@@ -86,6 +87,10 @@ class FipamoServiceProvider extends ServiceProvider
new SettingsService(new DocService(), new ContentService())
);
});
+
+ $this->app->bind(InitService::class, function ($app) {
+ return new InitService(new DocService());
+ });
}
/**
diff --git a/app/Services/DocService.php b/app/Services/DocService.php
index 1afde60..7e15c1a 100644
--- a/app/Services/DocService.php
+++ b/app/Services/DocService.php
@@ -51,10 +51,15 @@ class DocService
DocTools::writeSettings('../config/settings.json', $settings);
}
- public static function writeSettings($fileContents)
+ public static function writeSettings($fileContents, $location = null)
{
- $fileLocation = env('SETTINGS_PATH');
- $message = [];
+ if (is_null($location)) {
+ $fileLocation = env('SETTINGS_PATH');
+ } else {
+ $fileLocation = $location;
+ }
+
+ $message = [];
try {
if (!is_file($fileLocation)) {
file_put_contents($fileLocation, json_encode($fileContents));
diff --git a/app/Services/InitService.php b/app/Services/InitService.php
new file mode 100644
index 0000000..7234ed9
--- /dev/null
+++ b/app/Services/InitService.php
@@ -0,0 +1,118 @@
+docs = $docService;
+ }
+
+ private static function validSecret($length)
+ {
+ $alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ $special = '*&!@%^#$';
+ $alphabet = $alphanum . $special;
+ $random = openssl_random_pseudo_bytes($length);
+ $alphabet_length = strlen($alphabet);
+ $string = '';
+ for ($i = 0; $i < $length; ++$i) {
+ $string .= $alphabet[ord($random[$i]) % $alphabet_length];
+ }
+ //secret needs to be a valid token
+ if ($length == 12) {
+ try {
+ $secret = Token::create(12, $string, time() + 3600, 'localhost');
+ return $string;
+ } catch (BuildException $e) {
+ //bad secret, so try agiain
+ return self::validSecret(12);
+ }
+
+ if (Token::validate($key, $string)) {
+ return $string;
+ } else {
+ return self::validSecret(12);
+ }
+ }
+ }
+
+ public function fresh($body)
+ {
+ //grab template files
+ $newFolks = json_decode(
+ file_get_contents('../content/config/init/folks-template.json'),
+ true
+ );
+ $newSettings = json_decode(
+ file_get_contents('../content/config/init/settings-template.json'),
+ true
+ );
+ //get form values
+ //$body = $request->getParsedBody();
+ $handle = $body->new_member_handle;
+ $email = $body->new_member_email;
+ $pass = $body->new_member_pass;
+ $title = $body->new_member_title;
+
+ $now = Carbon::now();
+ //setup folks config
+ $hash = password_hash($pass, PASSWORD_DEFAULT);
+ $newFolks[0]['id'] = 0;
+ $newFolks[0]['handle'] = $handle;
+ $newFolks[0]['email'] = $email;
+ $newFolks[0]['password'] = $hash;
+ $newFolks[0]['key'] = password_hash($email, PASSWORD_DEFAULT);
+ $newFolks[0]['secret'] = self::validSecret(12);
+ $newFolks[0]['role'] = 'hnic';
+ $newFolks[0]['created'] = $now->format("Y-m-d\TH:i:sP");
+ $newFolks[0]['updated'] = $now->format("Y-m-d\TH:i:sP");
+ //set up settings config
+ $newSettings['global']['title'] = $title;
+
+ //create index file
+ $index = [
+ 'id' => 1,
+ 'uuid' => createUUID(),
+ 'title' => 'FIRST!',
+ 'imageList' => '/assets/images/global/default-bg.jpg',
+ 'fileList' => '',
+ 'path' => 'content/pages/start',
+ 'layout' => 'index',
+ 'tags' => 'start, welcome',
+ 'author' => $handle,
+ 'created' => $now->format("Y-m-d\TH:i:sP"),
+ 'updated' => $now->format("Y-m-d\TH:i:sP"),
+ 'deleted' => 'false',
+ 'slug' => 'first',
+ 'menu' => 'false',
+ 'featured' => 'false',
+ 'published' => 'true',
+ 'content' => "# F**k Yes \n\nIf you're seeing this, you're up and running. NICE WORK!\n\nFrom here, feel free to start dropping pages to your heart's content.\n\nFor some tips about using Fipamo, check out the ![docs](https://code.playvicio.us/Are0h/Fipamo/wiki/02-Usage)\n\nAll good? Feel free to edit this page to whatever you want!\n\nYOU'RE THE CAPTAIN NOW.",
+ ];
+
+ //once all files created, write down
+ $this->docs->writeSettings($newSettings, '../content/config/settings.json');
+ $this->docs->writeSettings($newFolks, '../content/config/folks.json');
+ $this->docs->writeSettings([], '../content/config/tags.json');
+ $object = (object) $index;
+
+ $this->docs->writePages(
+ 'create',
+ 'start',
+ '../content/pages/start/index.md',
+ $this->docs::objectToMD($object)
+ );
+
+ $result = ['type' => 'blogInitGood', 'message' => 'Site Created'];
+
+ return $result;
+ }
+}
diff --git a/public/assets/css/dash/init.css b/public/assets/css/dash/init.css
index da98fcb..f6471c3 100644
--- a/public/assets/css/dash/init.css
+++ b/public/assets/css/dash/init.css
@@ -1,9 +1,9 @@
/* LOGIN */
section.login,
-section[role="password-reset"],
-section[role="restore-fresh"],
-section[role="restore-backup"] {
+section.password-reset,
+section.restore-fresh,
+section.restore-backup {
margin: 15% auto;
padding: 10px;
width: 500px;
@@ -14,7 +14,7 @@ section[role="restore-backup"] {
visibility: visible;
}
-section[role="restore-backup"] {
+section.restore-backup {
display: none;
visibility: hidden;
color: var(--white);
@@ -47,12 +47,12 @@ section.login form a {
/* PASSWORD-RESET */
-section[role="password-reset"] form button {
+section.password-reset form button {
padding: 10px 5px;
width: 82%;
}
-section[role="password-reset"] form input {
+section.password-reset form input {
width: 95%;
height: 30px;
padding: 5px;
@@ -61,24 +61,24 @@ section[role="password-reset"] form input {
/* SITE RESTORE */
-section[role="restore-fresh"] form button {
+section.restore-fresh form button {
padding: 10px 5px;
width: 82%;
}
-section[role="restore-fresh"] form input {
+section.restore-fresh form input {
width: 95%;
height: 30px;
padding: 5px;
margin-bottom: 10px;
}
-section[role="restore-backup"] form button {
+section.restore-backup form button {
padding: 10px 5px;
width: 82%;
}
-section[role="restore-backup"] form input {
+section.restore-backup form input {
width: 95%;
height: 30px;
padding: 5px;
@@ -89,25 +89,25 @@ section[role="restore-backup"] form input {
@media only screen and (max-width: 500px) {
section.login,
- section[role="password-reset"],
- section[role="restore-fresh"],
- section[role="restore-backup"] {
+ section.password-reset,
+ section.restore-fresh,
+ section.restore-backup {
width: 97%;
}
}
@media only screen and (max-width: 375px) {
section.login,
- section[role="password-reset"],
- section[role="restore-fresh"],
- section[role="restore-backup"] {
+ section.password-reset,
+ section.restore-fresh,
+ section.restore-backup {
grid-template-columns: 1fr;
}
section.login img,
- section[role="password-reset"] img,
- section[role="restore-fresh"] img,
- section[role="restore-backup"] img {
+ section.password-reset img,
+ section.restore-fresh img,
+ section.restore-backup img {
width: 50px;
}
}
diff --git a/public/assets/scripts/dash/app/Init.js b/public/assets/scripts/dash/app/Init.js
new file mode 100644
index 0000000..5e03f8d
--- /dev/null
+++ b/public/assets/scripts/dash/app/Init.js
@@ -0,0 +1,9 @@
+import Init from './controllers/InitController.js';
+
+document.addEventListener(
+ 'DOMContentLoaded',
+ function () {
+ new Init();
+ },
+ false
+);
diff --git a/public/assets/scripts/dash/app/controllers/InitController.js b/public/assets/scripts/dash/app/controllers/InitController.js
new file mode 100644
index 0000000..898fb63
--- /dev/null
+++ b/public/assets/scripts/dash/app/controllers/InitController.js
@@ -0,0 +1,127 @@
+import FipamoAdminAPI from '../../libraries/FipamoAdminAPI.js';
+import Maintenance from './MaintenanceManager.js';
+import DataUitls from '../utils/DataUtils.js';
+import * as DataEvent from '../events/DataEvent.js';
+import Notfications from '../ui/Notifications.js';
+const data = new DataUitls();
+const notify = new Notfications();
+
+export default class InitController {
+ //--------------------------
+ // constructor
+ //--------------------------
+ constructor() {
+ this.processing = false;
+ this.start();
+ }
+
+ //--------------------------
+ // methods
+ //--------------------------
+
+ //TODO: Move init functions and set up to their own class
+ start() {
+ if (document.getElementById('login') || document.querySelector('.site-restore')) {
+ var options = document.getElementsByClassName('init-option');
+ for (let index = 0; index < options.length; index++) {
+ options[index].addEventListener('click', e => this.handleOptions(e));
+ }
+ if (document.getElementById('login')) {
+ document
+ .getElementById('login-btn')
+ .addEventListener('click', e => this.handleLogin(e));
+ } else {
+ document
+ .getElementById('init-blog')
+ .addEventListener('click', e => this.handleSetup(e));
+ document
+ .getElementById('blog-restore')
+ .addEventListener('click', e => this.handleRestore(e));
+ }
+ } else if (document.getElementById('dash-reset')) {
+ document
+ .getElementById('get-secret-btn')
+ .addEventListener('click', e => this.handleReset(e));
+
+ document
+ .getElementById('reset-btn')
+ .addEventListener('click', e => this.handleReset(e));
+ }
+ }
+ //--------------------------
+ // event handlers
+ //--------------------------
+
+ handleSetup(e) {
+ if (this.processing) return;
+ let self = this;
+ e.stopPropagation();
+ e.preventDefault();
+ let setUpForm = data.formDataToJSON(document.getElementById('init-form'));
+ let mm = new Maintenance();
+ this.processing = true;
+ mm.create(setUpForm)
+ .then(response => {
+ if (response.type === DataEvent.API_INIT_LAME) {
+ self.processing = false;
+ e.target.innerHTML = response.message;
+ } else {
+ self.processing = false;
+ e.target.innerHTML = response.message;
+ setTimeout(() => {
+ window.location = '/dashboard';
+ }, 700);
+ }
+ })
+ .catch(err => {
+ self.processing = false;
+ //notify.alert(err, false);
+ });
+ }
+
+ handleRestore(e) {
+ if (this.processing) return;
+ let self = this;
+ e.stopPropagation();
+ e.preventDefault();
+ let mm = new Maintenance();
+ var form = document.getElementById('init-restore');
+ this.processing = true;
+ mm.restore(form)
+ .then(response => {
+ if (response.type === DataEvent.REQUEST_LAME) {
+ self.processing = false;
+ e.target.innerHTML = response.message;
+ } else {
+ self.processing = false;
+ e.target.innerHTML = response.message;
+ setTimeout(() => {
+ window.location = '/dashboard';
+ }, 1500);
+ }
+ })
+ .catch(err => {
+ self.processing = false;
+ e.target.innerHTML = err;
+ });
+ }
+ handleOptions(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ let init = document.querySelector('.restore-fresh');
+ let restore = document.querySelector('.restore-backup');
+ if (e.target.id === 'init-switch-restore') {
+ init.style.display = 'none';
+ init.style.visibility = 'hidden';
+
+ restore.style.display = 'grid';
+ restore.style.visibility = 'visible';
+ } else {
+ init.style.display = 'grid';
+ init.style.visibility = 'visible';
+
+ restore.style.display = 'none';
+ restore.style.visibility = 'hidden';
+ }
+ }
+}
diff --git a/resources/views/back/init.blade.php b/resources/views/back/init.blade.php
new file mode 100644
index 0000000..29b6826
--- /dev/null
+++ b/resources/views/back/init.blade.php
@@ -0,0 +1,17 @@
+@extends('frame')
+
+@section('title', 'The Dash | Set Up Fipamo')
+
+ @section('main-content')
+