ro
d24df50d96
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.
273 lines
11 KiB
PHP
273 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 ![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
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|