This commit is contained in:
Bubka 2021-10-15 23:46:21 +02:00
parent 9e899aab53
commit 5db549fe5e
14 changed files with 81 additions and 13 deletions

View File

@ -39,7 +39,7 @@ IS_DEMO_APP=false
# The log channel defines where your log entries go to. # The log channel defines where your log entries go to.
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. # 'daily' is the default logging mode giving you 7 daily rotated log files in /storage/logs/.
# Several other options exist. You can use 'single' for one big fat error log (not recommended). # Several other options exist. You can use 'single' for one big fat error log (not recommended).
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.

View File

@ -7,6 +7,7 @@
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Log;
class FixUnsplittedAccounts extends Command class FixUnsplittedAccounts extends Command
{ {

View File

@ -3,6 +3,7 @@
namespace App; namespace App;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
class Group extends Model class Group extends Model
{ {
@ -56,6 +57,10 @@ protected static function boot()
['group_id' => NULL] ['group_id' => NULL]
); );
}); });
static::deleted(function ($model) {
Log::info(sprintf('Group %s deleted', var_export($model->name, true)));
});
} }

View File

@ -4,6 +4,7 @@
use Closure; use Closure;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
class AvoidPasswordResetInDemo class AvoidPasswordResetInDemo
{ {
@ -18,7 +19,9 @@ public function handle($request, Closure $next)
{ {
if( config('2fauth.config.isDemoApp') ) { if( config('2fauth.config.isDemoApp') ) {
return response()->json(['requestFailed' => __('auth.forms.no_reset_password_in_demo')], Response::HTTP_UNAUTHORIZED); Log::notice('Cannot request a password reset in Demo mode');
return response()->json(['message' => __('auth.forms.no_reset_password_in_demo')], Response::HTTP_UNAUTHORIZED);
} }
return $next($request); return $next($request);

View File

@ -7,6 +7,7 @@
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class LogoutInactiveUser class LogoutInactiveUser
{ {
@ -50,6 +51,8 @@ public function handle($request, Closure $next)
$accessToken->revoke(); $accessToken->revoke();
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
Log::notice('Inactive user detected, access token revoked');
return response()->json(['message' => 'unauthorised'], Response::HTTP_UNAUTHORIZED); return response()->json(['message' => 'unauthorised'], Response::HTTP_UNAUTHORIZED);
} }

View File

@ -4,6 +4,7 @@
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class AppstractOptionsService implements SettingServiceInterface class AppstractOptionsService implements SettingServiceInterface
{ {
@ -47,6 +48,10 @@ public function set($setting, $value = null) : void
} }
option($settings); option($settings);
foreach ($settings as $setting => $value) {
Log::info(sprintf('Setting %s is now %s', var_export($setting, true), var_export($this->restoreType($value), true)));
}
} }
@ -56,6 +61,8 @@ public function set($setting, $value = null) : void
public function delete(string $name) : void public function delete(string $name) : void
{ {
option()->remove($name); option()->remove($name);
Log::info(sprintf('Setting %s deleted', var_export($name, true)));
} }

View File

@ -4,12 +4,11 @@
use Throwable; use Throwable;
use Exception; use Exception;
use App\TwoFAccount;
use App\Exceptions\DbEncryptionException; use App\Exceptions\DbEncryptionException;
use App\Services\SettingServiceInterface; use App\Services\SettingServiceInterface;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log;
class DbEncryptionService class DbEncryptionService
{ {
@ -44,8 +43,14 @@ public function setTo(bool $state) : void
if ($isInUse === !$state) { if ($isInUse === !$state) {
if ($this->updateRecords($state)) { if ($this->updateRecords($state)) {
$this->settingService->set('useEncryption', $state); $this->settingService->set('useEncryption', $state);
if ($state) {
Log::notice('Sensible data are now encrypted');
}
else Log::notice('Sensible data are now decrypted');
} }
else { else {
Log::warning('Some data cannot be encrypted/decrypted, the useEncryption setting remain unchanged');
throw new DbEncryptionException($state === true ? __('errors.error_during_encryption') : __('errors.error_during_decryption')); throw new DbEncryptionException($state === true ? __('errors.error_during_encryption') : __('errors.error_during_decryption'));
} }
} }
@ -69,7 +74,7 @@ private function updateRecords(bool $encrypted) : bool
$item->account = $encrypted ? Crypt::encryptString($item->account) : Crypt::decryptString($item->account); $item->account = $encrypted ? Crypt::encryptString($item->account) : Crypt::decryptString($item->account);
$item->secret = $encrypted ? Crypt::encryptString($item->secret) : Crypt::decryptString($item->secret); $item->secret = $encrypted ? Crypt::encryptString($item->secret) : Crypt::decryptString($item->secret);
} }
catch (Exception $e) { catch (Exception $ex) {
$success = false; $success = false;
// Exit the each iteration // Exit the each iteration
return false; return false;
@ -97,9 +102,8 @@ private function updateRecords(bool $encrypted) : bool
} }
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
// Dont now how to fake that :( // Dont now how to fake that :(
catch (Throwable $e) { catch (Throwable $ex) {
DB::rollBack(); DB::rollBack();
return false; return false;
} }
} }

