Skip to content
This repository was archived by the owner on Jun 8, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions app/Console/Commands/ExportAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace App\Console\Commands;

use App\Domains\Settings\ExportAccount\Services\JsonExportAccount;
use App\Helpers\StorageHelper;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

class ExportAccount extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'monica:export-account
{--user=user : The user id to export.}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Export an account';

/**
* Execute the console command.
*/
public function handle(): void
{
$user = User::findOrFail($this->option('user'));

$tempFileName = '';
try {
$tempFileName = app(JsonExportAccount::class)->execute([
'account_id' => $user->account_id,
'author_id' => $user->id,
]);

$file = StorageHelper::disk('local')->get($tempFileName);

$this->line($file);
} finally {
// delete old file from temp folder
$storage = Storage::disk('local');
if ($storage->exists($tempFileName)) {
$storage->delete($tempFileName);
}
}
}
}
86 changes: 86 additions & 0 deletions app/Domains/Settings/ExportAccount/Jobs/ExportAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace App\Domains\Settings\ExportAccount\Jobs;

use App\Domains\Settings\ExportAccount\Services\JsonExportAccount;
use App\Helpers\StorageHelper;
use App\Models\ExportJob;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\File;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Throwable;

class ExportAccount implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

/**
* Path to the export file.
*/
protected string $path = '';

/**
* Export job to run.
*/
protected ExportJob $exportJob;

/**
* Create a new job instance.
*/
public function __construct(ExportJob $exportJob, string $path = null)
{
$exportJob->status = ExportJob::EXPORT_TODO;
$exportJob->save();
$this->exportJob = $exportJob->withoutRelations();
$this->path = $path ?? "exports/{$exportJob->account->id}";
}

/**
* Execute the job.
*/
public function handle()
{
$this->exportJob->start();

$tempFileName = '';
try {
$tempFileName = app(JsonExportAccount::class)->execute([
'account_id' => $this->exportJob->account_id,
'author_id' => $this->exportJob->author_id,
]);

// get the temp file that we just created
$tempFilePath = StorageHelper::disk('local')->path($tempFileName);

// move the file to the public storage
$file = StorageHelper::disk(config('filesystems.default'))
->putFileAs($this->path, new File($tempFilePath), basename($tempFileName));

$this->exportJob->location = config('filesystems.default');
$this->exportJob->filename = $file;

$this->exportJob->end();
} catch (Throwable $e) {
$this->fail($e);
} finally {
// delete old file from temp folder
$storage = Storage::disk('local');
if ($storage->exists($tempFileName)) {
$storage->delete($tempFileName);
}
}
}

/**
* Handle a job failure.
*/
public function failed(Throwable $exception): void
{
$this->exportJob->status = ExportJob::EXPORT_FAILED;
$this->exportJob->save();
}
}
88 changes: 88 additions & 0 deletions app/Domains/Settings/ExportAccount/Services/JsonExportAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace App\Domains\Settings\ExportAccount\Services;

use App\ExportResources\Account\Account as AccountResource;
use App\Models\Account;
use App\Models\User;
use App\Services\BaseService;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class JsonExportAccount extends BaseService
{
protected string $tempFileName;

/**
* Get the validation rules that apply to the service.
*/
public function rules(): array
{
return [
'account_id' => 'required|uuid|exists:accounts,id',
'author_id' => 'required|uuid|exists:users,id',
];
}

/**
* Get the permissions that apply to the user calling the service.
*/
public function permissions(): array
{
return [
'author_must_belong_to_account',
'author_must_be_account_administrator',
];
}

/**
* Export account as Json.
*/
public function execute(array $data): string
{
$this->validateRules($data);

$this->tempFileName = 'temp/'.Str::uuid().'.json';

$this->writeExport($data, $this->author);

return $this->tempFileName;
}

/**
* Export data in temp file.
*/
private function writeExport(array $data, User $user)
{
$result = [];
$result['version'] = '2.0-preview.1';
$result['app_version'] = config('monica.app_version');
$result['export_date'] = now();
$result['url'] = config('app.url');
$result['exported_by'] = $user->id;
$result['account'] = $this->exportAccount($data);

$this->writeToTempFile(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_IGNORE | JSON_UNESCAPED_SLASHES));
}

/**
* Write to a temp file.
*/
private function writeToTempFile(string $sql): void
{
Storage::disk('local')
->append($this->tempFileName, $sql);
}

/**
* Export the Account table.
*/
private function exportAccount(array $data): array
{
$account = Account::find($data['account_id']);

$exporter = new AccountResource($account);

return $exporter->resolve();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace App\Domains\Settings\ExportAccount\Web\Controllers;

use App\Domains\Settings\ExportAccount\Jobs\ExportAccount;
use App\Domains\Settings\ExportAccount\Web\ViewHelpers\ExportAccountViewHelper;
use App\Domains\Vault\ManageVault\Web\ViewHelpers\VaultIndexViewHelper;
use App\Helpers\StorageHelper;
use App\Http\Controllers\Controller;
use App\Models\ExportJob;
use Illuminate\Http\Request;
use Inertia\Inertia;

class ExportAccountController extends Controller
{
public function index(Request $request)
{
return Inertia::render('Settings/ExportAccount/Index', [
'layoutData' => VaultIndexViewHelper::layoutData(),
'data' => ExportAccountViewHelper::data($request->user()->account),
]);
}

public function store(Request $request)
{
$exportJob = $request->user()->account->exportJobs()->create([
'author_id' => $request->user()->id,
]);
ExportAccount::dispatch($exportJob);

return $this->index($request);
}

/**
* Download the generated file.
*
* @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response|null
*/
public function download(Request $request, ExportJob $job)
{
if ($job->status !== ExportJob::EXPORT_DONE) {
return redirect()->route('settings.export.index')
->withErrors(__('Download impossible, this export is not done yet.'));
}
$disk = StorageHelper::disk($job->location);

return $disk->response($job->filename,
'monica.json',
[
'Content-Type' => 'application/json; charset=utf-8',
'Content-Disposition' => 'attachment; filename=monica.json',
]
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Domains\Settings\ExportAccount\Web\ViewHelpers;

use App\Helpers\DateHelper;
use App\Models\Account;
use App\Models\ExportJob;

class ExportAccountViewHelper
{
public static function data(Account $account): array
{
return [
'url' => [
'settings' => route('settings.index'),
'back' => route('settings.index'),
'destroy' => route('settings.cancel.destroy'),
],
'jobs' => $account->exportJobs()->orderBy('created_at', 'desc')->get()->map(fn ($job) => static::dtoJob($job)),
];
}

public static function dtoJob(ExportJob $job): array
{
$status = '';
switch ($job->status) {
case ExportJob::EXPORT_TODO:
$status = __('Todo');
break;
case ExportJob::EXPORT_DOING:
$status = __('In progress');
break;
case ExportJob::EXPORT_DONE:
$status = __('Done');
break;
case ExportJob::EXPORT_FAILED:
$status = __('Failed');
break;
}

return [
'id' => $job->id,
'date' => DateHelper::formatShortDateWithTime($job->created_at),
'status' => $status,
];
}
}
Loading