This commit is contained in:
James Cole
2020-07-11 15:13:15 +02:00
parent 86600d4fcf
commit 54d92f5b39
20 changed files with 737 additions and 205 deletions

View File

@@ -0,0 +1,280 @@
<?php
/**
* DestroyController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Data;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DataDestroyRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use Illuminate\Http\JsonResponse;
/**
* Class DestroyController
*/
class DestroyController extends Controller
{
/**
* @return JsonResponse
*/
public function destroy(DataDestroyRequest $request): JsonResponse
{
$objects = $request->getObjects();
switch ($objects) {
default:
throw new FireflyException(sprintf('This endpoint can\'t handle object "%s"', $objects));
case 'budgets':
$this->destroyBudgets();
break;
case 'bills':
$this->destroyBills();
break;
case 'piggy_banks':
$this->destroyPiggyBanks();
break;
case 'rules':
$this->destroyRules();
break;
case 'recurring':
$this->destroyRecurringTransactions();
break;
case 'categories':
$this->destroyCategories();
break;
case 'tags':
$this->destroyTags();
break;
case 'object_groups':
$this->destroyObjectGroups();
break;
case 'accounts':
$this->destroyAccounts(
[
AccountType::ASSET, AccountType::DEFAULT,
AccountType::BENEFICIARY, AccountType::EXPENSE,
AccountType::REVENUE, AccountType::INITIAL_BALANCE,
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
]
);
break;
case 'asset_accounts':
$this->destroyAccounts(
[
AccountType::ASSET, AccountType::DEFAULT,
]
);
break;
case 'expense_accounts':
$this->destroyAccounts(
[
AccountType::BENEFICIARY, AccountType::EXPENSE,
]
);
break;
case 'revenue_accounts':
$this->destroyAccounts(
[
AccountType::REVENUE,
]
);
break;
case 'liabilities':
$this->destroyAccounts(
[
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
]
);
break;
case 'transactions':
$this->destroyTransactions(
[
TransactionType::WITHDRAWAL,
TransactionType::DEPOSIT,
TransactionType::TRANSFER,
TransactionType::RECONCILIATION,
TransactionType::OPENING_BALANCE,
]
);
break;
case 'withdrawals':
$this->destroyTransactions(
[
TransactionType::WITHDRAWAL,
]
);
break;
case 'deposits':
$this->destroyTransactions(
[
TransactionType::DEPOSIT,
]
);
break;
case 'transfers':
$this->destroyTransactions(
[
TransactionType::TRANSFER,
]
);
break;
}
return response()->json([], 204);
}
/**
* @param array $types
*/
private function destroyAccounts(array $types): void
{
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$collection = $repository->getAccountsByType($types);
$service = app(AccountDestroyService::class);
/** @var Account $account */
foreach ($collection as $account) {
$service->destroy($account, null);
}
}
/**
*
*/
private function destroyBills(): void
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyBudgets(): void
{
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$abRepository->destroyAll();
/** @var BudgetLimitRepositoryInterface $blRepository */
$blRepository = app(BudgetLimitRepositoryInterface::class);
$blRepository->destroyAll();
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgetRepository->destroyAll();
}
/**
*
*/
private function destroyCategories(): void
{
/** @var CategoryRepositoryInterface $categoryRepos */
$categoryRepos = app(CategoryRepositoryInterface::class);
$categoryRepos->destroyAll();
}
private function destroyObjectGroups(): void
{
/** @var ObjectGroupRepositoryInterface $repository */
$repository = app(ObjectGroupRepositoryInterface::class);
$repository->deleteAll();
}
/**
*
*/
private function destroyPiggyBanks(): void
{
/** @var PiggyBankRepositoryInterface $repository */
$repository = app(PiggyBankRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRecurringTransactions(): void
{
/** @var RecurringRepositoryInterface $repository */
$repository = app(RecurringRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRules(): void
{
/** @var RuleGroupRepositoryInterface $repository */
$repository = app(RuleGroupRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyTags(): void
{
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
$tagRepository->destroyAll();
}
/**
* @param array $types
*/
private function destroyTransactions(array $types): void
{
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$journals = $repository->findByType($types);
$service = app(JournalDestroyService::class);
/** @var TransactionJournal $journal */
foreach($journals as $journal) {
$service->destroy($journal);
}
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* DataDestroyRequest.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
/**
* Class DataDestroyRequest
*/
class DataDestroyRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return string
*/
public function getObjects(): string
{
return $this->get('objects') ?? '';
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups' .
',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers';
return [
'objects' => sprintf('min:1|string|in:%s', $valid),
];
}
}

View File

@@ -1,91 +0,0 @@
<?php
/**
* DataController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Profile;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Http\RedirectResponse;
/**
* Class DataController
*/
class DataController extends Controller
{
/**
*
*/
public function deleteBudgets(): RedirectResponse
{
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$abRepository->destroyAll();
/** @var BudgetLimitRepositoryInterface $blRepository */
$blRepository = app(BudgetLimitRepositoryInterface::class);
$blRepository->destroyAll();
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgetRepository->destroyAll();
session()->flash('success', trans('firefly.deleted_all_budgets'));
return redirect(route('profile.index'));
}
/**
*
*/
public function deleteCategories(): RedirectResponse
{
/** @var CategoryRepositoryInterface $categoryRepos */
$categoryRepos = app(CategoryRepositoryInterface::class);
$categoryRepos->destroyAll();
session()->flash('success', trans('firefly.deleted_all_categories'));
return redirect(route('profile.index'));
}
/**
*
*/
public function deleteTags(): RedirectResponse
{
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
$tagRepository->destroyAll();
session()->flash('success', trans('firefly.deleted_all_tags'));
return redirect(route('profile.index'));
}
}

View File

@@ -50,8 +50,7 @@ use Storage;
class BillRepository implements BillRepositoryInterface
{
use CreatesObjectGroups;
/** @var User */
private $user;
private User $user;
/**
* Constructor.
@@ -764,4 +763,12 @@ class BillRepository implements BillRepositoryInterface
$bill->order = $order;
$bill->save();
}
/**
* @inheritDoc
*/
public function destroyAll(): void
{
$this->user->bills()->delete();
}
}

View File

@@ -43,6 +43,11 @@ interface BillRepositoryInterface
*/
public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill;
/**
*
*/
public function destroyAll(): void;
/**
* @param Bill $bill
*

View File

@@ -396,4 +396,16 @@ class JournalRepository implements JournalRepositoryInterface
return $result;
}
/**
* @inheritDoc
*/
public function findByType(array $types): Collection
{
return $this->user
->transactionJournals()
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->whereIn('transaction_types.type', $types)
->get(['transaction_journals.*']);
}
}

View File

@@ -42,6 +42,13 @@ interface JournalRepositoryInterface
*/
public function getLast(): ?TransactionJournal;
/**
* @param array $types
*
* @return Collection
*/
public function findByType(array $types): Collection;
/**
* TODO maybe create JSON repository?
*

View File

@@ -171,4 +171,18 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface
{
return $objectGroup->piggyBanks;
}
/**
* @inheritDoc
*/
public function deleteAll(): void
{
$all = $this->get();
/** @var ObjectGroup $group */
foreach ($all as $group) {
$group->piggyBanks()->sync([]);
$group->bills()->sync([]);
$group->delete();
}
}
}

View File

@@ -48,6 +48,10 @@ interface ObjectGroupRepositoryInterface
* Delete empty ones.
*/
public function deleteEmpty(): void;
/**
* Delete all.
*/
public function deleteAll(): void;
/**
* @param ObjectGroup $objectGroup

View File

@@ -396,4 +396,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
}
/**
* @inheritDoc
*/
public function destroyAll(): void
{
$this->user->piggyBanks()->delete();
}
}

View File

@@ -36,6 +36,11 @@ use Illuminate\Support\Collection;
*/
interface PiggyBankRepositoryInterface
{
/**
*
*/
public function destroyAll(): void;
/**
* @param PiggyBank $piggyBank
* @param string $objectGroupTitle

View File

@@ -561,4 +561,12 @@ class RecurringRepository implements RecurringRepositoryInterface
return $filtered;
}
/**
* @inheritDoc
*/
public function destroyAll(): void
{
$this->user->recurrences()->delete();
}
}

View File

@@ -25,7 +25,6 @@ namespace FireflyIII\Repositories\Recurring;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Models\RecurrenceTransaction;
@@ -40,6 +39,11 @@ use Illuminate\Support\Collection;
*/
interface RecurringRepositoryInterface
{
/**
* Destroy all recurring transactions.
*/
public function destroyAll(): void;
/**
* Destroy a recurring transaction.
*

View File

@@ -358,4 +358,16 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
return $this->user->ruleGroups()->where('title', $title)->first();
}
/**
* @inheritDoc
*/
public function destroyAll(): void
{
$groups = $this->get();
/** @var RuleGroup $group */
foreach ($groups as $group) {
$group->rules()->delete();
$group->delete();
}
}
}

View File

@@ -31,13 +31,18 @@ use Illuminate\Support\Collection;
*/
interface RuleGroupRepositoryInterface
{
/**
* Delete everything.
*/
public function destroyAll(): void;
/**
* @return int
*/
public function count(): int;
/**
* @param RuleGroup $ruleGroup
* @param RuleGroup $ruleGroup
* @param RuleGroup|null $moveTo
*
* @return bool

View File

@@ -96,6 +96,16 @@ class JournalDestroyService
$journal->piggyBankEvents()->update(['transaction_journal_id' => null]);
$journal->delete();
// delete group, if group is empty:
$group = $journal->transactionGroup;
if (null !== $group) {
$count = $group->transactionJournals->count();
if (0 === $count) {
$group->delete();
}
}
} catch (Exception $e) {
Log::error(sprintf('Could not delete bill: %s', $e->getMessage())); // @codeCoverageIgnore
}

View File

@@ -605,54 +605,84 @@ return [
'list_page_size_help' => 'Any list of things (accounts, transactions, etc) shows at most this many per page.',
'list_page_size_label' => 'Page size',
'between_dates' => '(:start and :end)',
'pref_optional_fields_transaction' => 'Optional fields for transactions',
'pref_optional_fields_transaction_help' => 'By default not all fields are enabled when creating a new transaction (because of the clutter). Below, you can enable these fields if you think they could be useful for you. Of course, any field that is disabled, but already filled in, will be visible regardless of the setting.',
'optional_tj_date_fields' => 'Date fields',
'optional_tj_business_fields' => 'Business fields',
'optional_tj_attachment_fields' => 'Attachment fields',
'pref_optional_tj_interest_date' => 'Interest date',
'pref_optional_tj_book_date' => 'Book date',
'pref_optional_tj_process_date' => 'Processing date',
'pref_optional_tj_due_date' => 'Due date',
'pref_optional_tj_payment_date' => 'Payment date',
'pref_optional_tj_invoice_date' => 'Invoice date',
'pref_optional_tj_internal_reference' => 'Internal reference',
'pref_optional_tj_notes' => 'Notes',
'pref_optional_tj_attachments' => 'Attachments',
'optional_field_meta_dates' => 'Dates',
'optional_field_meta_business' => 'Business',
'optional_field_attachments' => 'Attachments',
'optional_field_meta_data' => 'Optional meta data',
'pref_optional_fields_transaction' => 'Optional fields for transactions',
'pref_optional_fields_transaction_help' => 'By default not all fields are enabled when creating a new transaction (because of the clutter). Below, you can enable these fields if you think they could be useful for you. Of course, any field that is disabled, but already filled in, will be visible regardless of the setting.',
'optional_tj_date_fields' => 'Date fields',
'optional_tj_business_fields' => 'Business fields',
'optional_tj_attachment_fields' => 'Attachment fields',
'pref_optional_tj_interest_date' => 'Interest date',
'pref_optional_tj_book_date' => 'Book date',
'pref_optional_tj_process_date' => 'Processing date',
'pref_optional_tj_due_date' => 'Due date',
'pref_optional_tj_payment_date' => 'Payment date',
'pref_optional_tj_invoice_date' => 'Invoice date',
'pref_optional_tj_internal_reference' => 'Internal reference',
'pref_optional_tj_notes' => 'Notes',
'pref_optional_tj_attachments' => 'Attachments',
'optional_field_meta_dates' => 'Dates',
'optional_field_meta_business' => 'Business',
'optional_field_attachments' => 'Attachments',
'optional_field_meta_data' => 'Optional meta data',
// profile:
'permanent_delete_stuff' => 'Be careful with these buttons. Deleting stuff is permanent.',
'other_sessions_logged_out' => 'All your other sessions have been logged out.',
'delete_all_budgets' => 'Delete ALL your budgets',
'delete_all_categories' => 'Delete ALL your categories',
'delete_all_tags' => 'Delete ALL your tags',
'deleted_all_budgets' => 'All budgets have been deleted',
'deleted_all_categories' => 'All categories have been deleted',
'deleted_all_tags' => 'All tags have been deleted',
'change_your_password' => 'Change your password',
'delete_account' => 'Delete account',
'current_password' => 'Current password',
'new_password' => 'New password',
'new_password_again' => 'New password (again)',
'delete_your_account' => 'Delete your account',
'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, <em>anything</em> you might have saved into Firefly III. It\'ll be GONE.',
'delete_your_account_password' => 'Enter your password to continue.',
'password' => 'Password',
'are_you_sure' => 'Are you sure? You cannot undo this.',
'delete_account_button' => 'DELETE your account',
'invalid_current_password' => 'Invalid current password!',
'password_changed' => 'Password changed!',
'should_change' => 'The idea is to change your password.',
'invalid_password' => 'Invalid password!',
'what_is_pw_security' => 'What is "verify password security"?',
'secure_pw_title' => 'How to choose a secure password',
'secure_pw_history' => 'Not a week goes by that you read in the news about a site losing the passwords of its users. Hackers and thieves use these passwords to try to steal your private information. This information is valuable.',
'secure_pw_ff' => 'Do you use the same password all over the internet? If one site loses your password, hackers have access to all your data. Firefly III relies on you to choose a strong and unique password to protect your financial records.',
'secure_pw_check_box' => 'To help you do that Firefly III can check if the password you want to use has been stolen in the past. If this is the case, Firefly III advises you NOT to use that password.',
'delete_stuff_header' => 'Delete data from Firefly III',
'permanent_delete_stuff' => 'Be careful with these buttons. Deleting stuff is permanent.',
'other_sessions_logged_out' => 'All your other sessions have been logged out.',
'delete_all_budgets' => 'Delete ALL your budgets',
'delete_all_categories' => 'Delete ALL your categories',
'delete_all_tags' => 'Delete ALL your tags',
'delete_all_bills' => 'Delete ALL your bills',
'delete_all_piggy_banks' => 'Delete ALL your piggy banks',
'delete_all_rules' => 'Delete ALL your rules',
'delete_all_recurring' => 'Delete ALL your recurring transactions',
'delete_all_object_groups' => 'Delete ALL your object groups',
'delete_all_accounts' => 'Delete ALL your accounts',
'delete_all_asset_accounts' => 'Delete ALL your asset accounts',
'delete_all_expense_accounts' => 'Delete ALL your expense accounts',
'delete_all_revenue_accounts' => 'Delete ALL your revenue accounts',
'delete_all_liabilities' => 'Delete ALL your liabilities',
'delete_all_transactions' => 'Delete ALL your transactions',
'delete_all_withdrawals' => 'Delete ALL your withdrawals',
'delete_all_deposits' => 'Delete ALL your deposits',
'delete_all_transfers' => 'Delete ALL your transfers',
'also_delete_transactions' => 'Deleting accounts will also delete ALL associated withdrawals, deposits and transfers!',
'deleted_all_budgets' => 'All budgets have been deleted',
'deleted_all_categories' => 'All categories have been deleted',
'deleted_all_tags' => 'All tags have been deleted',
'deleted_all_bills' => 'All bills have been deleted',
'deleted_all_piggy_banks' => 'All piggy banks have been deleted',
'deleted_all_rules' => 'All rules and rule groups have been deleted',
'deleted_all_object_groups' => 'All groups have been deleted',
'deleted_all_accounts' => 'All accounts have been deleted',
'deleted_all_asset_accounts' => 'All asset accounts have been deleted',
'deleted_all_expense_accounts' => 'All expense accounts have been deleted',
'deleted_all_revenue_accounts' => 'All revenue accounts have been deleted',
'deleted_all_liabilities' => 'All liabilities have been deleted',
'deleted_all_transactions' => 'All transactions have been deleted',
'deleted_all_withdrawals' => 'All withdrawals have been deleted',
'deleted_all_deposits' => 'All deposits have been deleted',
'deleted_all_transfers' => 'All transfers have been deleted',
'deleted_all_recurring' => 'All recurring transactions have been deleted',
'change_your_password' => 'Change your password',
'delete_account' => 'Delete account',
'current_password' => 'Current password',
'new_password' => 'New password',
'new_password_again' => 'New password (again)',
'delete_your_account' => 'Delete your account',
'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, <em>anything</em> you might have saved into Firefly III. It\'ll be GONE.',
'delete_your_account_password' => 'Enter your password to continue.',
'password' => 'Password',
'are_you_sure' => 'Are you sure? You cannot undo this.',
'delete_account_button' => 'DELETE your account',
'invalid_current_password' => 'Invalid current password!',
'password_changed' => 'Password changed!',
'should_change' => 'The idea is to change your password.',
'invalid_password' => 'Invalid password!',
'what_is_pw_security' => 'What is "verify password security"?',
'secure_pw_title' => 'How to choose a secure password',
'secure_pw_history' => 'Not a week goes by that you read in the news about a site losing the passwords of its users. Hackers and thieves use these passwords to try to steal your private information. This information is valuable.',
'secure_pw_ff' => 'Do you use the same password all over the internet? If one site loses your password, hackers have access to all your data. Firefly III relies on you to choose a strong and unique password to protect your financial records.',
'secure_pw_check_box' => 'To help you do that Firefly III can check if the password you want to use has been stolen in the past. If this is the case, Firefly III advises you NOT to use that password.',
'secure_pw_working_title' => 'How does it work?',
'secure_pw_working' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to <a href="https://www.troyhunt.com/introducing-306-million-freely-downloadable-pwned-passwords/">the website of Troy Hunt</a> to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">NIST Special Publication</a> on this subject.',
'secure_pw_should' => 'Should I check the box?',

View File

@@ -27,84 +27,225 @@
<li><a class="text-danger" href="{{ route('profile.delete-account') }}">{{ 'delete_account'|_ }}</a></li>
</ul>
</div>
<div class="col-lg-6">
<p>
{{ 'permanent_delete_stuff'|_ }}
</p>
<ul>
<li><a onclick="return confirm('{{ trans('firefly.are_you_sure')|escape('js') }}');" class="text-danger" href="{{ route('profile.delete-budgets') }}">{{ 'delete_all_budgets'|_ }}</a></li>
<li><a onclick="return confirm('{{ trans('firefly.are_you_sure')|escape('js') }}');" class="text-danger" href="{{ route('profile.delete-categories') }}">{{ 'delete_all_categories'|_ }}</a></li>
<li><a onclick="return confirm('{{ trans('firefly.are_you_sure')|escape('js') }}');" class="text-danger" href="{{ route('profile.delete-tags') }}">{{ 'delete_all_tags'|_ }}</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ 'command_line_token'|_ }}</h3>
</div>
<div class="box-body">
<p>
{{ 'explain_command_line_token'|_ }}
</p>
<p>
<input id="token" type="text" class="form-control" name="token" value="{{ accessToken.data }}" size="32" maxlength="32" readonly/>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ 'command_line_token'|_ }}</h3>
</div>
<div class="box-body">
<p>
{{ 'explain_command_line_token'|_ }}
</p>
<p>
<input id="token" type="text" class="form-control" name="token" value="{{ accessToken.data }}" size="32" maxlength="32" readonly/>
</p>
<p>
<form action="{{ route('profile.regenerate') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<button type="submit" class="btn btn-danger btn-xs"><i class="fa fa-refresh"></i> {{ 'regenerate_command_line_token'|_ }}</button>
</form>
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ 'pref_two_factor_auth'|_ }}</h3>
</div>
<div class="box-body">
<p class="text-info">{{ 'pref_two_factor_auth_help'|_ }}</p>
{% if enabled2FA == true %}
<p class="text-info">
{{ trans_choice('firefly.pref_two_factor_backup_code_count', mfaBackupCount) }}
</p>
<div class="btn-group">
<a class="btn btn-info" href="{{ route('profile.code') }}">
<i class="fa fa-recycle"></i>
{{ 'pref_two_factor_auth_reset_code'|_ }}</a>
<a class="btn btn-default" href="{{ route('profile.new-backup-codes') }}">
<i class="fa fa-star"></i>
{{ 'pref_two_factor_new_backup_codes'|_ }}</a>
<a class="btn btn-danger" href="{{ route('profile.delete-code') }}">
<i class="fa fa-trash"></i>
{{ 'pref_two_factor_auth_disable_2fa'|_ }}</a>
</div>
{% else %}
<p>
<form action="{{ route('profile.regenerate') }}" method="post">
<form action="{{ route('profile.enable2FA') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<button type="submit" class="btn btn-danger btn-xs"><i class="fa fa-refresh"></i> {{ 'regenerate_command_line_token'|_ }}</button>
<button type="submit" class="btn btn-info"><i class="fa fa-lock"></i> {{ 'pref_enable_two_factor_auth'|_ }}</button>
</form>
</p>
{% endif %}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ 'delete_stuff_header'|_ }}</h3>
</div>
<div class="box-header with-border">
<div class="col-lg-12">
<p>
{{ 'permanent_delete_stuff'|_ }}
</p>
<h4>{{ 'financial_control'|_ }}</h4>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_budgets')|escape('html') }}"
data-type="budgets" class="confirm btn btn-danger btn-sm"><i
class="fa fa-pie-chart"></i> {{ 'delete_all_budgets'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_bills')|escape('html') }}"
data-type="bills" class="confirm btn btn-danger btn-sm"><i
class="fa fa-calendar-o"></i> {{ 'delete_all_bills'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_piggy_banks')|escape('html') }}"
data-type="piggy_banks" class="confirm btn btn-danger btn-sm"><i
class="fa fa-bullseye"></i> {{ 'delete_all_piggy_banks'|_ }}</button>
</p>
<h4>{{ 'automation'|_ }}</h4>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_rules')|escape('html') }}"
data-type="rules" class="confirm btn btn-danger btn-sm"><i
class="fa fa-random"></i> {{ 'delete_all_rules'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_recurring')|escape('html') }}"
data-type="recurring" class="confirm btn btn-danger btn-sm"><i
class="fa fa-paint-brush"></i> {{ 'delete_all_recurring'|_ }}</button>
</p>
<h4>{{ 'classification'|_ }}</h4>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_categories')|escape('html') }}"
data-type="categories" class="confirm btn btn-danger btn-sm"><i
class="fa fa-bookmark"></i> {{ 'delete_all_categories'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_tags')|escape('html') }}"
data-type="tags" class="confirm btn btn-danger btn-sm"><i
class="fa fa-tag"></i> {{ 'delete_all_tags'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_object_groups')|escape('html') }}"
data-type="object_groups" class="confirm btn btn-danger btn-sm"><i
class="fa fa-envelope-o"></i> {{ 'delete_all_object_groups'|_ }}</button>
</p>
<h4>{{ 'accounts'|_ }}</h4>
<p>
<em class="text-danger">{{ 'also_delete_transactions'|_ }}</em>
</p>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_accounts')|escape('html') }}"
data-type="accounts" class="confirm btn btn-danger btn-sm"><i
class="fa fa-credit-card"></i> {{ 'delete_all_accounts'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_asset_accounts')|escape('html') }}"
data-type="asset_accounts" class="confirm btn btn-danger btn-sm"><i
class="fa fa-money"></i> {{ 'delete_all_asset_accounts'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_expense_accounts')|escape('html') }}"
data-type="expense_accounts" class="confirm btn btn-danger btn-sm"><i
class="fa fa-shopping-cart"></i> {{ 'delete_all_expense_accounts'|_ }}</button>
</p>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_revenue_accounts')|escape('html') }}"
data-type="revenue_accounts" class="confirm btn btn-danger btn-sm"><i
class="fa fa-download"></i> {{ 'delete_all_revenue_accounts'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_liabilities')|escape('html') }}"
data-type="liabilities" class="confirm btn btn-danger btn-sm"><i
class="fa fa-ticket"></i> {{ 'delete_all_liabilities'|_ }}</button>
</p>
<h4>{{ 'transactions'|_ }}</h4>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_transactions')|escape('html') }}"
data-type="transactions" class="confirm btn btn-danger btn-sm"><i
class="fa fa-exchange"></i> {{ 'delete_all_transactions'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_withdrawals')|escape('html') }}"
data-type="withdrawals" class="confirm btn btn-danger btn-sm"><i
class="fa fa-long-arrow-left"></i> {{ 'delete_all_withdrawals'|_ }}</button>
<button type="button"
data-success="{{ trans('firefly.deleted_all_deposits')|escape('html') }}"
data-type="deposits" class="confirm btn btn-danger btn-sm"><i
class="fa fa-long-arrow-right"></i> {{ 'delete_all_deposits'|_ }}</button>
</p>
<p>
<button type="button"
data-success="{{ trans('firefly.deleted_all_transfers')|escape('html') }}"
data-type="transfers" class="confirm btn btn-danger btn-sm"><i
class="fa fa-exchange"></i> {{ 'delete_all_transfers'|_ }}</button>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ 'pref_two_factor_auth'|_ }}</h3>
</div>
<div class="box-body">
<p class="text-info">{{ 'pref_two_factor_auth_help'|_ }}</p>
{% if enabled2FA == true %}
<p class="text-info">
{{ trans_choice('firefly.pref_two_factor_backup_code_count', mfaBackupCount) }}
</p>
<div class="btn-group">
<a class="btn btn-info" href="{{ route('profile.code') }}">
<i class="fa fa-recycle"></i>
{{ 'pref_two_factor_auth_reset_code'|_ }}</a>
<a class="btn btn-default" href="{{ route('profile.new-backup-codes') }}">
<i class="fa fa-star"></i>
{{ 'pref_two_factor_new_backup_codes'|_ }}</a>
<a class="btn btn-danger" href="{{ route('profile.delete-code') }}">
<i class="fa fa-trash"></i>
{{ 'pref_two_factor_auth_disable_2fa'|_ }}</a>
</div>
{% else %}
<p>
<form action="{{ route('profile.enable2FA') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<button type="submit" class="btn btn-info"><i class="fa fa-lock"></i> {{ 'pref_enable_two_factor_auth'|_ }}</button>
</form>
</p>
{% endif %}
</div>
</div>
</div>
</div>
<div id="passport_clients"></div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" nonce="{{ JS_NONCE }}">
var deleteAPIRoute = '{{ route('api.v1.data.destroy') }}';
var confirmText = '{{ trans('firefly.are_you_sure')|escape('js') }}';
$(document).ready(function () {
$('.confirm').on('click', function (e) {
var link = $(e.currentTarget);
var classes = link.find('i').attr('class');
// replace icon with loading thing
link.prop('disabled', true);
link.find('i').removeClass().addClass('fa fa-spin fa-spinner');
// call API:
$.ajax({
method: 'DELETE',
url: deleteAPIRoute + '?objects=' + link.data('type'),
}).done(
function () {
// enable button again:
link.prop('disabled',false);
link.find('i').removeClass().addClass(classes);
alert(link.data('success'));
}
).fail(function() {
link.find('i').removeClass().addClass('fa fa-exclamation-triangle');
alert('Could not delete. Sorry.');
});
return false;
});
});
</script>
{% endblock %}

View File

@@ -386,6 +386,16 @@ Route::group(
}
);
Route::group(
['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'data',
'as' => 'api.v1.data.',],
static function () {
// Overview API routes:
Route::delete('destroy', ['uses' => 'Data\DestroyController@destroy', 'as' => 'destroy']);
}
);
Route::group(
['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'currencies',
'as' => 'api.v1.currencies.',],

View File

@@ -721,10 +721,6 @@ Route::group(
Route::get('/delete-code', ['uses' => 'ProfileController@deleteCode', 'as' => 'delete-code']);
Route::get('2fa/new-codes', ['uses' => 'ProfileController@newBackupCodes', 'as' => 'new-backup-codes']);
// routes to delete stuff.
Route::get('delete-budgets', ['uses' => 'Profile\DataController@deleteBudgets', 'as' => 'delete-budgets']);
Route::get('delete-categories', ['uses' => 'Profile\DataController@deleteCategories', 'as' => 'delete-categories']);
Route::get('delete-tags', ['uses' => 'Profile\DataController@deleteTags', 'as' => 'delete-tags']);
}
);