View File

@ -6,6 +6,7 @@
use App\TwoFAccount; use App\TwoFAccount;
use App\Services\SettingServiceInterface; use App\Services\SettingServiceInterface;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Log;
class GroupService class GroupService
{ {
@ -68,6 +69,8 @@ public function create(array $data) : Group
$group->save(); $group->save();
Log::info(sprintf('Group %s created', var_export($group->name, true)));
return $group; return $group;
} }
@ -85,6 +88,8 @@ public function update(Group $group, array $data) : Group
'name' => $data['name'], 'name' => $data['name'],
]); ]);
Log::info(sprintf('Group %s updated', var_export($group->name, true)));
return $group; return $group;
} }
@ -118,6 +123,8 @@ public function delete($ids) : int
$deleted = Group::destroy($ids); $deleted = Group::destroy($ids);
Log::info(sprintf('Groups #%s deleted', implode(',#', $ids)));
return $deleted; return $deleted;
} }
@ -144,7 +151,10 @@ public function assign($ids, Group $group = null) : void
$twofaccounts = TwoFAccount::find($ids); $twofaccounts = TwoFAccount::find($ids);
$group->twofaccounts()->saveMany($twofaccounts); $group->twofaccounts()->saveMany($twofaccounts);
Log::info(sprintf('Twofaccounts #%s assigned to groups %s', implode(',#', $ids), var_export($group->name, true)));
} }
else Log::info('Cannot find a group to assign the TwoFAccounts to');
} }

View File

@ -5,6 +5,7 @@
use App\TwoFAccount; use App\TwoFAccount;
use Zxing\QrReader; use Zxing\QrReader;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use chillerlan\QRCode\{QRCode, QROptions}; use chillerlan\QRCode\{QRCode, QROptions};
class QrCodeService class QrCodeService
@ -36,6 +37,8 @@ public function encode(string $data)
$qrcode = new QRCode($options); $qrcode = new QRCode($options);
Log::info('data encoded to QR code');
return $qrcode->render($data); return $qrcode->render($data);
} }
@ -53,6 +56,8 @@ public function decode(\Illuminate\Http\UploadedFile $file)
if(!$data) { if(!$data) {
throw new \App\Exceptions\InvalidQrCodeException; throw new \App\Exceptions\InvalidQrCodeException;
} }
Log::info('QR code decoded');
return $data; return $data;
} }

View File

