content restore was already enabled, so the last step was completing file restorartion if there was a file archive uploaded now that this has been added, full site restore from backup archives now works.
272 lines
11 KiB
PHP
272 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Upkeep;
|
|
|
|
use ReallySimpleJWT\Token;
|
|
use ReallySimpleJWT\Exception\EncodeException;
|
|
use App\Services\Assets\DocService;
|
|
use Carbon\Carbon;
|
|
|
|
use function _\find;
|
|
|
|
class InitService
|
|
{
|
|
protected $docs;
|
|
|
|
public function __construct(DocService $docService)
|
|
{
|
|
$this->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 (EncodeException $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
|
|
//TODO: Remove hardcoded link and set up init path in settings
|
|
$newFolks = json_decode(
|
|
file_get_contents(env('FIPAMO_INIT') . '/folks-template.json'),
|
|
true
|
|
);
|
|
$newSettings = json_decode(
|
|
file_get_contents(env('FIPAMO_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
|
|
//TODO: upate path attribute to use env variable
|
|
$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 \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
|
|
mkdir(env('FIPAMO_CONFIG'), 0755, true);
|
|
$this->docs->writeSettings($newSettings, env('FIPAMO_CONFIG') . '/settings.json');
|
|
$this->docs->writeSettings($newFolks, env('FIPAMO_CONFIG') . '/folks.json');
|
|
$this->docs->writeSettings([], env('FIPAMO_CONFIG') . '/tags.json');
|
|
$object = (object) $index;
|
|
|
|
$this->docs->writePages(
|
|
'create',
|
|
'start',
|
|
env('PAGES_PATH') . '/start/index.md',
|
|
$this->docs::objectToMD($object)
|
|
);
|
|
|
|
$result = ['type' => 'blogInitGood', 'message' => 'Site Created'];
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function restore($request)
|
|
{
|
|
//content required, so check it
|
|
$result = [];
|
|
$contentArchive = $request->file('backup-content-upload');
|
|
$fileArchive = $request->file('backup-files-upload');
|
|
if ($contentArchive == null || $contentArchive == '') {
|
|
return $result = [
|
|
'type' => 'requestLame',
|
|
'message' => 'Content Archive EMPTY',
|
|
];
|
|
}
|
|
$result = $this->restoreContent($contentArchive, $request);
|
|
//file upload is optional, so if it's present, restore it
|
|
if ($fileArchive != null || $fileArchive != '') {
|
|
$result = $this->restoreFiles($fileArchive);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
private function restoreContent($contentUpload, $request)
|
|
{
|
|
$contentUpload->move(env('FIPAMO_DIR') . '/', $contentUpload->getClientOriginalName());
|
|
$contentZip = new \ZipArchive();
|
|
$result = [];
|
|
$tempDir = env('FIPAMO_DIR') . '/_temp';
|
|
if ($contentZip->open(env('FIPAMO_DIR') . '/' . $contentUpload->getClientOriginalName()) === true) {
|
|
$folks = json_decode($contentZip->getFromName('config/folks.json'), true);
|
|
$found = find($folks, ['handle' => $request->restore_member_handle]);
|
|
if ($found) {
|
|
if (password_verify($request->restore_member_pass, $found['password'])) {
|
|
//restore assets from previous site
|
|
if ($request->restore_former_url != '' || $request->restore_former_url != null) {
|
|
$this->moveAssets($contentZip, $request->restore_former_url);
|
|
}
|
|
$newFolks = [];
|
|
if (!isset($found['secret'])) {
|
|
$found['secret'] = self::validSecret(12);
|
|
}
|
|
array_push($newFolks, $found);
|
|
//make temp folder and dump file in there
|
|
mkdir($tempDir, 0755, true);
|
|
$contentZip->extractTo($tempDir);
|
|
//load up old config file
|
|
$newConfig = json_decode(
|
|
file_get_contents($tempDir . '/config/settings.json'),
|
|
true
|
|
);
|
|
//check for key, add if not there
|
|
if (!isset($newConfig['global']['externalAPI'])) {
|
|
$newConfig['global']['externalAPI'] = 'false';
|
|
}
|
|
//make dir and write new config files
|
|
if (!is_dir(env('FIPAMO_CONFIG'))) {
|
|
mkdir(env('FIPAMO_CONFIG'), 0755, true);
|
|
}
|
|
$this->docs->writeSettings($newConfig, env('FIPAMO_CONFIG') . '/settings.json');
|
|
$this->docs->writeSettings($newFolks, env('FIPAMO_CONFIG') . '/folks.json');
|
|
rename($tempDir . '/config/tags.json', env('FIPAMO_CONFIG') . '/tags.json');
|
|
//move saved markdown pages
|
|
rename($tempDir . '/content/pages/', env('PAGES_PATH'));
|
|
//clean up temp dir and zip file
|
|
$this->docs::deleteFolder($tempDir);
|
|
$contentZip->close();
|
|
unlink(env('FIPAMO_DIR') . '/' . $contentUpload->getClientOriginalName());
|
|
$result = [
|
|
'type' => 'requestGood',
|
|
'message' => 'Content Restored! Redirecting',
|
|
];
|
|
} else {
|
|
$result = [
|
|
'type' => 'requestLame',
|
|
'message' => 'Check that password, champ.',
|
|
];
|
|
}
|
|
} else {
|
|
$result = [
|
|
'type' => 'requestLame',
|
|
'message' => 'Could not open backup. RATS!',
|
|
];
|
|
}
|
|
};
|
|
}
|
|
|
|
private function restoreFiles($filesUpload)
|
|
{
|
|
$filesUpload->move(env('FIPAMO_DIR') . '/', $filesUpload->getClientOriginalName());
|
|
$filesZip = new \ZipArchive();
|
|
$tempDir = env('FIPAMO_DIR') . '/_file_temp';
|
|
$result = [];
|
|
//images path for blog and user
|
|
$blogImagePath = '../public/assets/images/blog';
|
|
$userImagePath = '../public/assets/images/user';
|
|
if ($filesZip->open(env('FIPAMO_DIR') . '/' . $filesUpload->getClientOriginalName()) === true) {
|
|
$filesZip->extractTo($tempDir);
|
|
//clear and move dir if present
|
|
delete_directory($blogImagePath, false);
|
|
if (is_dir($tempDir . '/public/assets/images/blog')) {
|
|
rename($tempDir . '/public/assets/images/blog', $blogImagePath);
|
|
}
|
|
delete_directory($userImagePath, false);
|
|
if (is_dir($tempDir . '/public/assets/images/user')) {
|
|
rename($tempDir . '/public/assets/images/user', $userImagePath);
|
|
}
|
|
$result = [
|
|
'type' => 'requestGood',
|
|
'message' => 'Files & Content Restored! Redirecting',
|
|
];
|
|
}
|
|
delete_directory($tempDir);
|
|
$filesZip->close();
|
|
unlink(env('FIPAMO_DIR') . '/' . $filesUpload->getClientOriginalName());
|
|
return $result;
|
|
}
|
|
|
|
private function moveAssets($zip, $url)
|
|
{
|
|
$assetFail = 0;
|
|
$assetList = [];
|
|
array_push($assetList, json_decode($zip->getFromName('assets/blog_images.json'), true));
|
|
array_push($assetList, json_decode($zip->getFromName('assets/user_images.json'), true));
|
|
array_push($assetList, json_decode($zip->getFromName('assets/blog_docs.json'), true));
|
|
array_push($assetList, json_decode($zip->getFromName('assets/blog_videos.json'), true));
|
|
foreach ($assetList as $list) {
|
|
foreach ($list as $asset) {
|
|
$path = explode('/', $asset['path']);
|
|
$type = $path[3];
|
|
$section = $path[4];
|
|
$year = $path[5];
|
|
$month = $path[6];
|
|
$blogDir = '../public/assets/' . $type . '/' . $section . '/' . $year . '/' . $month;
|
|
if (!is_dir($blogDir)) {
|
|
mkdir($blogDir, 0755, true);
|
|
}
|
|
$externalPath = '/assets/' . $type . '/' . $section . '/' . $year . '/' . $month;
|
|
$asset_url = $url . $externalPath . '/' . $asset['file'];
|
|
try {
|
|
file_put_contents(
|
|
$asset['path'] . '/' . $asset['file'],
|
|
file_get_contents($asset_url)
|
|
);
|
|
} catch (\Throwable $e) {
|
|
$assetFail++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|