diff --git a/app/Http/Controllers/PreferencesController.php b/app/Http/Controllers/PreferencesController.php index 529993a8df..becfd42819 100644 --- a/app/Http/Controllers/PreferencesController.php +++ b/app/Http/Controllers/PreferencesController.php @@ -9,13 +9,16 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); + namespace FireflyIII\Http\Controllers; use FireflyIII\Http\Requests\TokenFormRequest; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\User\UserRepositoryInterface; use Illuminate\Http\Request; +use Log; use PragmaRX\Google2FA\Contracts\Google2FA; use Preferences; use Session; @@ -131,7 +134,7 @@ class PreferencesController extends Controller * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function postIndex(Request $request) + public function postIndex(Request $request, UserRepositoryInterface $repository) { // front page accounts $frontPageAccounts = []; @@ -168,7 +171,7 @@ class PreferencesController extends Controller $twoFactorAuthEnabled = false; $hasTwoFactorAuthSecret = false; - if (!auth()->user()->hasRole('demo')) { + if (!$repository->hasRole(auth()->user(), 'demo')) { // two factor auth $twoFactorAuthEnabled = intval($request->get('twoFactorAuthEnabled')); $hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret')); diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index e2f7516dd8..b816a1e5bd 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -9,14 +9,16 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace FireflyIII\Http\Controllers; use FireflyIII\Exceptions\ValidationException; +use FireflyIII\Http\Middleware\IsLimitedUser; use FireflyIII\Http\Requests\DeleteAccountFormRequest; use FireflyIII\Http\Requests\ProfileFormRequest; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\User; use Hash; use Log; use Session; @@ -45,6 +47,8 @@ class ProfileController extends Controller return $next($request); } ); + $this->middleware(IsLimitedUser::class); + } /** @@ -52,16 +56,6 @@ class ProfileController extends Controller */ public function changePassword() { - if (intval(getenv('SANDSTORM')) === 1) { - return view('error')->with('message', strval(trans('firefly.sandstorm_not_available'))); - } - - if (auth()->user()->hasRole('demo')) { - Session::flash('info', strval(trans('firefly.cannot_change_demo'))); - - return redirect(route('profile.index')); - } - $title = auth()->user()->email; $subTitle = strval(trans('firefly.change_your_password')); $subTitleIcon = 'fa-key'; @@ -74,16 +68,6 @@ class ProfileController extends Controller */ public function deleteAccount() { - if (intval(getenv('SANDSTORM')) === 1) { - return view('error')->with('message', strval(trans('firefly.sandstorm_not_available'))); - } - - if (auth()->user()->hasRole('demo')) { - Session::flash('info', strval(trans('firefly.cannot_delete_demo'))); - - return redirect(route('profile.index')); - } - $title = auth()->user()->email; $subTitle = strval(trans('firefly.delete_account')); $subTitleIcon = 'fa-trash'; @@ -111,32 +95,18 @@ class ProfileController extends Controller */ public function postChangePassword(ProfileFormRequest $request, UserRepositoryInterface $repository) { - if (intval(getenv('SANDSTORM')) === 1) { - return view('error')->with('message', strval(trans('firefly.sandstorm_not_available'))); - } - - if (auth()->user()->hasRole('demo')) { - Session::flash('info', strval(trans('firefly.cannot_change_demo'))); - - return redirect(route('profile.index')); - } - - // old, new1, new2 - if (!Hash::check($request->get('current_password'), auth()->user()->password)) { - Session::flash('error', strval(trans('firefly.invalid_current_password'))); - - return redirect(route('profile.change-password')); - } + // the request has already validated both new passwords must be equal. + $current = $request->get('current_password'); + $new = $request->get('new_password'); try { - $this->validatePassword($request->get('current_password'), $request->get('new_password')); + $this->validatePassword(auth()->user(), $current, $new); } catch (ValidationException $e) { Session::flash('error', $e->getMessage()); return redirect(route('profile.change-password')); } - // update the user with the new password. $repository->changePassword(auth()->user(), $request->get('new_password')); Session::flash('success', strval(trans('firefly.password_changed'))); @@ -151,17 +121,6 @@ class ProfileController extends Controller */ public function postDeleteAccount(UserRepositoryInterface $repository, DeleteAccountFormRequest $request) { - if (intval(getenv('SANDSTORM')) === 1) { - return view('error')->with('message', strval(trans('firefly.sandstorm_not_available'))); - } - - if (auth()->user()->hasRole('demo')) { - Session::flash('info', strval(trans('firefly.cannot_delete_demo'))); - - return redirect(route('profile.index')); - } - - // old, new1, new2 if (!Hash::check($request->get('password'), auth()->user()->password)) { Session::flash('error', strval(trans('firefly.invalid_password'))); @@ -182,15 +141,21 @@ class ProfileController extends Controller } /** - * @param string $old + * @param User $user + * @param string $current * @param string $new + * @param string $newConfirmation * * @return bool * @throws ValidationException */ - protected function validatePassword(string $old, string $new): bool + protected function validatePassword(User $user, string $current, string $new): bool { - if ($new === $old) { + if (!Hash::check($current, auth()->user()->password)) { + throw new ValidationException(strval(trans('firefly.invalid_current_password'))); + } + + if ($current === $new) { throw new ValidationException(strval(trans('firefly.should_change'))); } diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index a3ac8ab74a..92fd5c98cd 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -26,6 +26,7 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Collection; +use Log; use Preferences; use Response; use Session; @@ -73,7 +74,7 @@ class ReportController extends Controller public function auditReport(Collection $accounts, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', trans('firefly.end_after_start_date')); + return view('error')->with('message', trans('firefly.end_after_start_date')); // @codeCoverageIgnore } if ($start < session('first')) { $start = session('first'); @@ -109,7 +110,7 @@ class ReportController extends Controller public function budgetReport(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', trans('firefly.end_after_start_date')); + return view('error')->with('message', trans('firefly.end_after_start_date')); // @codeCoverageIgnore } if ($start < session('first')) { $start = session('first'); @@ -145,7 +146,7 @@ class ReportController extends Controller public function categoryReport(Collection $accounts, Collection $categories, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', trans('firefly.end_after_start_date')); + return view('error')->with('message', trans('firefly.end_after_start_date')); // @codeCoverageIgnore } if ($start < session('first')) { $start = session('first'); @@ -251,10 +252,9 @@ class ReportController extends Controller /** * @param ReportFormRequest $request * - * @return RedirectResponse - * @throws FireflyException + * @return RedirectResponse|\Illuminate\Routing\Redirector */ - public function postIndex(ReportFormRequest $request): RedirectResponse + public function postIndex(ReportFormRequest $request) { // report type: $reportType = $request->get('report_type'); @@ -266,6 +266,7 @@ class ReportController extends Controller $tags = join(',', $request->getTagList()->pluck('tag')->toArray()); if ($request->getAccountList()->count() === 0) { + Log::debug('Account count is zero'); Session::flash('error', trans('firefly.select_more_than_one_account')); return redirect(route('reports.index')); @@ -293,14 +294,7 @@ class ReportController extends Controller return view('error')->with('message', trans('firefly.end_after_start_date')); } - // lower threshold - if ($start < session('first')) { - $start = session('first'); - } - switch ($reportType) { - default: - throw new FireflyException(sprintf('Firefly does not support the "%s"-report yet.', $reportType)); case 'category': $uri = route('reports.report.category', [$accounts, $categories, $start, $end]); break; @@ -332,7 +326,7 @@ class ReportController extends Controller public function tagReport(Collection $accounts, Collection $tags, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', trans('firefly.end_after_start_date')); + return view('error')->with('message', trans('firefly.end_after_start_date')); // @codeCoverageIgnore } if ($start < session('first')) { $start = session('first'); diff --git a/app/Http/Controllers/RuleController.php b/app/Http/Controllers/RuleController.php index cc8e896156..60461e1c53 100644 --- a/app/Http/Controllers/RuleController.php +++ b/app/Http/Controllers/RuleController.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -255,10 +255,11 @@ class RuleController extends Controller Preferences::mark(); if (intval($request->get('create_another')) === 1) { - // set value so create routine will not overwrite URL: + // @codeCoverageIgnoreStart Session::put('rules.create.fromStore', true); return redirect(route('rules.create', [$ruleGroup]))->withInput(); + // @codeCoverageIgnoreEnd } return redirect($this->getPreviousUri('rules.create.uri')); @@ -340,10 +341,11 @@ class RuleController extends Controller Preferences::mark(); if (intval($request->get('return_to_edit')) === 1) { - // set value so edit routine will not overwrite URL: + // @codeCoverageIgnoreStart Session::put('rules.edit.fromUpdate', true); return redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]); + // @codeCoverageIgnoreEnd } return redirect($this->getPreviousUri('rules.edit.uri')); @@ -473,7 +475,7 @@ class RuleController extends Controller $actions[] = view( 'rules.partials.action', [ - 'oldTrigger' => $entry, + 'oldAction' => $entry, 'oldValue' => $request->old('rule-action-value')[$index], 'oldChecked' => $checked, 'count' => $count, @@ -531,7 +533,7 @@ class RuleController extends Controller if (is_array($data['rule-triggers'])) { foreach ($data['rule-triggers'] as $index => $triggerType) { $data['rule-trigger-stop'][$index] = $data['rule-trigger-stop'][$index] ?? 0; - $triggers[] = [ + $triggers[] = [ 'type' => $triggerType, 'value' => $data['rule-trigger-values'][$index], 'stopProcessing' => intval($data['rule-trigger-stop'][$index]) === 1 ? true : false, diff --git a/app/Http/Controllers/RuleGroupController.php b/app/Http/Controllers/RuleGroupController.php index e0bc8b7476..12f9a0bb58 100644 --- a/app/Http/Controllers/RuleGroupController.php +++ b/app/Http/Controllers/RuleGroupController.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -217,10 +217,11 @@ class RuleGroupController extends Controller Preferences::mark(); if (intval($request->get('create_another')) === 1) { - // set value so create routine will not overwrite URL: + // @codeCoverageIgnoreStart Session::put('rule-groups.create.fromStore', true); return redirect(route('rule-groups.create'))->withInput(); + // @codeCoverageIgnoreEnd } return redirect($this->getPreviousUri('rule-groups.create.uri')); @@ -261,10 +262,11 @@ class RuleGroupController extends Controller Preferences::mark(); if (intval($request->get('return_to_edit')) === 1) { - // set value so edit routine will not overwrite URL: + // @codeCoverageIgnoreStart Session::put('rule-groups.edit.fromUpdate', true); return redirect(route('rule-groups.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]); + // @codeCoverageIgnoreEnd } // redirect to previous URL. diff --git a/app/Http/Middleware/IsLimitedUser.php b/app/Http/Middleware/IsLimitedUser.php new file mode 100644 index 0000000000..6b22eccda8 --- /dev/null +++ b/app/Http/Middleware/IsLimitedUser.php @@ -0,0 +1,61 @@ +guest()) { + if ($request->ajax()) { + return response('Unauthorized.', 401); + } + + return redirect()->guest('login'); + } + /** @var User $user */ + $user = auth()->user(); + if ($user->hasRole('demo')) { + Session::flash('warning', strval(trans('firefly.not_available_demo_user'))); + + return redirect(route('index')); + } + + if (intval(getenv('SANDSTORM')) === 1) { + Session::flash('warning', strval(trans('firefly.sandstorm_not_available'))); + + return redirect(route('index')); + } + + return $next($request); + } +} diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index f38a164993..ef8982988c 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -29,6 +29,7 @@ use Google2FA; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Translation\Translator; use Illuminate\Validation\Validator; +use Log; use Session; /** diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 38cea0b744..bb82214b04 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -124,7 +124,7 @@ return [ 'journals_in_period_for_account' => 'All transactions for account :name between :start and :end', 'transferred' => 'Transferred', 'all_withdrawal' => 'All expenses', - 'all_transactions' => 'All transactions', + 'all_transactions' => 'All transactions', 'title_withdrawal_between' => 'All expenses between :start and :end', 'all_deposit' => 'All revenue', 'title_deposit_between' => 'All revenue between :start and :end', @@ -134,6 +134,7 @@ return [ 'title_transfer_between' => 'All transfers between :start and :end', 'all_journals_for_category' => 'All transactions for category :name', 'journals_in_period_for_category' => 'All transactions for category :name between :start and :end', + 'not_available_demo_user' => 'The feature you try to access is not available to demo users.', // repeat frequencies: diff --git a/resources/views/rules/partials/action.twig b/resources/views/rules/partials/action.twig index f7e7a0886d..a9927e7e15 100644 --- a/resources/views/rules/partials/action.twig +++ b/resources/views/rules/partials/action.twig @@ -10,11 +10,7 @@ diff --git a/tests/Feature/Controllers/PreferencesControllerTest.php b/tests/Feature/Controllers/PreferencesControllerTest.php index bb23853f60..ca74cb177e 100644 --- a/tests/Feature/Controllers/PreferencesControllerTest.php +++ b/tests/Feature/Controllers/PreferencesControllerTest.php @@ -7,7 +7,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Tests\Feature\Controllers; @@ -15,8 +15,10 @@ use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\User\UserRepositoryInterface; use Illuminate\Support\Collection; use PragmaRX\Google2FA\Contracts\Google2FA; +use Preferences; use Tests\TestCase; /** @@ -81,6 +83,34 @@ class PreferencesControllerTest extends TestCase $response->assertSee('