@ -14,6 +14,7 @@
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
class TwoFAccountService class TwoFAccountService
@ -59,7 +60,11 @@ public function createFromUri(string $uri, bool $saveToDB = true ) : TwoFAccount
$twofaccount->legacy_uri = $uri; $twofaccount->legacy_uri = $uri;
$this->fillWithToken($twofaccount); $this->fillWithToken($twofaccount);
if ( $saveToDB ) $twofaccount->save(); if ( $saveToDB ) {
$twofaccount->save();
Log::info(sprintf('TwoFAccount #%d created (from URI)', $twofaccount->id));
}
return $twofaccount; return $twofaccount;
} }
@ -84,7 +89,11 @@ public function createFromParameters(array $data, bool $saveToDB = true) : TwoFA
$twofaccount->icon = Arr::get($data, 'icon', null); $twofaccount->icon = Arr::get($data, 'icon', null);
$this->fillWithToken($twofaccount); $this->fillWithToken($twofaccount);
if ( $saveToDB ) $twofaccount->save(); if ( $saveToDB ) {
$twofaccount->save();
Log::info(sprintf('TwoFAccount #%d created (from parameters)', $twofaccount->id));
}
return $twofaccount; return $twofaccount;
} }
@ -107,6 +116,8 @@ public function update(TwoFAccount $twofaccount, array $data) : TwoFAccount
$twofaccount->icon = Arr::get($data, 'icon', null); $twofaccount->icon = Arr::get($data, 'icon', null);
$twofaccount->save(); $twofaccount->save();
Log::info(sprintf('TwoFAccount #%d updated', $twofaccount->id));
return $twofaccount; return $twofaccount;
} }
@ -128,6 +139,8 @@ public function getOTP($data) : OtpDto
// Early exit if the model returned an undecipherable secret // Early exit if the model returned an undecipherable secret
if (strtolower($this->token->getSecret()) === __('errors.indecipherable')) { if (strtolower($this->token->getSecret()) === __('errors.indecipherable')) {
Log::error('Secret cannot be deciphered, OTP generation aborted');
throw new UndecipherableException(); throw new UndecipherableException();
} }
@ -154,6 +167,8 @@ public function getOTP($data) : OtpDto
throw new InvalidSecretException($ex->getMessage()); throw new InvalidSecretException($ex->getMessage());
} }
Log::info(sprintf('New %s generated', $OtpDto->otp_type));
return $OtpDto; return $OtpDto;
} }
@ -190,7 +205,10 @@ public function withdraw($ids) : void
->update( ->update(
['group_id' => NULL] ['group_id' => NULL]
); );
Log::info(sprintf('TwoFAccounts #%s withdrawn', implode(',#', $ids)));
} }
else Log::info('No TwoFAccount to withdraw');
} }
@ -321,7 +339,7 @@ private function initTokenWithUri(string $uri) : void
try { try {
$this->token = Factory::loadFromProvisioningUri($uri); $this->token = Factory::loadFromProvisioningUri($uri);
} }
catch (\Assert\AssertionFailedException|\Assert\InvalidArgumentException|\Exception|\Throwable $e) { catch (\Assert\AssertionFailedException|\Assert\InvalidArgumentException|\Exception|\Throwable $ex) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'uri' => __('validation.custom.uri.regex', ['attribute' => 'uri']) 'uri' => __('validation.custom.uri.regex', ['attribute' => 'uri'])
]); ]);
@ -330,6 +348,8 @@ private function initTokenWithUri(string $uri) : void
// As loadFromProvisioningUri() accept URI without label (nor account nor service) we check // As loadFromProvisioningUri() accept URI without label (nor account nor service) we check
// that the account is set // that the account is set
if ( ! $this->token->getLabel() ) { if ( ! $this->token->getLabel() ) {
Log::error('URI passed to initTokenWithUri() must contain a label');
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'label' => __('validation.custom.label.required') 'label' => __('validation.custom.label.required')
]); ]);
@ -347,6 +367,8 @@ private function initTokenWithParameters(TwoFAccountDto $dto) : void
{ {
// Check OTP type again to ensure the upcoming OTPHP instanciation // Check OTP type again to ensure the upcoming OTPHP instanciation
if ( ! in_array($dto->otp_type, $this->supportedOtpTypes, true) ) { if ( ! in_array($dto->otp_type, $this->supportedOtpTypes, true) ) {
Log::error(sprintf('%s is not an OTP type supported by the current token', $dto->otp_type));
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'otp_type' => __('validation.custom.otp_type.in', ['attribute' => 'otp type']) 'otp_type' => __('validation.custom.otp_type.in', ['attribute' => 'otp type'])
]); ]);
@ -431,6 +453,8 @@ private function storeTokenImageAsIcon()
{ {
// Should be a valid image // Should be a valid image
Storage::move($imageFile, $iconFile); Storage::move($imageFile, $iconFile);
Log::info(sprintf('Icon file %s stored', $newFilename));
} }
else { else {
Storage::delete($imageFile); Storage::delete($imageFile);

View File

@ -9,6 +9,7 @@
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
class TwoFAccount extends Model implements Sortable class TwoFAccount extends Model implements Sortable
{ {
@ -66,6 +67,7 @@ protected static function boot()
parent::boot(); parent::boot();
static::deleted(function ($model) { static::deleted(function ($model) {
Log::info(sprintf('TwoFAccount #%d deleted', $model->id));
Storage::delete('public/icons/' . $model->icon); Storage::delete('public/icons/' . $model->icon);
}); });
} }
@ -193,7 +195,7 @@ private function decryptOrReturn($value)
try { try {
return Crypt::decryptString($value); return Crypt::decryptString($value);
} }
catch (Exception $e) { catch (Exception $ex) {
return __('errors.indecipherable'); return __('errors.indecipherable');
} }
} }

View File

@ -7,6 +7,7 @@
use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens; use Laravel\Passport\HasApiTokens;
use Illuminate\Support\Facades\Log;
class User extends Authenticatable class User extends Authenticatable
{ {
@ -48,6 +49,8 @@ class User extends Authenticatable
public function sendPasswordResetNotification($token) public function sendPasswordResetNotification($token)
{ {
$this->notify(new ResetPassword($token)); $this->notify(new ResetPassword($token));
Log::info('Password reset token sent');
} }
/** /**

View File

@ -50,7 +50,7 @@
'driver' => 'daily', 'driver' => 'daily',
'path' => storage_path('logs/laravel.log'), 'path' => storage_path('logs/laravel.log'),
'level' => 'debug', 'level' => 'debug',
'days' => 14, 'days' => 7,
], ],
'slack' => [ 'slack' => [

View File

@ -5,6 +5,7 @@
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
class SplitTwofaccountsUriInMultipleColumns extends Migration class SplitTwofaccountsUriInMultipleColumns extends Migration
{ {
@ -50,7 +51,7 @@ public function up()
} }
catch(Exception $ex) catch(Exception $ex)
{ {
// We leave the record as is Log::error($ex->getMessage());
} }
} }
} }