From d63c9c9aeae1746f7c02c1d0db451c949ab835d0 Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 8 Feb 2019 07:13:59 +0100 Subject: [PATCH] Add audit logging. --- .../Controllers/Account/CreateController.php | 4 +-- app/Http/Controllers/CurrencyController.php | 34 +++++++++++++++---- app/Http/Controllers/HomeController.php | 3 ++ app/Support/Logging/AuditLogger.php | 23 +++++++++++++ app/Support/Logging/AuditProcessor.php | 28 +++++++++++++++ config/logging.php | 10 +++++- 6 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 app/Support/Logging/AuditLogger.php create mode 100644 app/Support/Logging/AuditProcessor.php diff --git a/app/Http/Controllers/Account/CreateController.php b/app/Http/Controllers/Account/CreateController.php index 02c32fb94b..50bf7ac4ac 100644 --- a/app/Http/Controllers/Account/CreateController.php +++ b/app/Http/Controllers/Account/CreateController.php @@ -111,7 +111,7 @@ class CreateController extends Controller $this->rememberPreviousUri('accounts.create.uri'); } $request->session()->forget('accounts.create.fromStore'); - + Log::channel('audit')->info('Create new account.'); return view('accounts.create', compact('subTitleIcon', 'what', 'interestPeriods', 'subTitle', 'roles', 'liabilityTypes')); } @@ -131,7 +131,7 @@ class CreateController extends Controller $request->session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name])); app('preferences')->mark(); - + Log::channel('audit')->info('Store new account.', $data); // update preferences if necessary: $frontPage = app('preferences')->get('frontPageAccounts', [])->data; diff --git a/app/Http/Controllers/CurrencyController.php b/app/Http/Controllers/CurrencyController.php index 4c72b09e3e..dda6f02d1f 100644 --- a/app/Http/Controllers/CurrencyController.php +++ b/app/Http/Controllers/CurrencyController.php @@ -91,6 +91,8 @@ class CurrencyController extends Controller } $request->session()->forget('currencies.create.fromStore'); + Log::channel('audit')->info('Create new currency.'); + return view('currencies.create', compact('subTitleIcon', 'subTitle')); } @@ -107,6 +109,8 @@ class CurrencyController extends Controller app('preferences')->set('currencyPreference', $currency->code); app('preferences')->mark(); + Log::channel('audit')->info(sprintf('Make %s the default currency.', $currency->code)); + $this->repository->enable($currency); $request->session()->flash('success', (string)trans('firefly.new_default_currency', ['name' => $currency->name])); @@ -128,6 +132,7 @@ class CurrencyController extends Controller if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); + Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but is not site owner.', $currency->code)); return redirect(route('currencies.index')); // @codeCoverageIgnoreEnd @@ -135,6 +140,7 @@ class CurrencyController extends Controller if ($this->repository->currencyInUse($currency)) { $request->session()->flash('error', (string)trans('firefly.cannot_delete_currency', ['name' => $currency->name])); + Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code)); return redirect(route('currencies.index')); } @@ -142,6 +148,7 @@ class CurrencyController extends Controller // put previous url in session $this->rememberPreviousUri('currencies.delete.uri'); $subTitle = (string)trans('form.delete_currency', ['name' => $currency->name]); + Log::channel('audit')->info(sprintf('Visit page to delete currency %s.', $currency->code)); return view('currencies.delete', compact('currency', 'subTitle')); } @@ -161,6 +168,7 @@ class CurrencyController extends Controller if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); + Log::channel('audit')->info(sprintf('Tried to delete currency %s but is not site owner.', $currency->code)); return redirect(route('currencies.index')); // @codeCoverageIgnoreEnd @@ -168,11 +176,13 @@ class CurrencyController extends Controller if ($this->repository->currencyInUse($currency)) { $request->session()->flash('error', (string)trans('firefly.cannot_delete_currency', ['name' => $currency->name])); + Log::channel('audit')->info(sprintf('Tried to delete currency %s but is in use.', $currency->code)); return redirect(route('currencies.index')); } - + Log::channel('audit')->info(sprintf('Deleted currency %s.', $currency->code)); $this->repository->destroy($currency); + $request->session()->flash('success', (string)trans('firefly.deleted_currency', ['name' => $currency->name])); return redirect($this->getPreviousUri('currencies.delete.uri')); @@ -193,6 +203,7 @@ class CurrencyController extends Controller if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); + Log::channel('audit')->info(sprintf('Tried to disable currency %s but is not site owner.', $currency->code)); return redirect(route('currencies.index')); // @codeCoverageIgnoreEnd @@ -200,20 +211,23 @@ class CurrencyController extends Controller if ($this->repository->currencyInUse($currency)) { $request->session()->flash('error', (string)trans('firefly.cannot_disable_currency', ['name' => $currency->name])); + Log::channel('audit')->info(sprintf('Tried to disable currency %s but is in use.', $currency->code)); return redirect(route('currencies.index')); } $this->repository->disable($currency); - + Log::channel('audit')->info(sprintf('Disabled currency %s.', $currency->code)); // if no currencies are enabled, enable the first one in the DB (usually the EUR) if (0 === $this->repository->get()->count()) { + /** @var TransactionCurrency $first */ $first = $this->repository->getAll()->first(); if (null === $first) { throw new FireflyException('No currencies found.'); } + Log::channel('audit')->info(sprintf('Auto-enabled currency %s.', $first->code)); $this->repository->enable($first); - app('preferences')->set('currencyPreference', $currency->code); + app('preferences')->set('currencyPreference', $first->code); app('preferences')->mark(); } @@ -237,6 +251,7 @@ class CurrencyController extends Controller if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); + Log::channel('audit')->info(sprintf('Tried to edit currency %s but is not owner.', $currency->code)); return redirect(route('currencies.index')); // @codeCoverageIgnoreEnd @@ -275,6 +290,7 @@ class CurrencyController extends Controller $this->repository->enable($currency); session()->flash('success', (string)trans('firefly.currency_is_now_enabled', ['name' => $currency->name])); + Log::channel('audit')->info(sprintf('Enabled currency %s.', $currency->code)); return redirect(route('currencies.index')); } @@ -329,21 +345,23 @@ class CurrencyController extends Controller { /** @var User $user */ $user = auth()->user(); + $data = $request->getCurrencyData(); if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart Log::error('User ' . auth()->user()->id . ' is not admin, but tried to store a currency.'); + Log::channel('audit')->info('Tried to create (POST) currency without admin rights.', $data); return redirect($this->getPreviousUri('currencies.create.uri')); // @codeCoverageIgnoreEnd } - $data = $request->getCurrencyData(); $data['enabled'] = true; $currency = $this->repository->store($data); $redirect = redirect($this->getPreviousUri('currencies.create.uri')); + if (null !== $currency) { $request->session()->flash('success', (string)trans('firefly.created_currency', ['name' => $currency->name])); - + Log::channel('audit')->info('Created (POST) currency.', $data); if (1 === (int)$request->get('create_another')) { // @codeCoverageIgnoreStart $request->session()->put('currencies.create.fromStore', true); @@ -353,6 +371,7 @@ class CurrencyController extends Controller } } if (null === $currency) { + Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data); $request->session()->flash('error', (string)trans('firefly.could_not_store_currency')); } @@ -372,16 +391,19 @@ class CurrencyController extends Controller { /** @var User $user */ $user = auth()->user(); + $data = $request->getCurrencyData(); if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); + Log::channel('audit')->info('Tried to update (POST) currency without admin rights.', $data); return redirect(route('currencies.index')); // @codeCoverageIgnoreEnd } - $data = $request->getCurrencyData(); + $currency = $this->repository->update($currency, $data); + Log::channel('audit')->info('Updated (POST) currency.', $data); $request->session()->flash('success', (string)trans('firefly.updated_currency', ['name' => $currency->name])); app('preferences')->mark(); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 804deca82b..703e53aa53 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -67,6 +67,7 @@ class HomeController extends Controller Log::debug('Received dateRange', ['start' => $request->get('start'), 'end' => $request->get('end'), 'label' => $request->get('label')]); + // check if the label is "everything" or "Custom range" which will betray // a possible problem with the budgets. if ($label === (string)trans('firefly.everything') || $label === (string)trans('firefly.customRange')) { @@ -103,6 +104,8 @@ class HomeController extends Controller $types = config('firefly.accountTypesByIdentifier.asset'); $count = $repository->count($types); + Log::channel('audit')->info('User visits homepage.'); + if (0 === $count) { return redirect(route('new-user.index')); } diff --git a/app/Support/Logging/AuditLogger.php b/app/Support/Logging/AuditLogger.php new file mode 100644 index 0000000000..3c98651b85 --- /dev/null +++ b/app/Support/Logging/AuditLogger.php @@ -0,0 +1,23 @@ +pushProcessor($processor); + } +} \ No newline at end of file diff --git a/app/Support/Logging/AuditProcessor.php b/app/Support/Logging/AuditProcessor.php new file mode 100644 index 0000000000..84fb2c4b86 --- /dev/null +++ b/app/Support/Logging/AuditProcessor.php @@ -0,0 +1,28 @@ +method() . ':' . request()->url(); + + $record['extra']['IP'] = app('request')->ip(); + if (auth()->check()) { + $record['extra']['user'] = auth()->user()->email; + } + + + return $record; + } +} \ No newline at end of file diff --git a/config/logging.php b/config/logging.php index 1ac3fb0284..f031506d13 100644 --- a/config/logging.php +++ b/config/logging.php @@ -19,7 +19,9 @@ * along with Firefly III. If not, see . */ + declare(strict_types=1); +use FireflyIII\Support\Logging\AuditLogger; return [ @@ -66,13 +68,19 @@ return [ 'path' => 'php://stdout', 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), ], - 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/ff3-' . PHP_SAPI . '.log'), 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), 'days' => 7, ], + 'audit' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/ff3-audit.log'), + 'tap' => [AuditLogger::class], + 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), + 'days' => 90, + ], 'dailytest' => [ 'driver' => 'daily', 'path' => storage_path('logs/test-ff3-' . PHP_SAPI . '.log'),