mirror of
https://github.com/Bubka/2FAuth.git
synced 2024-11-22 08:13:11 +01:00
Apply Laravel Pint fixes
This commit is contained in:
parent
d84dd6659e
commit
d6fd8e3c52
@ -2,18 +2,16 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Controllers;
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\Group;
|
|
||||||
use App\Facades\Groups;
|
|
||||||
use App\Api\v1\Requests\GroupStoreRequest;
|
|
||||||
use App\Api\v1\Requests\GroupAssignRequest;
|
use App\Api\v1\Requests\GroupAssignRequest;
|
||||||
|
use App\Api\v1\Requests\GroupStoreRequest;
|
||||||
use App\Api\v1\Resources\GroupResource;
|
use App\Api\v1\Resources\GroupResource;
|
||||||
use App\Api\v1\Resources\TwoFAccountCollection;
|
use App\Api\v1\Resources\TwoFAccountCollection;
|
||||||
|
use App\Facades\Groups;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\App;
|
use App\Models\Group;
|
||||||
|
|
||||||
class GroupController extends Controller
|
class GroupController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
@ -26,7 +24,6 @@ public function index()
|
|||||||
return GroupResource::collection($groups);
|
return GroupResource::collection($groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*
|
*
|
||||||
@ -44,7 +41,6 @@ public function store(GroupStoreRequest $request)
|
|||||||
->setStatusCode(201);
|
->setStatusCode(201);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
@ -56,7 +52,6 @@ public function show(Group $group)
|
|||||||
return new GroupResource($group);
|
return new GroupResource($group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
@ -71,10 +66,8 @@ public function update(GroupStoreRequest $request, Group $group)
|
|||||||
Groups::update($group, $validated);
|
Groups::update($group, $validated);
|
||||||
|
|
||||||
return new GroupResource($group);
|
return new GroupResource($group);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associate the specified accounts with the group
|
* Associate the specified accounts with the group
|
||||||
*
|
*
|
||||||
@ -89,10 +82,8 @@ public function assignAccounts(GroupAssignRequest $request, Group $group)
|
|||||||
Groups::assign($validated['ids'], $group);
|
Groups::assign($validated['ids'], $group);
|
||||||
|
|
||||||
return new GroupResource($group);
|
return new GroupResource($group);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get accounts assign to the group
|
* Get accounts assign to the group
|
||||||
*
|
*
|
||||||
@ -104,10 +95,8 @@ public function accounts(Group $group)
|
|||||||
$twofaccounts = Groups::getAccounts($group);
|
$twofaccounts = Groups::getAccounts($group);
|
||||||
|
|
||||||
return new TwoFAccountCollection($twofaccounts);
|
return new TwoFAccountCollection($twofaccounts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
@ -120,5 +109,4 @@ public function destroy(Group $group)
|
|||||||
|
|
||||||
return response()->json(null, 204);
|
return response()->json(null, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Controllers;
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\LogoService;
|
use App\Services\LogoService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class IconController extends Controller
|
class IconController extends Controller
|
||||||
{
|
{
|
||||||
@ -31,7 +30,6 @@ public function upload(Request $request)
|
|||||||
: response()->json(['message' => __('errors.file_upload_failed')], 500);
|
: response()->json(['message' => __('errors.file_upload_failed')], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a logo
|
* Fetch a logo
|
||||||
*
|
*
|
||||||
@ -52,7 +50,6 @@ public function fetch(Request $request)
|
|||||||
: response()->json(null, 204);
|
: response()->json(null, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* delete an icon
|
* delete an icon
|
||||||
*
|
*
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Controllers;
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
use App\Facades\QrCode;
|
|
||||||
use App\Api\v1\Requests\QrCodeDecodeRequest;
|
use App\Api\v1\Requests\QrCodeDecodeRequest;
|
||||||
|
use App\Facades\QrCode;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
|
||||||
class QrCodeController extends Controller
|
class QrCodeController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a QR code image
|
* Show a QR code image
|
||||||
*
|
*
|
||||||
@ -24,7 +22,6 @@ public function show(TwoFAccount $twofaccount)
|
|||||||
return response()->json(['qrcode' => QrCode::encode($uri)], 200);
|
return response()->json(['qrcode' => QrCode::encode($uri)], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode an uploaded QR Code image
|
* Decode an uploaded QR Code image
|
||||||
*
|
*
|
||||||
@ -39,5 +36,4 @@ public function decode(QrCodeDecodeRequest $request)
|
|||||||
? response()->json(['data' => QrCode::decode($file)], 200)
|
? response()->json(['data' => QrCode::decode($file)], 200)
|
||||||
: response()->json(['message' => __('errors.file_upload_failed')], 500);
|
: response()->json(['message' => __('errors.file_upload_failed')], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Controllers;
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Facades\Settings;
|
|
||||||
use App\Api\v1\Requests\SettingStoreRequest;
|
use App\Api\v1\Requests\SettingStoreRequest;
|
||||||
use App\Api\v1\Requests\SettingUpdateRequest;
|
use App\Api\v1\Requests\SettingUpdateRequest;
|
||||||
|
use App\Facades\Settings;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
|
||||||
class SettingController extends Controller
|
class SettingController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -22,14 +21,13 @@ public function index()
|
|||||||
$settings->each(function (mixed $item, string $key) use ($settingsResources) {
|
$settings->each(function (mixed $item, string $key) use ($settingsResources) {
|
||||||
$settingsResources->push([
|
$settingsResources->push([
|
||||||
'key' => $key,
|
'key' => $key,
|
||||||
'value' => $item
|
'value' => $item,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return response()->json($settingsResources->all(), 200);
|
return response()->json($settingsResources->all(), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a setting
|
* Display a setting
|
||||||
*
|
*
|
||||||
@ -46,11 +44,10 @@ public function show($settingName)
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'key' => $settingName,
|
'key' => $settingName,
|
||||||
'value' => $setting
|
'value' => $setting,
|
||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a setting
|
* Store a setting
|
||||||
*
|
*
|
||||||
@ -65,11 +62,10 @@ public function store(SettingStoreRequest $request)
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'key' => $validated['key'],
|
'key' => $validated['key'],
|
||||||
'value' => $validated['value']
|
'value' => $validated['value'],
|
||||||
], 201);
|
], 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a setting
|
* Update a setting
|
||||||
*
|
*
|
||||||
@ -84,12 +80,10 @@ public function update(SettingUpdateRequest $request, string $settingName)
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'key' => $settingName,
|
'key' => $settingName,
|
||||||
'value' => $validated['value']
|
'value' => $validated['value'],
|
||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a setting
|
* Delete a setting
|
||||||
*
|
*
|
||||||
@ -105,10 +99,10 @@ public function destroy(string $settingName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
$optionsConfig = config('2fauth.options');
|
$optionsConfig = config('2fauth.options');
|
||||||
if(array_key_exists($settingName, $optionsConfig)) {
|
if (array_key_exists($settingName, $optionsConfig)) {
|
||||||
return response()->json(
|
return response()->json(
|
||||||
['message' => 'bad request',
|
['message' => 'bad request',
|
||||||
'reason' => [__('errors.delete_user_setting_only')]
|
'reason' => [__('errors.delete_user_setting_only')],
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,5 +110,4 @@ public function destroy(string $settingName)
|
|||||||
|
|
||||||
return response()->json(null, 204);
|
return response()->json(null, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,25 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Controllers;
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\TwoFAccount;
|
use App\Api\v1\Requests\TwoFAccountBatchRequest;
|
||||||
|
use App\Api\v1\Requests\TwoFAccountDynamicRequest;
|
||||||
|
use App\Api\v1\Requests\TwoFAccountImportRequest;
|
||||||
use App\Api\v1\Requests\TwoFAccountReorderRequest;
|
use App\Api\v1\Requests\TwoFAccountReorderRequest;
|
||||||
use App\Api\v1\Requests\TwoFAccountStoreRequest;
|
use App\Api\v1\Requests\TwoFAccountStoreRequest;
|
||||||
use App\Api\v1\Requests\TwoFAccountUpdateRequest;
|
use App\Api\v1\Requests\TwoFAccountUpdateRequest;
|
||||||
use App\Api\v1\Requests\TwoFAccountImportRequest;
|
|
||||||
use App\Api\v1\Requests\TwoFAccountBatchRequest;
|
|
||||||
use App\Api\v1\Requests\TwoFAccountUriRequest;
|
use App\Api\v1\Requests\TwoFAccountUriRequest;
|
||||||
use App\Api\v1\Requests\TwoFAccountDynamicRequest;
|
|
||||||
use App\Api\v1\Resources\TwoFAccountCollection;
|
use App\Api\v1\Resources\TwoFAccountCollection;
|
||||||
use App\Api\v1\Resources\TwoFAccountReadResource;
|
use App\Api\v1\Resources\TwoFAccountReadResource;
|
||||||
use App\Api\v1\Resources\TwoFAccountStoreResource;
|
use App\Api\v1\Resources\TwoFAccountStoreResource;
|
||||||
use App\Facades\Groups;
|
use App\Facades\Groups;
|
||||||
use App\Facades\TwoFAccounts;
|
use App\Facades\TwoFAccounts;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
class TwoFAccountController extends Controller
|
class TwoFAccountController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all resources
|
* List all resources
|
||||||
*
|
*
|
||||||
@ -32,12 +31,10 @@ public function index(Request $request)
|
|||||||
return new TwoFAccountCollection(TwoFAccount::ordered()->get());
|
return new TwoFAccountCollection(TwoFAccount::ordered()->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a 2FA account
|
* Display a 2FA account
|
||||||
*
|
*
|
||||||
* @param \App\Models\TwoFAccount $twofaccount
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
*
|
|
||||||
* @return \App\Api\v1\Resources\TwoFAccountReadResource
|
* @return \App\Api\v1\Resources\TwoFAccountReadResource
|
||||||
*/
|
*/
|
||||||
public function show(TwoFAccount $twofaccount)
|
public function show(TwoFAccount $twofaccount)
|
||||||
@ -45,7 +42,6 @@ public function show(TwoFAccount $twofaccount)
|
|||||||
return new TwoFAccountReadResource($twofaccount);
|
return new TwoFAccountReadResource($twofaccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a new 2FA account
|
* Store a new 2FA account
|
||||||
*
|
*
|
||||||
@ -65,8 +61,7 @@ public function store(TwoFAccountDynamicRequest $request)
|
|||||||
|
|
||||||
if (Arr::has($validated, 'uri')) {
|
if (Arr::has($validated, 'uri')) {
|
||||||
$twofaccount->fillWithURI($validated['uri'], Arr::get($validated, 'custom_otp') === TwoFAccount::STEAM_TOTP);
|
$twofaccount->fillWithURI($validated['uri'], Arr::get($validated, 'custom_otp') === TwoFAccount::STEAM_TOTP);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$twofaccount->fillWithOtpParameters($validated);
|
$twofaccount->fillWithOtpParameters($validated);
|
||||||
}
|
}
|
||||||
$twofaccount->save();
|
$twofaccount->save();
|
||||||
@ -79,8 +74,6 @@ public function store(TwoFAccountDynamicRequest $request)
|
|||||||
->setStatusCode(201);
|
->setStatusCode(201);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a 2FA account
|
* Update a 2FA account
|
||||||
*
|
*
|
||||||
@ -98,10 +91,8 @@ public function update(TwoFAccountUpdateRequest $request, TwoFAccount $twofaccou
|
|||||||
return (new TwoFAccountReadResource($twofaccount))
|
return (new TwoFAccountReadResource($twofaccount))
|
||||||
->response()
|
->response()
|
||||||
->setStatusCode(200);
|
->setStatusCode(200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a migration resource to a valid TwoFAccounts collection
|
* Convert a migration resource to a valid TwoFAccounts collection
|
||||||
*
|
*
|
||||||
@ -118,13 +109,11 @@ public function migrate(TwoFAccountImportRequest $request)
|
|||||||
return $migrationResource instanceof \Illuminate\Http\UploadedFile
|
return $migrationResource instanceof \Illuminate\Http\UploadedFile
|
||||||
? new TwoFAccountCollection(TwoFAccounts::migrate($migrationResource->get()))
|
? new TwoFAccountCollection(TwoFAccounts::migrate($migrationResource->get()))
|
||||||
: response()->json(['message' => __('errors.file_upload_failed')], 500);
|
: response()->json(['message' => __('errors.file_upload_failed')], 500);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return new TwoFAccountCollection(TwoFAccounts::migrate($request->payload));
|
return new TwoFAccountCollection(TwoFAccounts::migrate($request->payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save 2FA accounts order
|
* Save 2FA accounts order
|
||||||
*
|
*
|
||||||
@ -140,7 +129,6 @@ public function reorder(TwoFAccountReorderRequest $request)
|
|||||||
return response()->json(['message' => 'order saved'], 200);
|
return response()->json(['message' => 'order saved'], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preview account using an uri, without any db moves
|
* Preview account using an uri, without any db moves
|
||||||
*
|
*
|
||||||
@ -155,7 +143,6 @@ public function preview(TwoFAccountUriRequest $request)
|
|||||||
return new TwoFAccountStoreResource($twofaccount);
|
return new TwoFAccountStoreResource($twofaccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a One-Time Password
|
* Get a One-Time Password
|
||||||
*
|
*
|
||||||
@ -173,15 +160,14 @@ public function otp(Request $request, $id = null)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The request input is an uri
|
// The request input is an uri
|
||||||
else if ( $request->has('uri') ) {
|
elseif ($request->has('uri')) {
|
||||||
// return 404 if uri is provided with any parameter other than otp_type
|
// return 404 if uri is provided with any parameter other than otp_type
|
||||||
if ((count($inputs) == 2 && $request->missing('custom_otp')) || count($inputs) > 2) {
|
if ((count($inputs) == 2 && $request->missing('custom_otp')) || count($inputs) > 2) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'bad request',
|
'message' => 'bad request',
|
||||||
'reason' => ['uri' => __('validation.onlyCustomOtpWithUri')]
|
'reason' => ['uri' => __('validation.onlyCustomOtpWithUri')],
|
||||||
], 400);
|
], 400);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$validatedData = $request->validate((new TwoFAccountUriRequest)->rules());
|
$validatedData = $request->validate((new TwoFAccountUriRequest)->rules());
|
||||||
$twofaccount = new TwoFAccount;
|
$twofaccount = new TwoFAccount;
|
||||||
$twofaccount->fillWithURI($validatedData['uri'], Arr::get($validatedData, 'custom_otp') === TwoFAccount::STEAM_TOTP, true);
|
$twofaccount->fillWithURI($validatedData['uri'], Arr::get($validatedData, 'custom_otp') === TwoFAccount::STEAM_TOTP, true);
|
||||||
@ -198,7 +184,6 @@ public function otp(Request $request, $id = null)
|
|||||||
return response()->json($twofaccount->getOTP(), 200);
|
return response()->json($twofaccount->getOTP(), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple and light method to get the account count.
|
* A simple and light method to get the account count.
|
||||||
*
|
*
|
||||||
@ -207,12 +192,10 @@ public function otp(Request $request, $id = null)
|
|||||||
*/
|
*/
|
||||||
public function count(Request $request)
|
public function count(Request $request)
|
||||||
{
|
{
|
||||||
return response()->json([ 'count' => TwoFAccount::count() ], 200);
|
return response()->json(['count' => TwoFAccount::count()], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Withdraw one or more accounts from their group
|
* Withdraw one or more accounts from their group
|
||||||
*
|
*
|
||||||
* @param \App\Api\v1\Requests\TwoFAccountBatchRequest $request
|
* @param \App\Api\v1\Requests\TwoFAccountBatchRequest $request
|
||||||
@ -225,16 +208,15 @@ public function withdraw(TwoFAccountBatchRequest $request)
|
|||||||
if ($this->tooManyIds($validated['ids'])) {
|
if ($this->tooManyIds($validated['ids'])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'bad request',
|
'message' => 'bad request',
|
||||||
'reason' => [__('errors.too_many_ids')]
|
'reason' => [__('errors.too_many_ids')],
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
TwoFAccounts::withdraw($validated['ids']);
|
TwoFAccounts::withdraw($validated['ids']);
|
||||||
|
|
||||||
return response()->json([ 'message' => 'accounts withdrawn' ], 200);
|
return response()->json(['message' => 'accounts withdrawn'], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
@ -248,7 +230,6 @@ public function destroy(TwoFAccount $twofaccount)
|
|||||||
return response()->json(null, 204);
|
return response()->json(null, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resources from storage.
|
* Remove the specified resources from storage.
|
||||||
*
|
*
|
||||||
@ -262,7 +243,7 @@ public function batchDestroy(TwoFAccountBatchRequest $request)
|
|||||||
if ($this->tooManyIds($validated['ids'])) {
|
if ($this->tooManyIds($validated['ids'])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'bad request',
|
'message' => 'bad request',
|
||||||
'reason' => [__('errors.too_many_ids')]
|
'reason' => [__('errors.too_many_ids')],
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +252,6 @@ public function batchDestroy(TwoFAccountBatchRequest $request)
|
|||||||
return response()->json(null, 204);
|
return response()->json(null, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks ids length
|
* Checks ids length
|
||||||
*
|
*
|
||||||
@ -285,5 +265,4 @@ private function tooManyIds(string $ids) : bool
|
|||||||
|
|
||||||
return $nb > 99 ? true : false;
|
return $nb > 99 ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Controllers;
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Api\v1\Resources\UserResource;
|
use App\Api\v1\Resources\UserResource;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
@ -24,6 +24,5 @@ public function show(Request $request)
|
|||||||
return $user
|
return $user
|
||||||
? new UserResource($user)
|
? new UserResource($user)
|
||||||
: response()->json(['name' => null], 200);
|
: response()->json(['name' => null], 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ public function rules()
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'ids' => 'required|array',
|
'ids' => 'required|array',
|
||||||
'ids.*' => 'integer'
|
'ids.*' => 'integer',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Api\v1\Requests;
|
namespace App\Api\v1\Requests;
|
||||||
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class TwoFAccountDynamicRequest extends FormRequest
|
class TwoFAccountDynamicRequest extends FormRequest
|
||||||
@ -32,7 +32,6 @@ public function rules()
|
|||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the data for validation.
|
* Prepare the data for validation.
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,6 @@ public function rules()
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the data for validation.
|
* Prepare the data for validation.
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,6 @@ public function rules()
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the data for validation.
|
* Prepare the data for validation.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +30,6 @@ public function rules()
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the data for validation.
|
* Prepare the data for validation.
|
||||||
*
|
*
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
namespace App\Api\v1\Resources;
|
namespace App\Api\v1\Resources;
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
use App\Api\v1\Resources\TwoFAccountReadResource;
|
|
||||||
|
|
||||||
class TwoFAccountCollection extends ResourceCollection
|
class TwoFAccountCollection extends ResourceCollection
|
||||||
{
|
{
|
||||||
@ -14,7 +13,6 @@ class TwoFAccountCollection extends ResourceCollection
|
|||||||
*/
|
*/
|
||||||
public $collects = TwoFAccountReadResource::class;
|
public $collects = TwoFAccountReadResource::class;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the resource collection into an array.
|
* Transform the resource collection into an array.
|
||||||
*
|
*
|
||||||
@ -27,7 +25,7 @@ public function toArray($request)
|
|||||||
// The underlying TwoFAccountReadResource hides the secret only when withSecret == false.
|
// The underlying TwoFAccountReadResource hides the secret only when withSecret == false.
|
||||||
// When withSecret is provided the underlying resource will return secret according to the parameter value
|
// When withSecret is provided the underlying resource will return secret according to the parameter value
|
||||||
// If no withSecret is set we force it to false to ensure the secret will not being returned.
|
// If no withSecret is set we force it to false to ensure the secret will not being returned.
|
||||||
if (!$request->has('withSecret')) {
|
if (! $request->has('withSecret')) {
|
||||||
$request->merge(['withSecret' => false]);
|
$request->merge(['withSecret' => false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,13 +31,13 @@ public function toArray($request)
|
|||||||
'service' => $this->service,
|
'service' => $this->service,
|
||||||
'icon' => $this->icon,
|
'icon' => $this->icon,
|
||||||
'secret' => $this->when(
|
'secret' => $this->when(
|
||||||
!$request->has('withSecret') || (int) filter_var($request->input('withSecret'), FILTER_VALIDATE_BOOLEAN) == 1,
|
! $request->has('withSecret') || (int) filter_var($request->input('withSecret'), FILTER_VALIDATE_BOOLEAN) == 1,
|
||||||
$this->secret
|
$this->secret
|
||||||
),
|
),
|
||||||
'digits' => (int) $this->digits,
|
'digits' => (int) $this->digits,
|
||||||
'algorithm' => $this->algorithm,
|
'algorithm' => $this->algorithm,
|
||||||
'period' => is_null($this->period) ? null : (int)$this->period,
|
'period' => is_null($this->period) ? null : (int) $this->period,
|
||||||
'counter' => is_null($this->counter) ? null : (int)$this->counter
|
'counter' => is_null($this->counter) ? null : (int) $this->counter,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,9 +20,9 @@ class UserResource extends JsonResource
|
|||||||
public function toArray($request)
|
public function toArray($request)
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->when(!is_null($request->user()), $this->id),
|
'id' => $this->when(! is_null($request->user()), $this->id),
|
||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'email' => $this->when(!is_null($request->user()), $this->email),
|
'email' => $this->when(! is_null($request->user()), $this->email),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
|
|
||||||
class CheckDbConnection extends Command
|
class CheckDbConnection extends Command
|
||||||
{
|
{
|
||||||
@ -44,6 +43,7 @@ public function handle() : int
|
|||||||
try {
|
try {
|
||||||
DB::connection()->getPDO();
|
DB::connection()->getPDO();
|
||||||
$this->line(DB::connection()->getDatabaseName());
|
$this->line(DB::connection()->getDatabaseName());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -42,12 +42,13 @@ public function __construct()
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
if (! Schema::hasColumn('twofaccounts', 'legacy_uri')) {
|
||||||
if (!Schema::hasColumn('twofaccounts', 'legacy_uri')) {
|
|
||||||
$this->comment('2fauth:fix-unsplitted-accounts is useful only after SplitTwofaccountsUriInMultipleColumns migration ran');
|
$this->comment('2fauth:fix-unsplitted-accounts is useful only after SplitTwofaccountsUriInMultipleColumns migration ran');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
$this->line('Fetching accounts...');
|
||||||
}
|
}
|
||||||
else $this->line('Fetching accounts...');
|
|
||||||
|
|
||||||
$twofaccounts = TwoFAccount::where('otp_type', '')
|
$twofaccounts = TwoFAccount::where('otp_type', '')
|
||||||
->where('secret', '')
|
->where('secret', '')
|
||||||
@ -61,6 +62,7 @@ public function handle()
|
|||||||
|
|
||||||
if ($twofaccounts->count() == 0) {
|
if ($twofaccounts->count() == 0) {
|
||||||
$this->info('Nothing to fix');
|
$this->info('Nothing to fix');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,16 +71,14 @@ public function handle()
|
|||||||
foreach ($twofaccounts as $twofaccount) {
|
foreach ($twofaccounts as $twofaccount) {
|
||||||
if ($twofaccount->legacy_uri === __('errors.indecipherable')) {
|
if ($twofaccount->legacy_uri === __('errors.indecipherable')) {
|
||||||
$this->error(sprintf('Account #%d cannot be deciphered', $twofaccount->id));
|
$this->error(sprintf('Account #%d cannot be deciphered', $twofaccount->id));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
try {
|
try {
|
||||||
// Get a consistent account
|
// Get a consistent account
|
||||||
$twofaccount->fillWithURI($twofaccount->legacy_uri, false, true);
|
$twofaccount->fillWithURI($twofaccount->legacy_uri, false, true);
|
||||||
$twofaccount->save();
|
$twofaccount->save();
|
||||||
|
|
||||||
$this->info(sprintf('Account #%d fixed', $twofaccount->id));
|
$this->info(sprintf('Account #%d fixed', $twofaccount->id));
|
||||||
}
|
} catch (\Exception $ex) {
|
||||||
catch (\Exception $ex) {
|
|
||||||
$this->error(sprintf('Error while updating account #%d', $twofaccount->id));
|
$this->error(sprintf('Error while updating account #%d', $twofaccount->id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use App\Console\Commands\Utils\ResetTrait;
|
use App\Console\Commands\Utils\ResetTrait;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class ResetDemo extends Command
|
class ResetDemo extends Command
|
||||||
{
|
{
|
||||||
@ -40,15 +40,15 @@ public function __construct()
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
if( !config('2fauth.config.isDemoApp') ) {
|
if (! config('2fauth.config.isDemoApp')) {
|
||||||
$this->comment('2fauth:reset-demo can only run when isDemoApp option is On');
|
$this->comment('2fauth:reset-demo can only run when isDemoApp option is On');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( $this->option('no-confirm') ) {
|
if ($this->option('no-confirm')) {
|
||||||
$demo = 'demo';
|
$demo = 'demo';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$this->line('This will reset the app in order to run a clean and fresh demo.');
|
$this->line('This will reset the app in order to run a clean and fresh demo.');
|
||||||
$demo = $this->ask('To prevent any mistake please type the word "demo" to go on');
|
$demo = $this->ask('To prevent any mistake please type the word "demo" to go on');
|
||||||
}
|
}
|
||||||
@ -57,8 +57,7 @@ public function handle()
|
|||||||
$this->resetIcons();
|
$this->resetIcons();
|
||||||
$this->resetDB('DemoSeeder');
|
$this->resetDB('DemoSeeder');
|
||||||
$this->info('Demo app refreshed');
|
$this->info('Demo app refreshed');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$this->comment('Bad confirmation word, nothing appened');
|
$this->comment('Bad confirmation word, nothing appened');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,15 +40,15 @@ public function __construct()
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
if( !config('2fauth.config.isTestingApp') ) {
|
if (! config('2fauth.config.isTestingApp')) {
|
||||||
$this->comment('2fauth:reset-testing can only run when isTestingApp option is On');
|
$this->comment('2fauth:reset-testing can only run when isTestingApp option is On');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( $this->option('no-confirm') ) {
|
if ($this->option('no-confirm')) {
|
||||||
$testing = 'testing';
|
$testing = 'testing';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$this->line('This will reset the app in order to run a clean and fresh testing app.');
|
$this->line('This will reset the app in order to run a clean and fresh testing app.');
|
||||||
$testing = $this->ask('To prevent any mistake please type the word "testing" to go on');
|
$testing = $this->ask('To prevent any mistake please type the word "testing" to go on');
|
||||||
}
|
}
|
||||||
@ -58,10 +58,8 @@ public function handle()
|
|||||||
$this->resetDB('TestingSeeder');
|
$this->resetDB('TestingSeeder');
|
||||||
|
|
||||||
$this->info('Testing app refreshed');
|
$this->info('Testing app refreshed');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$this->comment('Bad confirmation word, nothing appened');
|
$this->comment('Bad confirmation word, nothing appened');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands\Utils;
|
namespace App\Console\Commands\Utils;
|
||||||
|
|
||||||
use App\Console\Commands\Utils\IconGenerator;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
@ -81,10 +80,9 @@ protected function flushDB() : void
|
|||||||
protected function seedDB(string $seeder) : void
|
protected function seedDB(string $seeder) : void
|
||||||
{
|
{
|
||||||
$this->callSilent('db:seed', [
|
$this->callSilent('db:seed', [
|
||||||
'--class' => $seeder
|
'--class' => $seeder,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->line('Database seeded');
|
$this->line('Database seeded');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ protected function schedule(Schedule $schedule)
|
|||||||
*/
|
*/
|
||||||
protected function commands()
|
protected function commands()
|
||||||
{
|
{
|
||||||
$this->load(__DIR__.'/Commands');
|
$this->load(__DIR__ . '/Commands');
|
||||||
|
|
||||||
require base_path('routes/console.php');
|
require base_path('routes/console.php');
|
||||||
}
|
}
|
||||||
|
@ -44,64 +44,71 @@ public function register()
|
|||||||
{
|
{
|
||||||
$this->renderable(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $exception, $request) {
|
$this->renderable(function (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'not found'], 404);
|
'message' => 'not found',
|
||||||
|
], 404);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (InvalidOtpParameterException $exception, $request) {
|
$this->renderable(function (InvalidOtpParameterException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'invalid OTP parameters',
|
'message' => 'invalid OTP parameters',
|
||||||
'reason' => [$exception->getMessage()]
|
'reason' => [$exception->getMessage()],
|
||||||
], 400);
|
], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (InvalidQrCodeException $exception, $request) {
|
$this->renderable(function (InvalidQrCodeException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'not a valid QR code'], 400);
|
'message' => 'not a valid QR code', ], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (InvalidSecretException $exception, $request) {
|
$this->renderable(function (InvalidSecretException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'not a valid base32 encoded secret'], 400);
|
'message' => 'not a valid base32 encoded secret', ], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (DbEncryptionException $exception, $request) {
|
$this->renderable(function (DbEncryptionException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => $exception->getMessage()], 400);
|
'message' => $exception->getMessage(), ], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (InvalidMigrationDataException $exception, $request) {
|
$this->renderable(function (InvalidMigrationDataException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('errors.invalid_x_migration', ['appname' => $exception->getMessage()])], 400);
|
'message' => __('errors.invalid_x_migration', ['appname' => $exception->getMessage()]),
|
||||||
|
], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (UnsupportedMigrationException $exception, $request) {
|
$this->renderable(function (UnsupportedMigrationException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('errors.unsupported_migration')], 400);
|
'message' => __('errors.unsupported_migration'),
|
||||||
|
], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (EncryptedMigrationException $exception, $request) {
|
$this->renderable(function (EncryptedMigrationException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('errors.encrypted_migration')], 400);
|
'message' => __('errors.encrypted_migration'),
|
||||||
|
], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (UndecipherableException $exception, $request) {
|
$this->renderable(function (UndecipherableException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('errors.cannot_decipher_secret')], 400);
|
'message' => __('errors.cannot_decipher_secret'),
|
||||||
|
], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (UnsupportedOtpTypeException $exception, $request) {
|
$this->renderable(function (UnsupportedOtpTypeException $exception, $request) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('errors.unsupported_otp_type')], 400);
|
'message' => __('errors.unsupported_otp_type'),
|
||||||
|
], 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->renderable(function (\Illuminate\Auth\AuthenticationException $exception, $request) {
|
$this->renderable(function (\Illuminate\Auth\AuthenticationException $exception, $request) {
|
||||||
if ($exception->guards() === ['reverse-proxy-guard']) {
|
if ($exception->guards() === ['reverse-proxy-guard']) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => $exception->getMessage()], 407);
|
'message' => $exception->getMessage(),
|
||||||
}
|
], 407);
|
||||||
else {
|
} else {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => $exception->getMessage()], 401);
|
'message' => $exception->getMessage(),
|
||||||
|
], 401);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
namespace App\Extensions;
|
namespace App\Extensions;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Contracts\Auth\Authenticatable;
|
use Illuminate\Contracts\Auth\Authenticatable;
|
||||||
use Illuminate\Contracts\Auth\UserProvider;
|
use Illuminate\Contracts\Auth\UserProvider;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Exception;
|
|
||||||
|
|
||||||
class RemoteUserProvider implements UserProvider
|
class RemoteUserProvider implements UserProvider
|
||||||
{
|
{
|
||||||
@ -23,7 +23,6 @@ class RemoteUserProvider implements UserProvider
|
|||||||
// The downside of this approach is that we have to be sure that no change that needs
|
// The downside of this approach is that we have to be sure that no change that needs
|
||||||
// to be persisted will be made to the user instance afterward (i.e through middlewares).
|
// to be persisted will be made to the user instance afterward (i.e through middlewares).
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently authenticated user.
|
* The currently authenticated user.
|
||||||
*
|
*
|
||||||
@ -31,7 +30,6 @@ class RemoteUserProvider implements UserProvider
|
|||||||
*/
|
*/
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the In-memory user
|
* Get the In-memory user
|
||||||
*
|
*
|
||||||
@ -48,9 +46,8 @@ protected function getInMemoryUser()
|
|||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function retrieveById($identifier)
|
public function retrieveById($identifier)
|
||||||
{
|
{
|
||||||
@ -67,7 +64,7 @@ public function retrieveById($identifier)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
@ -77,7 +74,7 @@ public function retrieveByToken($identifier, $token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
@ -87,7 +84,7 @@ public function updateRememberToken(Authenticatable $user, $token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
@ -97,7 +94,7 @@ public function retrieveByCredentials(array $credentials)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Extensions;
|
namespace App\Extensions;
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use App\Models\WebAuthnAuthenticatable;
|
use App\Models\WebAuthnAuthenticatable;
|
||||||
|
use Closure;
|
||||||
use Illuminate\Auth\Passwords\PasswordBroker;
|
use Illuminate\Auth\Passwords\PasswordBroker;
|
||||||
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
|
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
|
||||||
|
|
||||||
@ -14,14 +14,13 @@ class WebauthnCredentialBroker extends PasswordBroker
|
|||||||
*
|
*
|
||||||
* @param array $credentials
|
* @param array $credentials
|
||||||
* @param \Closure|null $callback
|
* @param \Closure|null $callback
|
||||||
*
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function sendResetLink(array $credentials, Closure $callback = null): string
|
public function sendResetLink(array $credentials, Closure $callback = null) : string
|
||||||
{
|
{
|
||||||
$user = $this->getUser($credentials);
|
$user = $this->getUser($credentials);
|
||||||
|
|
||||||
if (!$user instanceof WebAuthnAuthenticatable) {
|
if (! $user instanceof WebAuthnAuthenticatable) {
|
||||||
return static::INVALID_USER;
|
return static::INVALID_USER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,20 +39,18 @@ public function sendResetLink(array $credentials, Closure $callback = null): str
|
|||||||
return static::RESET_LINK_SENT;
|
return static::RESET_LINK_SENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the password for the given token.
|
* Reset the password for the given token.
|
||||||
*
|
*
|
||||||
* @param array $credentials
|
* @param array $credentials
|
||||||
* @param \Closure $callback
|
* @param \Closure $callback
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\Auth\CanResetPassword|string
|
* @return \Illuminate\Contracts\Auth\CanResetPassword|string
|
||||||
*/
|
*/
|
||||||
public function reset(array $credentials, Closure $callback)
|
public function reset(array $credentials, Closure $callback)
|
||||||
{
|
{
|
||||||
$user = $this->validateReset($credentials);
|
$user = $this->validateReset($credentials);
|
||||||
|
|
||||||
if (!$user instanceof CanResetPasswordContract || !$user instanceof WebAuthnAuthenticatable) {
|
if (! $user instanceof CanResetPasswordContract || ! $user instanceof WebAuthnAuthenticatable) {
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
namespace App\Factories;
|
namespace App\Factories;
|
||||||
|
|
||||||
use App\Services\Migrators\GoogleAuthMigrator;
|
use App\Exceptions\EncryptedMigrationException;
|
||||||
|
use App\Exceptions\UnsupportedMigrationException;
|
||||||
use App\Services\Migrators\AegisMigrator;
|
use App\Services\Migrators\AegisMigrator;
|
||||||
|
use App\Services\Migrators\GoogleAuthMigrator;
|
||||||
use App\Services\Migrators\Migrator;
|
use App\Services\Migrators\Migrator;
|
||||||
use App\Services\Migrators\PlainTextMigrator;
|
use App\Services\Migrators\PlainTextMigrator;
|
||||||
use App\Services\Migrators\TwoFASMigrator;
|
use App\Services\Migrators\TwoFASMigrator;
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use App\Exceptions\UnsupportedMigrationException;
|
|
||||||
use App\Exceptions\EncryptedMigrationException;
|
|
||||||
|
|
||||||
class MigratorFactory implements MigratorFactoryInterface
|
class MigratorFactory implements MigratorFactoryInterface
|
||||||
{
|
{
|
||||||
@ -25,21 +25,17 @@ public function create(string $migrationPayload) : Migrator
|
|||||||
{
|
{
|
||||||
if ($this->isAegisJSON($migrationPayload)) {
|
if ($this->isAegisJSON($migrationPayload)) {
|
||||||
return App::make(AegisMigrator::class);
|
return App::make(AegisMigrator::class);
|
||||||
}
|
} elseif ($this->is2FASv2($migrationPayload)) {
|
||||||
else if ($this->is2FASv2($migrationPayload)) {
|
|
||||||
return App::make(TwoFASMigrator::class);
|
return App::make(TwoFASMigrator::class);
|
||||||
}
|
} elseif ($this->isGoogleAuth($migrationPayload)) {
|
||||||
else if ($this->isGoogleAuth($migrationPayload)) {
|
|
||||||
return App::make(GoogleAuthMigrator::class);
|
return App::make(GoogleAuthMigrator::class);
|
||||||
}
|
} elseif ($this->isPlainText($migrationPayload)) {
|
||||||
else if ($this->isPlainText($migrationPayload)) {
|
|
||||||
return App::make(PlainTextMigrator::class);
|
return App::make(PlainTextMigrator::class);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedMigrationException();
|
||||||
}
|
}
|
||||||
else throw new UnsupportedMigrationException();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a payload comes from Google Authenticator
|
* Determine if a payload comes from Google Authenticator
|
||||||
*
|
*
|
||||||
@ -50,15 +46,15 @@ private function isGoogleAuth(string $migrationPayload) : bool
|
|||||||
{
|
{
|
||||||
// - Google Auth migration URI : a string starting with otpauth-migration://offline?data= on a single line
|
// - Google Auth migration URI : a string starting with otpauth-migration://offline?data= on a single line
|
||||||
|
|
||||||
$lines = preg_split('~\R~', $migrationPayload, -1 , PREG_SPLIT_NO_EMPTY);
|
$lines = preg_split('~\R~', $migrationPayload, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
if (!$lines || count($lines) != 1)
|
if (! $lines || count($lines) != 1) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return preg_match('/^otpauth-migration:\/\/offline\?data=.+$/', $lines[0]) == 1;
|
return preg_match('/^otpauth-migration:\/\/offline\?data=.+$/', $lines[0]) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a payload is a plain text content
|
* Determine if a payload is a plain text content
|
||||||
*
|
*
|
||||||
@ -70,14 +66,13 @@ private function isPlainText(string $migrationPayload) : bool
|
|||||||
// - Plain text : one or more otpauth URIs (otpauth://[t|h]otp/...), one per line
|
// - Plain text : one or more otpauth URIs (otpauth://[t|h]otp/...), one per line
|
||||||
|
|
||||||
return Validator::make(
|
return Validator::make(
|
||||||
preg_split('~\R~', $migrationPayload, -1 , PREG_SPLIT_NO_EMPTY),
|
preg_split('~\R~', $migrationPayload, -1, PREG_SPLIT_NO_EMPTY),
|
||||||
[
|
[
|
||||||
'*' => 'regex:/^otpauth:\/\/[h,t]otp\//i',
|
'*' => 'regex:/^otpauth:\/\/[h,t]otp\//i',
|
||||||
]
|
]
|
||||||
)->passes();
|
)->passes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a payload comes from Aegis Authenticator in JSON format
|
* Determine if a payload comes from Aegis Authenticator in JSON format
|
||||||
*
|
*
|
||||||
@ -107,15 +102,14 @@ private function isAegisJSON(string $migrationPayload) : mixed
|
|||||||
if (Arr::has($json, 'db')) {
|
if (Arr::has($json, 'db')) {
|
||||||
if (is_string($json['db']) && is_array(Arr::get($json, 'header.slots'))) {
|
if (is_string($json['db']) && is_array(Arr::get($json, 'header.slots'))) {
|
||||||
throw new EncryptedMigrationException();
|
throw new EncryptedMigrationException();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return count(Validator::validate(
|
return count(Validator::validate(
|
||||||
$json,
|
$json,
|
||||||
[
|
[
|
||||||
'db.entries.*.type' => 'required',
|
'db.entries.*.type' => 'required',
|
||||||
'db.entries.*.name' => 'required',
|
'db.entries.*.name' => 'required',
|
||||||
'db.entries.*.issuer' => 'required',
|
'db.entries.*.issuer' => 'required',
|
||||||
'db.entries.*.info' => 'required'
|
'db.entries.*.info' => 'required',
|
||||||
]
|
]
|
||||||
)) > 0;
|
)) > 0;
|
||||||
}
|
}
|
||||||
@ -124,7 +118,6 @@ private function isAegisJSON(string $migrationPayload) : mixed
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a payload comes from 2FAS Authenticator
|
* Determine if a payload comes from 2FAS Authenticator
|
||||||
*
|
*
|
||||||
@ -159,14 +152,13 @@ private function is2FASv2(string $migrationPayload) : mixed
|
|||||||
if (Arr::get($json, 'schemaVersion') == 2 && (Arr::has($json, 'services') || Arr::has($json, 'servicesEncrypted'))) {
|
if (Arr::get($json, 'schemaVersion') == 2 && (Arr::has($json, 'services') || Arr::has($json, 'servicesEncrypted'))) {
|
||||||
if (Arr::has($json, 'servicesEncrypted')) {
|
if (Arr::has($json, 'servicesEncrypted')) {
|
||||||
throw new EncryptedMigrationException();
|
throw new EncryptedMigrationException();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return count(Validator::validate(
|
return count(Validator::validate(
|
||||||
$json,
|
$json,
|
||||||
[
|
[
|
||||||
'services.*.secret' => 'required',
|
'services.*.secret' => 'required',
|
||||||
'services.*.name' => 'required',
|
'services.*.name' => 'required',
|
||||||
'services.*.otp' => 'required'
|
'services.*.otp' => 'required',
|
||||||
]
|
]
|
||||||
)) > 0;
|
)) > 0;
|
||||||
}
|
}
|
||||||
@ -174,5 +166,4 @@ private function is2FASv2(string $migrationPayload) : mixed
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,18 @@ class Helpers
|
|||||||
* @param string $extension
|
* @param string $extension
|
||||||
* @return string The filename
|
* @return string The filename
|
||||||
*/
|
*/
|
||||||
public static function getUniqueFilename(string $extension): string
|
public static function getUniqueFilename(string $extension) : string
|
||||||
{
|
{
|
||||||
return Str::random(40).'.'.$extension;
|
return Str::random(40) . '.' . $extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public static function cleanVersionNumber(?string $release): string|false
|
* Clean a version number string
|
||||||
|
*
|
||||||
|
* @param string|null $release
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
public static function cleanVersionNumber(?string $release) : string|false
|
||||||
{
|
{
|
||||||
return preg_match('/([[0-9][0-9\.]*[0-9])/', $release, $version) ? $version[0] : false;
|
return preg_match('/([[0-9][0-9\.]*[0-9])/', $release, $version) ? $version[0] : false;
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ForgotPasswordController extends Controller
|
class ForgotPasswordController extends Controller
|
||||||
{
|
{
|
||||||
@ -21,7 +21,6 @@ class ForgotPasswordController extends Controller
|
|||||||
|
|
||||||
use SendsPasswordResetEmails;
|
use SendsPasswordResetEmails;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the email for the given request.
|
* Validate the email for the given request.
|
||||||
*
|
*
|
||||||
|
@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\LoginRequest;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Lang;
|
use Illuminate\Support\Facades\Lang;
|
||||||
use App\Http\Requests\LoginRequest;
|
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
|
||||||
class LoginController extends Controller
|
class LoginController extends Controller
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -28,7 +27,6 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
use AuthenticatesUsers;
|
use AuthenticatesUsers;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a login request to the application.
|
* Handle a login request to the application.
|
||||||
*
|
*
|
||||||
@ -65,9 +63,9 @@ public function login(LoginRequest $request)
|
|||||||
return $this->sendFailedLoginResponse($request);
|
return $this->sendFailedLoginResponse($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* log out current user
|
* log out current user
|
||||||
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
@ -79,7 +77,6 @@ public function logout(Request $request)
|
|||||||
return response()->json(['message' => 'signed out'], Response::HTTP_OK);
|
return response()->json(['message' => 'signed out'], Response::HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the response after the user was authenticated.
|
* Send the response after the user was authenticated.
|
||||||
*
|
*
|
||||||
@ -96,11 +93,10 @@ protected function sendLoginResponse(Request $request)
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'authenticated',
|
'message' => 'authenticated',
|
||||||
'name' => $name
|
'name' => $name,
|
||||||
], Response::HTTP_OK);
|
], Response::HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the failed login response instance.
|
* Get the failed login response instance.
|
||||||
*
|
*
|
||||||
@ -112,7 +108,6 @@ protected function sendFailedLoginResponse(Request $request)
|
|||||||
return response()->json(['message' => 'unauthorised'], Response::HTTP_UNAUTHORIZED);
|
return response()->json(['message' => 'unauthorised'], Response::HTTP_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect the user after determining they are locked out.
|
* Redirect the user after determining they are locked out.
|
||||||
*
|
*
|
||||||
@ -128,7 +123,6 @@ protected function sendLockoutResponse(Request $request)
|
|||||||
return response()->json(['message' => Lang::get('auth.throttle', ['seconds' => $seconds])], Response::HTTP_TOO_MANY_REQUESTS);
|
return response()->json(['message' => Lang::get('auth.throttle', ['seconds' => $seconds])], Response::HTTP_TOO_MANY_REQUESTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the needed authorization credentials from the request.
|
* Get the needed authorization credentials from the request.
|
||||||
*
|
*
|
||||||
@ -145,7 +139,6 @@ protected function credentials(Request $request)
|
|||||||
return $credentials;
|
return $credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user has been authenticated.
|
* The user has been authenticated.
|
||||||
*
|
*
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Http\Requests\UserPatchPwdRequest;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\UserPatchPwdRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@ -20,12 +20,13 @@ public function update(UserPatchPwdRequest $request)
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
if (!Hash::check( $validated['currentPassword'], Auth::user()->password) ) {
|
if (! Hash::check($validated['currentPassword'], Auth::user()->password)) {
|
||||||
Log::notice('Password update failed: wrong password provided');
|
Log::notice('Password update failed: wrong password provided');
|
||||||
|
|
||||||
return response()->json(['message' => __('errors.wrong_current_password')], 400);
|
return response()->json(['message' => __('errors.wrong_current_password')], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config('2fauth.config.isDemoApp') ) {
|
if (! config('2fauth.config.isDemoApp')) {
|
||||||
$request->user()->update([
|
$request->user()->update([
|
||||||
'password' => bcrypt($validated['password']),
|
'password' => bcrypt($validated['password']),
|
||||||
]);
|
]);
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Http\Requests\UserStoreRequest;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use App\Http\Requests\UserStoreRequest;
|
||||||
|
use App\Models\User;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class RegisterController extends Controller
|
class RegisterController extends Controller
|
||||||
@ -25,7 +25,6 @@ class RegisterController extends Controller
|
|||||||
|
|
||||||
use RegistersUsers;
|
use RegistersUsers;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a registration request for the application.
|
* Handle a registration request for the application.
|
||||||
*
|
*
|
||||||
@ -46,7 +45,6 @@ public function register(UserStoreRequest $request)
|
|||||||
], 201);
|
], 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new user instance after a valid registration.
|
* Create a new user instance after a valid registration.
|
||||||
*
|
*
|
||||||
|
@ -19,5 +19,4 @@ class ResetPasswordController extends Controller
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use ResetsPasswords;
|
use ResetsPasswords;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Http\Requests\UserUpdateRequest;
|
|
||||||
use App\Http\Requests\UserDeleteRequest;
|
|
||||||
use App\Api\v1\Resources\UserResource;
|
use App\Api\v1\Resources\UserResource;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use App\Http\Requests\UserDeleteRequest;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use App\Http\Requests\UserUpdateRequest;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
@ -25,12 +25,13 @@ public function update(UserUpdateRequest $request)
|
|||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
if (!Hash::check( $request->password, Auth::user()->password) ) {
|
if (! Hash::check($request->password, Auth::user()->password)) {
|
||||||
Log::notice('Account update failed: wrong password provided');
|
Log::notice('Account update failed: wrong password provided');
|
||||||
|
|
||||||
return response()->json(['message' => __('errors.wrong_current_password')], 400);
|
return response()->json(['message' => __('errors.wrong_current_password')], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config('2fauth.config.isDemoApp') ) {
|
if (! config('2fauth.config.isDemoApp')) {
|
||||||
$user->update([
|
$user->update([
|
||||||
'name' => $validated['name'],
|
'name' => $validated['name'],
|
||||||
'email' => $validated['email'],
|
'email' => $validated['email'],
|
||||||
@ -41,7 +42,6 @@ public function update(UserUpdateRequest $request)
|
|||||||
return new UserResource($user);
|
return new UserResource($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the user's account.
|
* Delete the user's account.
|
||||||
*
|
*
|
||||||
@ -53,7 +53,7 @@ public function delete(UserDeleteRequest $request)
|
|||||||
Log::info('User deletion requested');
|
Log::info('User deletion requested');
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
if (!Hash::check( $validated['password'], Auth::user()->password) ) {
|
if (! Hash::check($validated['password'], Auth::user()->password)) {
|
||||||
return response()->json(['message' => __('errors.wrong_current_password')], 400);
|
return response()->json(['message' => __('errors.wrong_current_password')], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +79,7 @@ public function delete(UserDeleteRequest $request)
|
|||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
catch (\Throwable $e) {
|
catch (\Throwable $e) {
|
||||||
Log::error('User deletion failed');
|
Log::error('User deletion failed');
|
||||||
|
|
||||||
return response()->json(['message' => __('errors.user_deletion_failed')], 400);
|
return response()->json(['message' => __('errors.user_deletion_failed')], 400);
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
|
@ -2,26 +2,25 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Validation\ValidationException;
|
|
||||||
use App\Extensions\WebauthnCredentialBroker;
|
use App\Extensions\WebauthnCredentialBroker;
|
||||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Password;
|
|
||||||
use App\Http\Requests\WebauthnDeviceLostRequest;
|
use App\Http\Requests\WebauthnDeviceLostRequest;
|
||||||
|
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Password;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class WebAuthnDeviceLostController extends Controller
|
class WebAuthnDeviceLostController extends Controller
|
||||||
{
|
{
|
||||||
use ResetsPasswords;
|
use ResetsPasswords;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a recovery email to the user.
|
* Send a recovery email to the user.
|
||||||
*
|
*
|
||||||
* @param \App\Http\Requests\WebauthnDeviceLostRequest $request
|
* @param \App\Http\Requests\WebauthnDeviceLostRequest $request
|
||||||
* @param \App\Extensions\WebauthnCredentialBroker $broker
|
* @param \App\Extensions\WebauthnCredentialBroker $broker
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
|
||||||
|
*
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
* @throws \Illuminate\Validation\ValidationException
|
||||||
*/
|
*/
|
||||||
public function sendRecoveryEmail(WebauthnDeviceLostRequest $request, WebauthnCredentialBroker $broker)
|
public function sendRecoveryEmail(WebauthnDeviceLostRequest $request, WebauthnCredentialBroker $broker)
|
||||||
@ -35,14 +34,13 @@ public function sendRecoveryEmail(WebauthnDeviceLostRequest $request, WebauthnCr
|
|||||||
: $this->sendRecoveryLinkFailedResponse($request, $response);
|
: $this->sendRecoveryLinkFailedResponse($request, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response for a failed account recovery link.
|
* Get the response for a failed account recovery link.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $response
|
* @param string $response
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
|
*
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
* @throws \Illuminate\Validation\ValidationException
|
||||||
*/
|
*/
|
||||||
protected function sendRecoveryLinkFailedResponse(Request $request, string $response)
|
protected function sendRecoveryLinkFailedResponse(Request $request, string $response)
|
||||||
@ -56,13 +54,11 @@ protected function sendRecoveryLinkFailedResponse(Request $request, string $resp
|
|||||||
->withErrors(['email' => trans($response)]);
|
->withErrors(['email' => trans($response)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response for a successful account recovery link.
|
* Get the response for a successful account recovery link.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $response
|
* @param string $response
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
protected function sendRecoveryLinkResponse(Request $request, string $response)
|
protected function sendRecoveryLinkResponse(Request $request, string $response)
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Laragear\WebAuthn\Http\Requests\AssertionRequest;
|
|
||||||
use Laragear\WebAuthn\Http\Requests\AssertedRequest;
|
|
||||||
use Illuminate\Contracts\Support\Responsable;
|
use Illuminate\Contracts\Support\Responsable;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Laragear\WebAuthn\Http\Requests\AssertedRequest;
|
||||||
|
use Laragear\WebAuthn\Http\Requests\AssertionRequest;
|
||||||
use Laragear\WebAuthn\WebAuthn;
|
use Laragear\WebAuthn\WebAuthn;
|
||||||
|
|
||||||
class WebAuthnLoginController extends Controller
|
class WebAuthnLoginController extends Controller
|
||||||
@ -31,7 +31,7 @@ class WebAuthnLoginController extends Controller
|
|||||||
* @param \Laragear\WebAuthn\Http\Requests\AssertionRequest $request
|
* @param \Laragear\WebAuthn\Http\Requests\AssertionRequest $request
|
||||||
* @return \Illuminate\Contracts\Support\Responsable|\Illuminate\Http\JsonResponse
|
* @return \Illuminate\Contracts\Support\Responsable|\Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function options(AssertionRequest $request): Responsable|JsonResponse
|
public function options(AssertionRequest $request) : Responsable|JsonResponse
|
||||||
{
|
{
|
||||||
switch (env('WEBAUTHN_USER_VERIFICATION')) {
|
switch (env('WEBAUTHN_USER_VERIFICATION')) {
|
||||||
case WebAuthn::USER_VERIFICATION_DISCOURAGED:
|
case WebAuthn::USER_VERIFICATION_DISCOURAGED:
|
||||||
@ -50,11 +50,10 @@ public function options(AssertionRequest $request): Responsable|JsonResponse
|
|||||||
return $user
|
return $user
|
||||||
? $request->toVerify($user)
|
? $request->toVerify($user)
|
||||||
: response()->json([
|
: response()->json([
|
||||||
'message' => 'no registered user'
|
'message' => 'no registered user',
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log the user in.
|
* Log the user in.
|
||||||
*
|
*
|
||||||
@ -70,7 +69,7 @@ public function login(AssertedRequest $request)
|
|||||||
|
|
||||||
// Some authenticators do not send a userHandle so we hack the response to be compliant
|
// Some authenticators do not send a userHandle so we hack the response to be compliant
|
||||||
// with Larapass/webauthn-lib implementation that waits for a userHandle
|
// with Larapass/webauthn-lib implementation that waits for a userHandle
|
||||||
if(!$response['userHandle']) {
|
if (! $response['userHandle']) {
|
||||||
$response['userHandle'] = User::getFromCredentialId($request->id)?->userHandle();
|
$response['userHandle'] = User::getFromCredentialId($request->id)?->userHandle();
|
||||||
$request->merge(['response' => $response]);
|
$request->merge(['response' => $response]);
|
||||||
}
|
}
|
||||||
@ -80,18 +79,17 @@ public function login(AssertedRequest $request)
|
|||||||
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
$this->authenticated($user);
|
$this->authenticated($user);
|
||||||
|
|
||||||
return response()->noContent();
|
return response()->noContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->noContent(422);
|
return response()->noContent(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user has been authenticated.
|
* The user has been authenticated.
|
||||||
*
|
*
|
||||||
* @param mixed $user
|
* @param mixed $user
|
||||||
*
|
|
||||||
* @return void|\Illuminate\Http\JsonResponse
|
* @return void|\Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
protected function authenticated($user)
|
protected function authenticated($user)
|
||||||
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Http\Requests\WebauthnRenameRequest;
|
use App\Http\Requests\WebauthnRenameRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class WebAuthnManageController extends Controller
|
class WebAuthnManageController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all WebAuthn registered credentials
|
* List all WebAuthn registered credentials
|
||||||
*
|
*
|
||||||
@ -23,7 +22,6 @@ public function index(Request $request)
|
|||||||
return response()->json($allUserCredentials, 200);
|
return response()->json($allUserCredentials, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename a WebAuthn credential
|
* Rename a WebAuthn credential
|
||||||
*
|
*
|
||||||
@ -42,13 +40,11 @@ public function rename(WebauthnRenameRequest $request, string $credential)
|
|||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified credential from storage.
|
* Remove the specified credential from storage.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string|array $credential
|
* @param string|array $credential
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function delete(Request $request, $credential)
|
public function delete(Request $request, $credential)
|
||||||
|
@ -2,18 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Requests\WebauthnRecoveryRequest;
|
|
||||||
use App\Extensions\WebauthnCredentialBroker;
|
use App\Extensions\WebauthnCredentialBroker;
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\WebauthnRecoveryRequest;
|
||||||
use Illuminate\Auth\AuthenticationException;
|
use Illuminate\Auth\AuthenticationException;
|
||||||
|
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Validation\ValidationException;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
|
||||||
use Illuminate\Support\Facades\Password;
|
use Illuminate\Support\Facades\Password;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class WebAuthnRecoveryController extends Controller
|
class WebAuthnRecoveryController extends Controller
|
||||||
{
|
{
|
||||||
@ -25,8 +24,8 @@ class WebAuthnRecoveryController extends Controller
|
|||||||
*
|
*
|
||||||
* @param \App\Http\Requests\WebauthnRecoveryRequest $request
|
* @param \App\Http\Requests\WebauthnRecoveryRequest $request
|
||||||
* @param \App\Extensions\WebauthnCredentialBroker $broker
|
* @param \App\Extensions\WebauthnCredentialBroker $broker
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
||||||
|
*
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
* @throws \Illuminate\Validation\ValidationException
|
||||||
*/
|
*/
|
||||||
public function recover(WebauthnRecoveryRequest $request, WebauthnCredentialBroker $broker)
|
public function recover(WebauthnRecoveryRequest $request, WebauthnCredentialBroker $broker)
|
||||||
@ -54,66 +53,57 @@ function ($user) use ($request) {
|
|||||||
$user->flushCredentials();
|
$user->flushCredentials();
|
||||||
}
|
}
|
||||||
Settings::delete('useWebauthnOnly');
|
Settings::delete('useWebauthnOnly');
|
||||||
|
} else {
|
||||||
|
throw new AuthenticationException();
|
||||||
}
|
}
|
||||||
else throw new AuthenticationException();
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return $response === Password::PASSWORD_RESET
|
return $response === Password::PASSWORD_RESET
|
||||||
? $this->sendRecoveryResponse($request, $response)
|
? $this->sendRecoveryResponse($request, $response)
|
||||||
: $this->sendRecoveryFailedResponse($request, $response);
|
: $this->sendRecoveryFailedResponse($request, $response);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the user has set to revoke all credentials.
|
* Check if the user has set to revoke all credentials.
|
||||||
*
|
*
|
||||||
* @param \App\Http\Requests\WebauthnRecoveryRequest $request
|
* @param \App\Http\Requests\WebauthnRecoveryRequest $request
|
||||||
*
|
|
||||||
* @return bool|mixed
|
* @return bool|mixed
|
||||||
*/
|
*/
|
||||||
protected function shouldRevokeAllCredentials(WebauthnRecoveryRequest $request): mixed
|
protected function shouldRevokeAllCredentials(WebauthnRecoveryRequest $request) : mixed
|
||||||
{
|
{
|
||||||
return filter_var($request->header('WebAuthn-Unique'), FILTER_VALIDATE_BOOLEAN)
|
return filter_var($request->header('WebAuthn-Unique'), FILTER_VALIDATE_BOOLEAN)
|
||||||
?: $request->input('revokeAll', true);
|
?: $request->input('revokeAll', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response for a successful account recovery.
|
* Get the response for a successful account recovery.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $response
|
* @param string $response
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
protected function sendRecoveryResponse(Request $request, string $response): JsonResponse
|
protected function sendRecoveryResponse(Request $request, string $response) : JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json(['message' => __('auth.webauthn.webauthn_login_disabled')]);
|
return response()->json(['message' => __('auth.webauthn.webauthn_login_disabled')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response for a failed account recovery.
|
* Get the response for a failed account recovery.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $response
|
* @param string $response
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
|
||||||
*
|
*
|
||||||
|
* @throws \Illuminate\Validation\ValidationException
|
||||||
*/
|
*/
|
||||||
protected function sendRecoveryFailedResponse(Request $request, string $response): JsonResponse
|
protected function sendRecoveryFailedResponse(Request $request, string $response) : JsonResponse
|
||||||
{
|
{
|
||||||
switch ($response) {
|
switch ($response) {
|
||||||
case Password::INVALID_TOKEN:
|
case Password::INVALID_TOKEN:
|
||||||
throw ValidationException::withMessages(['token' => [__('auth.webauthn.invalid_reset_token')]]);
|
throw ValidationException::withMessages(['token' => [__('auth.webauthn.invalid_reset_token')]]);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ValidationException::withMessages(['email' => [trans($response)]]);
|
throw ValidationException::withMessages(['email' => [trans($response)]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ class WebAuthnRegisterController extends Controller
|
|||||||
* @param \Laragear\WebAuthn\Http\Requests\AttestationRequest $request
|
* @param \Laragear\WebAuthn\Http\Requests\AttestationRequest $request
|
||||||
* @return \Illuminate\Contracts\Support\Responsable
|
* @return \Illuminate\Contracts\Support\Responsable
|
||||||
*/
|
*/
|
||||||
public function options(AttestationRequest $request): Responsable
|
public function options(AttestationRequest $request) : Responsable
|
||||||
{
|
{
|
||||||
switch (env('WEBAUTHN_USER_VERIFICATION')) {
|
switch (env('WEBAUTHN_USER_VERIFICATION')) {
|
||||||
case WebAuthn::USER_VERIFICATION_DISCOURAGED:
|
case WebAuthn::USER_VERIFICATION_DISCOURAGED:
|
||||||
@ -34,14 +34,13 @@ public function options(AttestationRequest $request): Responsable
|
|||||||
->toCreate();
|
->toCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a device for further WebAuthn authentication.
|
* Registers a device for further WebAuthn authentication.
|
||||||
*
|
*
|
||||||
* @param \Laragear\WebAuthn\Http\Requests\AttestedRequest $request
|
* @param \Laragear\WebAuthn\Http\Requests\AttestedRequest $request
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function register(AttestedRequest $request): Response
|
public function register(AttestedRequest $request) : Response
|
||||||
{
|
{
|
||||||
$request->save();
|
$request->save();
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
|
||||||
use Illuminate\Routing\Controller as BaseController;
|
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
|
||||||
class Controller extends BaseController
|
class Controller extends BaseController
|
||||||
{
|
{
|
||||||
|
@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Events\ScanForNewReleaseCalled;
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use App\Events\ScanForNewReleaseCalled;
|
|
||||||
|
|
||||||
class SinglePageController extends Controller
|
class SinglePageController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the main view
|
* return the main view
|
||||||
|
*
|
||||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
@ -21,13 +20,13 @@ public function index()
|
|||||||
return view('landing')->with([
|
return view('landing')->with([
|
||||||
'appSettings' => Settings::all()->toJson(),
|
'appSettings' => Settings::all()->toJson(),
|
||||||
'appConfig' => collect([
|
'appConfig' => collect([
|
||||||
'proxyAuth' => config("auth.defaults.guard") === 'reverse-proxy-guard' ? true : false,
|
'proxyAuth' => config('auth.defaults.guard') === 'reverse-proxy-guard' ? true : false,
|
||||||
'proxyLogoutUrl' => config("2fauth.config.proxyLogoutUrl") ? config("2fauth.config.proxyLogoutUrl") : false,
|
'proxyLogoutUrl' => config('2fauth.config.proxyLogoutUrl') ? config('2fauth.config.proxyLogoutUrl') : false,
|
||||||
])->toJson(),
|
])->toJson(),
|
||||||
'lang' => App::currentLocale(),
|
'lang' => App::currentLocale(),
|
||||||
'isDemoApp' => config("2fauth.config.isDemoApp") ? 'true' : 'false',
|
'isDemoApp' => config('2fauth.config.isDemoApp') ? 'true' : 'false',
|
||||||
'isTestingApp' => config("2fauth.config.isTestingApp") ? 'true' : 'false',
|
'isTestingApp' => config('2fauth.config.isTestingApp') ? 'true' : 'false',
|
||||||
'locales' => collect(config("2fauth.locales"))->toJson() /** @phpstan-ignore-line */
|
'locales' => collect(config('2fauth.locales'))->toJson(), /** @phpstan-ignore-line */
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Services\ReleaseRadarService;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
|
use App\Services\ReleaseRadarService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
@ -17,7 +16,7 @@ class SystemController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function infos(Request $request)
|
public function infos(Request $request)
|
||||||
{
|
{
|
||||||
$infos = array();
|
$infos = [];
|
||||||
$infos['Date'] = date(DATE_RFC2822);
|
$infos['Date'] = date(DATE_RFC2822);
|
||||||
$infos['userAgent'] = $request->header('user-agent');
|
$infos['userAgent'] = $request->header('user-agent');
|
||||||
// App info
|
// App info
|
||||||
@ -50,7 +49,6 @@ public function infos(Request $request)
|
|||||||
return response()->json($infos);
|
return response()->json($infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get latest release
|
* Get latest release
|
||||||
*
|
*
|
||||||
|
@ -20,8 +20,7 @@ protected function authenticate($request, array $guards)
|
|||||||
if (empty($guards)) {
|
if (empty($guards)) {
|
||||||
// Will retreive the default guard
|
// Will retreive the default guard
|
||||||
$guards = [null];
|
$guards = [null];
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// We replace routes guard by the reverse proxy guard if necessary
|
// We replace routes guard by the reverse proxy guard if necessary
|
||||||
$proxyGuard = 'reverse-proxy-guard';
|
$proxyGuard = 'reverse-proxy-guard';
|
||||||
|
|
||||||
@ -33,11 +32,11 @@ protected function authenticate($request, array $guards)
|
|||||||
foreach ($guards as $guard) {
|
foreach ($guards as $guard) {
|
||||||
if ($this->auth->guard($guard)->check()) {
|
if ($this->auth->guard($guard)->check()) {
|
||||||
$this->auth->shouldUse($guard);
|
$this->auth->shouldUse($guard);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->unauthenticated($request, $guards);
|
$this->unauthenticated($request, $guards);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
class CustomCreateFreshApiToken extends CreateFreshApiToken
|
class CustomCreateFreshApiToken extends CreateFreshApiToken
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the request should receive a fresh token.
|
* Determine if the request should receive a fresh token.
|
||||||
*
|
*
|
||||||
@ -15,6 +14,6 @@ class CustomCreateFreshApiToken extends CreateFreshApiToken
|
|||||||
*/
|
*/
|
||||||
protected function requestShouldReceiveFreshToken($request)
|
protected function requestShouldReceiveFreshToken($request)
|
||||||
{
|
{
|
||||||
return !is_null($request->user($this->guard));
|
return ! is_null($request->user($this->guard));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
use App\Facades\Settings;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Closure;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use App\Facades\Settings;
|
|
||||||
|
|
||||||
class KickOutInactiveUser
|
class KickOutInactiveUser
|
||||||
{
|
{
|
||||||
@ -38,7 +38,6 @@ public function handle($request, Closure $next, ...$guards)
|
|||||||
|
|
||||||
// If user has been inactive longer than the allowed inactivity period
|
// If user has been inactive longer than the allowed inactivity period
|
||||||
if ($kickUserAfterXSecond > 0 && $inactiveFor > $kickUserAfterXSecond) {
|
if ($kickUserAfterXSecond > 0 && $inactiveFor > $kickUserAfterXSecond) {
|
||||||
|
|
||||||
$user->last_seen_at = $now->format('Y-m-d H:i:s');
|
$user->last_seen_at = $now->format('Y-m-d H:i:s');
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Closure;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class LogUserLastSeen
|
class LogUserLastSeen
|
||||||
@ -25,7 +25,7 @@ public function handle($request, Closure $next, ...$guards)
|
|||||||
// - Guest
|
// - Guest
|
||||||
// - User authenticated against a bearer token
|
// - User authenticated against a bearer token
|
||||||
// - User authenticated via a reverse-proxy
|
// - User authenticated via a reverse-proxy
|
||||||
if (Auth::guard($guard)->check() && !$request->bearerToken() && config('auth.defaults.guard') !== 'reverse-proxy-guard') {
|
if (Auth::guard($guard)->check() && ! $request->bearerToken() && config('auth.defaults.guard') !== 'reverse-proxy-guard') {
|
||||||
Auth::guard($guard)->user()->last_seen_at = Carbon::now()->format('Y-m-d H:i:s');
|
Auth::guard($guard)->user()->last_seen_at = Carbon::now()->format('Y-m-d H:i:s');
|
||||||
Auth::guard($guard)->user()->save();
|
Auth::guard($guard)->user()->save();
|
||||||
break;
|
break;
|
||||||
|
@ -17,8 +17,7 @@ class RejectIfDemoMode
|
|||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
|
if (config('2fauth.config.isDemoApp')) {
|
||||||
if( config('2fauth.config.isDemoApp') ) {
|
|
||||||
Log::info('Cannot request this action in Demo mode');
|
Log::info('Cannot request this action in Demo mode');
|
||||||
|
|
||||||
return response()->json(['message' => __('auth.forms.disabled_in_demo')], Response::HTTP_UNAUTHORIZED);
|
return response()->json(['message' => __('auth.forms.disabled_in_demo')], Response::HTTP_UNAUTHORIZED);
|
||||||
|
@ -20,7 +20,8 @@ public function handle($request, Closure $next)
|
|||||||
Log::info('Cannot request this action in Demo mode');
|
Log::info('Cannot request this action in Demo mode');
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => __('errors.unsupported_with_reverseproxy')], 400);
|
'message' => __('errors.unsupported_with_reverseproxy'),
|
||||||
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Facades\Settings;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use App\Facades\Settings;
|
|
||||||
|
|
||||||
class SetLanguage
|
class SetLanguage
|
||||||
{
|
{
|
||||||
@ -26,16 +26,17 @@ public function handle($request, Closure $next)
|
|||||||
// FI: Settings::get() always returns a fallback value
|
// FI: Settings::get() always returns a fallback value
|
||||||
$lang = Settings::get('lang');
|
$lang = Settings::get('lang');
|
||||||
|
|
||||||
if($lang === 'browser') {
|
if ($lang === 'browser') {
|
||||||
$lang = config('app.fallback_locale');
|
$lang = config('app.fallback_locale');
|
||||||
$accepted = str_replace(' ', '', $request->header("Accept-Language"));
|
$accepted = str_replace(' ', '', $request->header('Accept-Language'));
|
||||||
|
|
||||||
if ($accepted && $accepted !== '*') {
|
if ($accepted && $accepted !== '*') {
|
||||||
$prefLocales = array_reduce(
|
$prefLocales = array_reduce(
|
||||||
array_diff(explode(',', $accepted), ['*']),
|
array_diff(explode(',', $accepted), ['*']),
|
||||||
function ($res, $el) {
|
function ($res, $el) {
|
||||||
list($l, $q) = array_merge(explode(';q=', $el), [1]);
|
[$l, $q] = array_merge(explode(';q=', $el), [1]);
|
||||||
$res[$l] = (float) $q;
|
$res[$l] = (float) $q;
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
|
@ -26,7 +26,7 @@ public function handle(Request $request, Closure $next, ...$guards)
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'authenticated',
|
'message' => 'authenticated',
|
||||||
'name' => $user
|
'name' => $user,
|
||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,7 @@ class TrustProxies extends Middleware
|
|||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $headers =
|
protected $headers = Request::HEADER_X_FORWARDED_FOR |
|
||||||
Request::HEADER_X_FORWARDED_FOR |
|
|
||||||
Request::HEADER_X_FORWARDED_HOST |
|
Request::HEADER_X_FORWARDED_HOST |
|
||||||
Request::HEADER_X_FORWARDED_PORT |
|
Request::HEADER_X_FORWARDED_PORT |
|
||||||
Request::HEADER_X_FORWARDED_PROTO |
|
Request::HEADER_X_FORWARDED_PROTO |
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Validation\Rule;
|
|
||||||
|
|
||||||
|
|
||||||
class LoginRequest extends FormRequest
|
class LoginRequest extends FormRequest
|
||||||
{
|
{
|
||||||
@ -30,7 +27,7 @@ public function rules()
|
|||||||
'email' => [
|
'email' => [
|
||||||
'required',
|
'required',
|
||||||
'email',
|
'email',
|
||||||
new \App\Rules\CaseInsensitiveEmailExists
|
new \App\Rules\CaseInsensitiveEmailExists,
|
||||||
],
|
],
|
||||||
'password' => 'required|string',
|
'password' => 'required|string',
|
||||||
];
|
];
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
|
||||||
class UserDeleteRequest extends FormRequest
|
class UserDeleteRequest extends FormRequest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class WebauthnDeviceLostRequest extends FormRequest
|
class WebauthnDeviceLostRequest extends FormRequest
|
||||||
{
|
{
|
||||||
@ -28,7 +27,7 @@ public function rules()
|
|||||||
'email' => [
|
'email' => [
|
||||||
'required',
|
'required',
|
||||||
'email',
|
'email',
|
||||||
new \App\Rules\CaseInsensitiveEmailExists
|
new \App\Rules\CaseInsensitiveEmailExists,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class WebauthnRecoveryRequest extends FormRequest
|
class WebauthnRecoveryRequest extends FormRequest
|
||||||
{
|
{
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
use App\Events\GroupDeleting;
|
use App\Events\GroupDeleting;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class DissociateTwofaccountFromGroup
|
class DissociateTwofaccountFromGroup
|
||||||
@ -28,7 +28,7 @@ public function handle(GroupDeleting $event)
|
|||||||
{
|
{
|
||||||
TwoFAccount::where('group_id', $event->group->id)
|
TwoFAccount::where('group_id', $event->group->id)
|
||||||
->update(
|
->update(
|
||||||
['group_id' => NULL]
|
['group_id' => null]
|
||||||
);
|
);
|
||||||
|
|
||||||
Log::info(sprintf('TwoFAccounts dissociated from group #%d', $event->group->id));
|
Log::info(sprintf('TwoFAccounts dissociated from group #%d', $event->group->id));
|
||||||
|
@ -4,22 +4,19 @@
|
|||||||
|
|
||||||
use App\Events\ScanForNewReleaseCalled;
|
use App\Events\ScanForNewReleaseCalled;
|
||||||
use App\Services\ReleaseRadarService;
|
use App\Services\ReleaseRadarService;
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ReleaseRadar
|
class ReleaseRadar
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var ReleaseRadarService $releaseRadar
|
* @var ReleaseRadarService
|
||||||
*/
|
*/
|
||||||
protected $releaseRadar;
|
protected $releaseRadar;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the event listener.
|
* Create the event listener.
|
||||||
*
|
*
|
||||||
* @param \App\Services\ReleaseRadarService $releaseRadar
|
* @param \App\Services\ReleaseRadarService $releaseRadar
|
||||||
*
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(ReleaseRadarService $releaseRadar)
|
public function __construct(ReleaseRadarService $releaseRadar)
|
||||||
@ -27,7 +24,6 @@ public function __construct(ReleaseRadarService $releaseRadar)
|
|||||||
$this->releaseRadar = $releaseRadar;
|
$this->releaseRadar = $releaseRadar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the event.
|
* Handle the event.
|
||||||
*
|
*
|
||||||
|
@ -3,16 +3,15 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Events\GroupDeleting;
|
use App\Events\GroupDeleting;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $twofaccounts_count
|
* @property int $twofaccounts_count
|
||||||
*/
|
*/
|
||||||
class Group extends Model
|
class Group extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +21,6 @@ class Group extends Model
|
|||||||
*/
|
*/
|
||||||
protected $fillable = ['name'];
|
protected $fillable = ['name'];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessors to append to the model's array form.
|
* The accessors to append to the model's array form.
|
||||||
*
|
*
|
||||||
@ -30,7 +28,6 @@ class Group extends Model
|
|||||||
*/
|
*/
|
||||||
protected $appends = [];
|
protected $appends = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be hidden for arrays.
|
* The attributes that should be hidden for arrays.
|
||||||
*
|
*
|
||||||
@ -38,7 +35,6 @@ class Group extends Model
|
|||||||
*/
|
*/
|
||||||
protected $hidden = ['created_at', 'updated_at'];
|
protected $hidden = ['created_at', 'updated_at'];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be cast.
|
* The attributes that should be cast.
|
||||||
*
|
*
|
||||||
@ -48,7 +44,6 @@ class Group extends Model
|
|||||||
'twofaccounts_count' => 'integer',
|
'twofaccounts_count' => 'integer',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event map for the model.
|
* The event map for the model.
|
||||||
*
|
*
|
||||||
@ -58,7 +53,6 @@ class Group extends Model
|
|||||||
'deleting' => GroupDeleting::class,
|
'deleting' => GroupDeleting::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override The "booting" method of the model
|
* Override The "booting" method of the model
|
||||||
*
|
*
|
||||||
@ -75,7 +69,6 @@ protected static function boot()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the TwoFAccounts of the group.
|
* Get the TwoFAccounts of the group.
|
||||||
*
|
*
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
|
||||||
class Option extends Model
|
class Option extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -17,7 +16,6 @@ class Option extends Model
|
|||||||
'value',
|
'value',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the model should be timestamped.
|
* Indicates if the model should be timestamped.
|
||||||
*
|
*
|
||||||
@ -25,12 +23,10 @@ class Option extends Model
|
|||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Casts.
|
* Casts.
|
||||||
*
|
*
|
||||||
* @var array<string, string>
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
protected $casts = [];
|
protected $casts = [];
|
||||||
|
|
||||||
}
|
}
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models\Traits;
|
namespace App\Models\Traits;
|
||||||
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use App\Notifications\WebauthnRecoveryNotification;
|
use App\Notifications\WebauthnRecoveryNotification;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see \App\Models\WebAuthnAuthenticatable
|
* @see \App\Models\WebAuthnAuthenticatable
|
||||||
@ -17,7 +17,7 @@ trait WebAuthnManageCredentials
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function userHandle(): string
|
public function userHandle() : string
|
||||||
{
|
{
|
||||||
// Laragear\WebAuthn uses Ramsey\Uuid\Uuid::fromString()->getHex()->toString()
|
// Laragear\WebAuthn uses Ramsey\Uuid\Uuid::fromString()->getHex()->toString()
|
||||||
// to obtain a UUID v4 with dashes removed and uses it as user_id (aka userHandle)
|
// to obtain a UUID v4 with dashes removed and uses it as user_id (aka userHandle)
|
||||||
@ -28,7 +28,6 @@ public function userHandle(): string
|
|||||||
?? str_replace('-', '', Str::uuid()->toString());
|
?? str_replace('-', '', Str::uuid()->toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a new alias for a given WebAuthn credential.
|
* Saves a new alias for a given WebAuthn credential.
|
||||||
*
|
*
|
||||||
@ -36,19 +35,18 @@ public function userHandle(): string
|
|||||||
* @param string $alias
|
* @param string $alias
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function renameCredential(string $id, string $alias): bool
|
public function renameCredential(string $id, string $alias) : bool
|
||||||
{
|
{
|
||||||
return boolval($this->webAuthnCredentials()->whereKey($id)->update(['alias' => $alias]));
|
return boolval($this->webAuthnCredentials()->whereKey($id)->update(['alias' => $alias]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes one or more credentials previously registered.
|
* Removes one or more credentials previously registered.
|
||||||
*
|
*
|
||||||
* @param string|array $id
|
* @param string|array $id
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function flushCredential($id): void
|
public function flushCredential($id) : void
|
||||||
{
|
{
|
||||||
if (! $this->relationLoaded('webAuthnCredentials')) {
|
if (! $this->relationLoaded('webAuthnCredentials')) {
|
||||||
$this->webAuthnCredentials()->whereKey($id)->delete();
|
$this->webAuthnCredentials()->whereKey($id)->delete();
|
||||||
@ -63,15 +61,13 @@ public function flushCredential($id): void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a webauthn recovery email to the user.
|
* Sends a webauthn recovery email to the user.
|
||||||
*
|
*
|
||||||
* @param string $token
|
* @param string $token
|
||||||
*
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendWebauthnRecoveryNotification(string $token): void
|
public function sendWebauthnRecoveryNotification(string $token) : void
|
||||||
{
|
{
|
||||||
// $accountRecoveryNotification = new WebauthnRecoveryNotification($token);
|
// $accountRecoveryNotification = new WebauthnRecoveryNotification($token);
|
||||||
// $accountRecoveryNotification->toMailUsing(null);
|
// $accountRecoveryNotification->toMailUsing(null);
|
||||||
@ -92,6 +88,5 @@ public function sendWebauthnRecoveryNotification(string $token): void
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
$this->notify(new WebauthnRecoveryNotification($token));
|
$this->notify(new WebauthnRecoveryNotification($token));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,55 +2,62 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use App\Services\LogoService;
|
|
||||||
use App\Facades\Settings;
|
|
||||||
use App\Models\Dto\TotpDto;
|
|
||||||
use App\Models\Dto\HotpDto;
|
|
||||||
use App\Events\TwoFAccountDeleted;
|
use App\Events\TwoFAccountDeleted;
|
||||||
use App\Exceptions\InvalidSecretException;
|
|
||||||
use App\Exceptions\InvalidOtpParameterException;
|
use App\Exceptions\InvalidOtpParameterException;
|
||||||
use App\Exceptions\UnsupportedOtpTypeException;
|
use App\Exceptions\InvalidSecretException;
|
||||||
use App\Exceptions\UndecipherableException;
|
use App\Exceptions\UndecipherableException;
|
||||||
use Illuminate\Validation\ValidationException;
|
use App\Exceptions\UnsupportedOtpTypeException;
|
||||||
use Spatie\EloquentSortable\Sortable;
|
use App\Facades\Settings;
|
||||||
use Spatie\EloquentSortable\SortableTrait;
|
use App\Helpers\Helpers;
|
||||||
use OTPHP\TOTP;
|
use App\Models\Dto\HotpDto;
|
||||||
use OTPHP\HOTP;
|
use App\Models\Dto\TotpDto;
|
||||||
use OTPHP\Factory;
|
use App\Services\LogoService;
|
||||||
use SteamTotp\SteamTotp;
|
use Exception;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use OTPHP\Factory;
|
||||||
|
use OTPHP\HOTP;
|
||||||
|
use OTPHP\TOTP;
|
||||||
use ParagonIE\ConstantTime\Base32;
|
use ParagonIE\ConstantTime\Base32;
|
||||||
use Illuminate\Support\Facades\App;
|
use Spatie\EloquentSortable\Sortable;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Spatie\EloquentSortable\SortableTrait;
|
||||||
use App\Helpers\Helpers;
|
use SteamTotp\SteamTotp;
|
||||||
|
|
||||||
class TwoFAccount extends Model implements Sortable
|
class TwoFAccount extends Model implements Sortable
|
||||||
{
|
{
|
||||||
|
|
||||||
use SortableTrait, HasFactory;
|
use SortableTrait, HasFactory;
|
||||||
|
|
||||||
const TOTP = 'totp';
|
const TOTP = 'totp';
|
||||||
|
|
||||||
const HOTP = 'hotp';
|
const HOTP = 'hotp';
|
||||||
|
|
||||||
const STEAM_TOTP = 'steamtotp';
|
const STEAM_TOTP = 'steamtotp';
|
||||||
|
|
||||||
const SHA1 = 'sha1';
|
const SHA1 = 'sha1';
|
||||||
|
|
||||||
const MD5 = 'md5';
|
const MD5 = 'md5';
|
||||||
|
|
||||||
const SHA256 = 'sha256';
|
const SHA256 = 'sha256';
|
||||||
|
|
||||||
const SHA512 = 'sha512';
|
const SHA512 = 'sha512';
|
||||||
|
|
||||||
const DEFAULT_PERIOD = 30;
|
const DEFAULT_PERIOD = 30;
|
||||||
|
|
||||||
const DEFAULT_COUNTER = 0;
|
const DEFAULT_COUNTER = 0;
|
||||||
|
|
||||||
const DEFAULT_DIGITS = 6;
|
const DEFAULT_DIGITS = 6;
|
||||||
|
|
||||||
const DEFAULT_ALGORITHM = self::SHA1;
|
const DEFAULT_ALGORITHM = self::SHA1;
|
||||||
|
|
||||||
const DUPLICATE_ID = -1;
|
const DUPLICATE_ID = -1;
|
||||||
|
|
||||||
const FAKE_ID = -2;
|
const FAKE_ID = -2;
|
||||||
|
|
||||||
private const IMAGELINK_STORAGE_PATH = 'imagesLink/';
|
private const IMAGELINK_STORAGE_PATH = 'imagesLink/';
|
||||||
@ -80,7 +87,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
// 'icon'
|
// 'icon'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The table associated with the model.
|
* The table associated with the model.
|
||||||
*
|
*
|
||||||
@ -88,7 +94,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
*/
|
*/
|
||||||
protected $table = 'twofaccounts';
|
protected $table = 'twofaccounts';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessors to append to the model's array form.
|
* The accessors to append to the model's array form.
|
||||||
*
|
*
|
||||||
@ -96,7 +101,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
*/
|
*/
|
||||||
public $appends = [];
|
public $appends = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model's default values for attributes.
|
* The model's default values for attributes.
|
||||||
*
|
*
|
||||||
@ -107,7 +111,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
'algorithm' => self::SHA1,
|
'algorithm' => self::SHA1,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be hidden for arrays.
|
* The attributes that should be hidden for arrays.
|
||||||
*
|
*
|
||||||
@ -115,7 +118,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
*/
|
*/
|
||||||
protected $hidden = [];
|
protected $hidden = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be cast.
|
* The attributes that should be cast.
|
||||||
*
|
*
|
||||||
@ -123,7 +125,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
*/
|
*/
|
||||||
protected $casts = [];
|
protected $casts = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event map for the model.
|
* The event map for the model.
|
||||||
*
|
*
|
||||||
@ -133,7 +134,6 @@ class TwoFAccount extends Model implements Sortable
|
|||||||
'deleted' => TwoFAccountDeleted::class,
|
'deleted' => TwoFAccountDeleted::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override The "booting" method of the model
|
* Override The "booting" method of the model
|
||||||
*
|
*
|
||||||
@ -144,9 +144,15 @@ protected static function boot()
|
|||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
static::saving(function (TwoFAccount $twofaccount) {
|
static::saving(function (TwoFAccount $twofaccount) {
|
||||||
if (!$twofaccount->legacy_uri) $twofaccount->legacy_uri = $twofaccount->getURI();
|
if (! $twofaccount->legacy_uri) {
|
||||||
if ($twofaccount->otp_type == TwoFAccount::TOTP && !$twofaccount->period) $twofaccount->period = TwoFAccount::DEFAULT_PERIOD;
|
$twofaccount->legacy_uri = $twofaccount->getURI();
|
||||||
if ($twofaccount->otp_type == TwoFAccount::HOTP && !$twofaccount->counter) $twofaccount->counter = TwoFAccount::DEFAULT_COUNTER;
|
}
|
||||||
|
if ($twofaccount->otp_type == TwoFAccount::TOTP && ! $twofaccount->period) {
|
||||||
|
$twofaccount->period = TwoFAccount::DEFAULT_PERIOD;
|
||||||
|
}
|
||||||
|
if ($twofaccount->otp_type == TwoFAccount::HOTP && ! $twofaccount->counter) {
|
||||||
|
$twofaccount->counter = TwoFAccount::DEFAULT_COUNTER;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// static::deleted(function ($model) {
|
// static::deleted(function ($model) {
|
||||||
@ -154,7 +160,6 @@ protected static function boot()
|
|||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings for @spatie/eloquent-sortable package
|
* Settings for @spatie/eloquent-sortable package
|
||||||
*
|
*
|
||||||
@ -165,7 +170,6 @@ protected static function boot()
|
|||||||
'sort_when_creating' => true,
|
'sort_when_creating' => true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The OTP generator.
|
* The OTP generator.
|
||||||
* Instanciated as null to keep the model light
|
* Instanciated as null to keep the model light
|
||||||
@ -174,7 +178,6 @@ protected static function boot()
|
|||||||
*/
|
*/
|
||||||
protected $generator = null;
|
protected $generator = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get legacy_uri attribute
|
* Get legacy_uri attribute
|
||||||
*
|
*
|
||||||
@ -183,9 +186,9 @@ protected static function boot()
|
|||||||
*/
|
*/
|
||||||
public function getLegacyUriAttribute($value)
|
public function getLegacyUriAttribute($value)
|
||||||
{
|
{
|
||||||
|
|
||||||
return $this->decryptOrReturn($value);
|
return $this->decryptOrReturn($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set legacy_uri attribute
|
* Set legacy_uri attribute
|
||||||
*
|
*
|
||||||
@ -198,7 +201,6 @@ public function setLegacyUriAttribute($value)
|
|||||||
$this->attributes['legacy_uri'] = $this->encryptOrReturn($value);
|
$this->attributes['legacy_uri'] = $this->encryptOrReturn($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get account attribute
|
* Get account attribute
|
||||||
*
|
*
|
||||||
@ -207,9 +209,9 @@ public function setLegacyUriAttribute($value)
|
|||||||
*/
|
*/
|
||||||
public function getAccountAttribute($value)
|
public function getAccountAttribute($value)
|
||||||
{
|
{
|
||||||
|
|
||||||
return $this->decryptOrReturn($value);
|
return $this->decryptOrReturn($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set account attribute
|
* Set account attribute
|
||||||
*
|
*
|
||||||
@ -222,7 +224,6 @@ public function setAccountAttribute($value)
|
|||||||
$this->attributes['account'] = $this->encryptOrReturn($value);
|
$this->attributes['account'] = $this->encryptOrReturn($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get secret attribute
|
* Get secret attribute
|
||||||
*
|
*
|
||||||
@ -231,9 +232,9 @@ public function setAccountAttribute($value)
|
|||||||
*/
|
*/
|
||||||
public function getSecretAttribute($value)
|
public function getSecretAttribute($value)
|
||||||
{
|
{
|
||||||
|
|
||||||
return $this->decryptOrReturn($value);
|
return $this->decryptOrReturn($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set secret attribute
|
* Set secret attribute
|
||||||
*
|
*
|
||||||
@ -246,7 +247,6 @@ public function setSecretAttribute($value)
|
|||||||
$this->attributes['secret'] = $this->encryptOrReturn($value);
|
$this->attributes['secret'] = $this->encryptOrReturn($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set digits attribute
|
* Set digits attribute
|
||||||
*
|
*
|
||||||
@ -255,10 +255,9 @@ public function setSecretAttribute($value)
|
|||||||
*/
|
*/
|
||||||
public function setDigitsAttribute($value)
|
public function setDigitsAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['digits'] = !$value ? 6 : $value;
|
$this->attributes['digits'] = ! $value ? 6 : $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set algorithm attribute
|
* Set algorithm attribute
|
||||||
*
|
*
|
||||||
@ -267,10 +266,9 @@ public function setDigitsAttribute($value)
|
|||||||
*/
|
*/
|
||||||
public function setAlgorithmAttribute($value)
|
public function setAlgorithmAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['algorithm'] = !$value ? self::SHA1 : strtolower($value);
|
$this->attributes['algorithm'] = ! $value ? self::SHA1 : strtolower($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set period attribute
|
* Set period attribute
|
||||||
*
|
*
|
||||||
@ -279,10 +277,9 @@ public function setAlgorithmAttribute($value)
|
|||||||
*/
|
*/
|
||||||
public function setPeriodAttribute($value)
|
public function setPeriodAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['period'] = !$value && $this->otp_type === self::TOTP ? self::DEFAULT_PERIOD : $value;
|
$this->attributes['period'] = ! $value && $this->otp_type === self::TOTP ? self::DEFAULT_PERIOD : $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set counter attribute
|
* Set counter attribute
|
||||||
*
|
*
|
||||||
@ -294,19 +291,19 @@ public function setCounterAttribute($value)
|
|||||||
$this->attributes['counter'] = blank($value) && $this->otp_type === self::HOTP ? self::DEFAULT_COUNTER : $value;
|
$this->attributes['counter'] = blank($value) && $this->otp_type === self::HOTP ? self::DEFAULT_COUNTER : $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a One-Time Password with its parameters
|
* Returns a One-Time Password with its parameters
|
||||||
*
|
*
|
||||||
|
* @return TotpDto|HotpDto
|
||||||
|
*
|
||||||
* @throws InvalidSecretException The secret is not a valid base32 encoded string
|
* @throws InvalidSecretException The secret is not a valid base32 encoded string
|
||||||
* @throws UndecipherableException The secret cannot be deciphered
|
* @throws UndecipherableException The secret cannot be deciphered
|
||||||
* @throws UnsupportedOtpTypeException The defined OTP type is not supported
|
* @throws UnsupportedOtpTypeException The defined OTP type is not supported
|
||||||
* @throws InvalidOtpParameterException One OTP parameter is invalid
|
* @throws InvalidOtpParameterException One OTP parameter is invalid
|
||||||
* @return TotpDto|HotpDto
|
|
||||||
*/
|
*/
|
||||||
public function getOTP()
|
public function getOTP()
|
||||||
{
|
{
|
||||||
Log::info(sprintf('OTP requested for TwoFAccount (%s)', $this->id ? 'id:'.$this->id: 'preview'));
|
Log::info(sprintf('OTP requested for TwoFAccount (%s)', $this->id ? 'id:' . $this->id : 'preview'));
|
||||||
|
|
||||||
// Early exit if the model has an undecipherable secret
|
// Early exit if the model has an undecipherable secret
|
||||||
if (strtolower($this->secret) === __('errors.indecipherable')) {
|
if (strtolower($this->secret) === __('errors.indecipherable')) {
|
||||||
@ -318,8 +315,7 @@ public function getOTP()
|
|||||||
$this->initGenerator();
|
$this->initGenerator();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ( $this->otp_type === self::HOTP ) {
|
if ($this->otp_type === self::HOTP) {
|
||||||
|
|
||||||
$OtpDto = new HotpDto();
|
$OtpDto = new HotpDto();
|
||||||
$OtpDto->otp_type = $this->otp_type;
|
$OtpDto->otp_type = $this->otp_type;
|
||||||
$counter = $this->generator->getParameter('counter');
|
$counter = $this->generator->getParameter('counter');
|
||||||
@ -330,9 +326,7 @@ public function getOTP()
|
|||||||
if ($this->id) {
|
if ($this->id) {
|
||||||
$this->save();
|
$this->save();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
|
|
||||||
$OtpDto = new TotpDto();
|
$OtpDto = new TotpDto();
|
||||||
$OtpDto->otp_type = $this->otp_type;
|
$OtpDto->otp_type = $this->otp_type;
|
||||||
$OtpDto->generated_at = time();
|
$OtpDto->generated_at = time();
|
||||||
@ -342,12 +336,10 @@ public function getOTP()
|
|||||||
$OtpDto->period = $this->period;
|
$OtpDto->period = $this->period;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info(sprintf('New OTP generated for TwoFAccount (%s)', $this->id ? 'id:'.$this->id: 'preview'));
|
Log::info(sprintf('New OTP generated for TwoFAccount (%s)', $this->id ? 'id:' . $this->id : 'preview'));
|
||||||
|
|
||||||
return $OtpDto;
|
return $OtpDto;
|
||||||
|
} catch (\Exception|\Throwable $ex) {
|
||||||
}
|
|
||||||
catch (\Exception|\Throwable $ex) {
|
|
||||||
Log::error('An error occured, OTP generation aborted');
|
Log::error('An error occured, OTP generation aborted');
|
||||||
// Currently a secret issue is the only possible exception thrown by OTPHP for this stack
|
// Currently a secret issue is the only possible exception thrown by OTPHP for this stack
|
||||||
// so it is Ok to send the corresponding 2FAuth exception.
|
// so it is Ok to send the corresponding 2FAuth exception.
|
||||||
@ -356,7 +348,6 @@ public function getOTP()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the model using an array of OTP parameters.
|
* Fill the model using an array of OTP parameters.
|
||||||
* Missing parameters will be set with default values
|
* Missing parameters will be set with default values
|
||||||
@ -385,11 +376,11 @@ public function fillWithOtpParameters(array $parameters, bool $skipIconFetching
|
|||||||
$this->enforceAsSteam();
|
$this->enforceAsSteam();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->icon && $skipIconFetching) {
|
if (! $this->icon && $skipIconFetching) {
|
||||||
$this->icon = $this->getDefaultIcon();
|
$this->icon = $this->getDefaultIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->icon && Settings::get('getOfficialIcons') && !$skipIconFetching) {
|
if (! $this->icon && Settings::get('getOfficialIcons') && ! $skipIconFetching) {
|
||||||
$this->icon = $this->getDefaultIcon();
|
$this->icon = $this->getDefaultIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +389,6 @@ public function fillWithOtpParameters(array $parameters, bool $skipIconFetching
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the model by parsing an otpauth URI
|
* Fill the model by parsing an otpauth URI
|
||||||
*
|
*
|
||||||
@ -409,20 +399,19 @@ public function fillWithURI(string $uri, bool $isSteamTotp = false, bool $skipIc
|
|||||||
// First we instanciate the OTP generator
|
// First we instanciate the OTP generator
|
||||||
try {
|
try {
|
||||||
$this->generator = Factory::loadFromProvisioningUri($uri);
|
$this->generator = Factory::loadFromProvisioningUri($uri);
|
||||||
}
|
} catch (\Assert\AssertionFailedException|\Assert\InvalidArgumentException|\Exception|\Throwable $ex) {
|
||||||
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']),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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->generator->getLabel() ) {
|
if (! $this->generator->getLabel()) {
|
||||||
Log::error('URI passed to fillWithURI() must contain a label');
|
Log::error('URI passed to fillWithURI() must contain a label');
|
||||||
|
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'label' => __('validation.custom.label.required')
|
'label' => __('validation.custom.label.required'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +432,7 @@ public function fillWithURI(string $uri, bool $isSteamTotp = false, bool $skipIc
|
|||||||
$this->icon = $this->storeImageAsIcon($this->generator->getParameter('image'));
|
$this->icon = $this->storeImageAsIcon($this->generator->getParameter('image'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->icon && Settings::get('getOfficialIcons') && !$skipIconFetching) {
|
if (! $this->icon && Settings::get('getOfficialIcons') && ! $skipIconFetching) {
|
||||||
$this->icon = $this->getDefaultIcon();
|
$this->icon = $this->getDefaultIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +441,6 @@ public function fillWithURI(string $uri, bool $isSteamTotp = false, bool $skipIc
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets model attributes to STEAM values
|
* Sets model attributes to STEAM values
|
||||||
*/
|
*/
|
||||||
@ -466,7 +454,6 @@ private function enforceAsSteam() : void
|
|||||||
Log::info(sprintf('TwoFAccount configured as Steam account'));
|
Log::info(sprintf('TwoFAccount configured as Steam account'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the OTP type of the instanciated OTP generator
|
* Returns the OTP type of the instanciated OTP generator
|
||||||
*
|
*
|
||||||
@ -477,7 +464,6 @@ private function getGeneratorOtpType()
|
|||||||
return Arr::get($this->generatorClassMap, get_class($this->generator));
|
return Arr::get($this->generatorClassMap, get_class($this->generator));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an otpauth URI built with model attribute values
|
* Returns an otpauth URI built with model attribute values
|
||||||
*/
|
*/
|
||||||
@ -488,9 +474,9 @@ public function getURI() : string
|
|||||||
return $this->generator->getProvisioningUri();
|
return $this->generator->getProvisioningUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instanciates the OTP generator with model attribute values
|
* Instanciates the OTP generator with model attribute values
|
||||||
|
*
|
||||||
* @throws UnsupportedOtpTypeException The defined OTP type is not supported
|
* @throws UnsupportedOtpTypeException The defined OTP type is not supported
|
||||||
* @throws InvalidOtpParameterException One OTP parameter is invalid
|
* @throws InvalidOtpParameterException One OTP parameter is invalid
|
||||||
*/
|
*/
|
||||||
@ -524,14 +510,16 @@ private function initGenerator() : void
|
|||||||
throw new UnsupportedOtpTypeException();
|
throw new UnsupportedOtpTypeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->service) $this->generator->setIssuer($this->service);
|
if ($this->service) {
|
||||||
if ($this->account) $this->generator->setLabel($this->account);
|
$this->generator->setIssuer($this->service);
|
||||||
}
|
}
|
||||||
catch (UnsupportedOtpTypeException $exception) {
|
if ($this->account) {
|
||||||
|
$this->generator->setLabel($this->account);
|
||||||
|
}
|
||||||
|
} catch (UnsupportedOtpTypeException $exception) {
|
||||||
Log::error(sprintf('%s is not an OTP type supported by the current generator', $this->otp_type));
|
Log::error(sprintf('%s is not an OTP type supported by the current generator', $this->otp_type));
|
||||||
throw $exception;
|
throw $exception;
|
||||||
}
|
} catch (\Exception|\Throwable $exception) {
|
||||||
catch (\Exception|\Throwable $exception) {
|
|
||||||
throw new InvalidOtpParameterException($exception->getMessage());
|
throw new InvalidOtpParameterException($exception->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +533,7 @@ private function storeImageAsIcon(string $url)
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$path_parts = pathinfo($url);
|
$path_parts = pathinfo($url);
|
||||||
$newFilename = Helpers::getUniqueFilename($path_parts['extension']); //Str::random(40).'.'.$path_parts['extension'];
|
$newFilename = Helpers::getUniqueFilename($path_parts['extension']);
|
||||||
$imageFile = self::IMAGELINK_STORAGE_PATH . $newFilename;
|
$imageFile = self::IMAGELINK_STORAGE_PATH . $newFilename;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -554,22 +542,19 @@ private function storeImageAsIcon(string $url)
|
|||||||
if ($response->successful()) {
|
if ($response->successful()) {
|
||||||
Storage::disk('imagesLink')->put($newFilename, $response->body());
|
Storage::disk('imagesLink')->put($newFilename, $response->body());
|
||||||
}
|
}
|
||||||
}
|
} catch (\Exception $exception) {
|
||||||
catch (\Exception $exception) {
|
|
||||||
Log::error(sprintf('Cannot fetch imageLink at "%s"', $url));
|
Log::error(sprintf('Cannot fetch imageLink at "%s"', $url));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( in_array(Storage::mimeType($imageFile), ['image/png', 'image/jpeg', 'image/webp', 'image/bmp'])
|
if (in_array(Storage::mimeType($imageFile), ['image/png', 'image/jpeg', 'image/webp', 'image/bmp'])
|
||||||
&& getimagesize(storage_path() . '/app/' . $imageFile) )
|
&& getimagesize(storage_path() . '/app/' . $imageFile)) {
|
||||||
{
|
|
||||||
// Should be a valid image, we move it to the icons disk
|
// Should be a valid image, we move it to the icons disk
|
||||||
if (Storage::disk('icons')->put($newFilename, Storage::disk('imagesLink')->get($newFilename))) {
|
if (Storage::disk('icons')->put($newFilename, Storage::disk('imagesLink')->get($newFilename))) {
|
||||||
Storage::disk('imagesLink')->delete($newFilename);
|
Storage::disk('imagesLink')->delete($newFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info(sprintf('Icon file %s stored', $newFilename));
|
Log::info(sprintf('Icon file %s stored', $newFilename));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
Storage::disk('imagesLink')->delete($newFilename);
|
Storage::disk('imagesLink')->delete($newFilename);
|
||||||
throw new \Exception('Unsupported mimeType or missing image on storage');
|
throw new \Exception('Unsupported mimeType or missing image on storage');
|
||||||
@ -581,12 +566,12 @@ private function storeImageAsIcon(string $url)
|
|||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
catch (\Exception|\Throwable $ex) {
|
catch (\Exception|\Throwable $ex) {
|
||||||
Log::error(sprintf('Icon storage failed: %s', $ex->getMessage()));
|
Log::error(sprintf('Icon storage failed: %s', $ex->getMessage()));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a logo in the tfa directory and store it as a new stand alone icon
|
* Fetch a logo in the tfa directory and store it as a new stand alone icon
|
||||||
*
|
*
|
||||||
@ -599,28 +584,23 @@ private function getDefaultIcon()
|
|||||||
return Settings::get('getOfficialIcons') ? $logoService->getIcon($this->service) : null;
|
return Settings::get('getOfficialIcons') ? $logoService->getIcon($this->service) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an acceptable value
|
* Returns an acceptable value
|
||||||
*/
|
*/
|
||||||
private function decryptOrReturn(mixed $value) : mixed
|
private function decryptOrReturn(mixed $value) : mixed
|
||||||
{
|
{
|
||||||
// Decipher when needed
|
// Decipher when needed
|
||||||
if ( Settings::get('useEncryption') && $value )
|
if (Settings::get('useEncryption') && $value) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
return Crypt::decryptString($value);
|
return Crypt::decryptString($value);
|
||||||
}
|
} catch (Exception $ex) {
|
||||||
catch (Exception $ex) {
|
|
||||||
return __('errors.indecipherable');
|
return __('errors.indecipherable');
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt a value
|
* Encrypt a value
|
||||||
*/
|
*/
|
||||||
@ -629,5 +609,4 @@ private function encryptOrReturn(mixed $value) : mixed
|
|||||||
// should be replaced by laravel 8 attribute encryption casting
|
// should be replaced by laravel 8 attribute encryption casting
|
||||||
return Settings::get('useEncryption') ? Crypt::encryptString($value) : $value;
|
return Settings::get('useEncryption') ? Crypt::encryptString($value) : $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Auth\Notifications\ResetPassword;
|
|
||||||
use Illuminate\Notifications\Notifiable;
|
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
||||||
use Laravel\Passport\HasApiTokens;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Laragear\WebAuthn\WebAuthnAuthentication;
|
|
||||||
use App\Models\Traits\WebAuthnManageCredentials;
|
use App\Models\Traits\WebAuthnManageCredentials;
|
||||||
|
use Illuminate\Auth\Notifications\ResetPassword;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Laragear\WebAuthn\WebAuthnAuthentication;
|
||||||
|
use Laravel\Passport\HasApiTokens;
|
||||||
|
|
||||||
class User extends Authenticatable implements WebAuthnAuthenticatable
|
class User extends Authenticatable implements WebAuthnAuthenticatable
|
||||||
{
|
{
|
||||||
@ -59,6 +59,7 @@ public function sendPasswordResetNotification($token)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* set Email attribute
|
* set Email attribute
|
||||||
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*/
|
*/
|
||||||
public function setEmailAttribute($value) : void
|
public function setEmailAttribute($value) : void
|
||||||
@ -66,14 +67,13 @@ public function setEmailAttribute($value) : void
|
|||||||
$this->attributes['email'] = strtolower($value);
|
$this->attributes['email'] = strtolower($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an WebAuthnAuthenticatable user from a given Credential ID.
|
* Returns an WebAuthnAuthenticatable user from a given Credential ID.
|
||||||
*
|
*
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return WebAuthnAuthenticatable|null
|
* @return WebAuthnAuthenticatable|null
|
||||||
*/
|
*/
|
||||||
public static function getFromCredentialId(string $id): ?WebAuthnAuthenticatable
|
public static function getFromCredentialId(string $id) : ?WebAuthnAuthenticatable
|
||||||
{
|
{
|
||||||
return static::whereHas(
|
return static::whereHas(
|
||||||
'webauthnCredentials',
|
'webauthnCredentials',
|
||||||
|
@ -11,8 +11,7 @@ interface WebAuthnAuthenticatable extends Authenticatable
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function userHandle(): string;
|
public function userHandle() : string;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a new alias for a given WebAuthn credential.
|
* Saves a new alias for a given WebAuthn credential.
|
||||||
@ -21,8 +20,7 @@ public function userHandle(): string;
|
|||||||
* @param string $alias
|
* @param string $alias
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function renameCredential(string $id, string $alias): bool;
|
public function renameCredential(string $id, string $alias) : bool;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes one or more credentials previously registered.
|
* Removes one or more credentials previously registered.
|
||||||
@ -30,8 +28,7 @@ public function renameCredential(string $id, string $alias): bool;
|
|||||||
* @param string|array $id
|
* @param string|array $id
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function flushCredential($id): void;
|
public function flushCredential($id) : void;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a webauthn recovery email to the user.
|
* Sends a webauthn recovery email to the user.
|
||||||
@ -39,5 +36,5 @@ public function flushCredential($id): void;
|
|||||||
* @param string $token
|
* @param string $token
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendWebauthnRecoveryNotification(string $token): void;
|
public function sendWebauthnRecoveryNotification(string $token) : void;
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
use Illuminate\Support\Facades\Blade;
|
use Illuminate\Support\Facades\Blade;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
use Laravel\Passport\Console\ClientCommand;
|
use Laravel\Passport\Console\ClientCommand;
|
||||||
use Laravel\Passport\Console\InstallCommand;
|
use Laravel\Passport\Console\InstallCommand;
|
||||||
use Laravel\Passport\Console\KeysCommand;
|
use Laravel\Passport\Console\KeysCommand;
|
||||||
|
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Extensions\RemoteUserProvider;
|
||||||
|
use App\Extensions\WebauthnCredentialBroker;
|
||||||
|
use App\Facades\Settings;
|
||||||
|
use App\Services\Auth\ReverseProxyGuard;
|
||||||
|
use Illuminate\Auth\Passwords\DatabaseTokenRepository;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use App\Services\Auth\ReverseProxyGuard;
|
|
||||||
use App\Extensions\RemoteUserProvider;
|
|
||||||
use App\Facades\Settings;
|
|
||||||
use Illuminate\Support\Facades\Config;
|
|
||||||
use RuntimeException;
|
|
||||||
use App\Extensions\WebauthnCredentialBroker;
|
|
||||||
use Illuminate\Auth\Passwords\DatabaseTokenRepository;
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
class AuthServiceProvider extends ServiceProvider
|
class AuthServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@ -24,20 +23,19 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the service provider.
|
* Register the service provider.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||||
*/
|
*/
|
||||||
public function register(): void
|
public function register() : void
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->app->singleton(
|
$this->app->singleton(
|
||||||
WebauthnCredentialBroker::class,
|
WebauthnCredentialBroker::class,
|
||||||
static function ($app) {
|
static function ($app) {
|
||||||
if (!$config = $app['config']['auth.passwords.webauthn']) {
|
if (! $config = $app['config']['auth.passwords.webauthn']) {
|
||||||
throw new RuntimeException('You must set the [webauthn] key broker in [auth] config.');
|
throw new RuntimeException('You must set the [webauthn] key broker in [auth] config.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +60,6 @@ static function ($app) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register any authentication / authorization services.
|
* Register any authentication / authorization services.
|
||||||
*
|
*
|
||||||
@ -86,7 +83,6 @@ public function boot()
|
|||||||
return new ReverseProxyGuard(Auth::createUserProvider($config['provider']));
|
return new ReverseProxyGuard(Auth::createUserProvider($config['provider']));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Previously we were using a custom user provider derived from the Larapass user provider
|
// Previously we were using a custom user provider derived from the Larapass user provider
|
||||||
// in order to honor the "useWebauthnOnly" user option.
|
// in order to honor the "useWebauthnOnly" user option.
|
||||||
// Since Laragear\WebAuthn now replaces DarkGhostHunter\Larapass, the new approach is
|
// Since Laragear\WebAuthn now replaces DarkGhostHunter\Larapass, the new approach is
|
||||||
@ -94,7 +90,7 @@ public function boot()
|
|||||||
// with a custom closure that uses the "useWebauthnOnly" user option
|
// with a custom closure that uses the "useWebauthnOnly" user option
|
||||||
Auth::provider(
|
Auth::provider(
|
||||||
'eloquent-webauthn',
|
'eloquent-webauthn',
|
||||||
static function (\Illuminate\Contracts\Foundation\Application $app, array $config): \Laragear\WebAuthn\Auth\WebAuthnUserProvider {
|
static function (\Illuminate\Contracts\Foundation\Application $app, array $config) : \Laragear\WebAuthn\Auth\WebAuthnUserProvider {
|
||||||
return new \Laragear\WebAuthn\Auth\WebAuthnUserProvider(
|
return new \Laragear\WebAuthn\Auth\WebAuthnUserProvider(
|
||||||
$app->make('hash'),
|
$app->make('hash'),
|
||||||
$config['model'],
|
$config['model'],
|
||||||
@ -104,7 +100,6 @@ static function (\Illuminate\Contracts\Foundation\Application $app, array $confi
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Normally we should set the Passport routes here using Passport::routes().
|
// Normally we should set the Passport routes here using Passport::routes().
|
||||||
// If so the passport routes would be set for both 'web' and 'api' middlewares without
|
// If so the passport routes would be set for both 'web' and 'api' middlewares without
|
||||||
// possibility to exclude the web middleware (we can only pass additional middlewares to Passport::routes())
|
// possibility to exclude the web middleware (we can only pass additional middlewares to Passport::routes())
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
|
||||||
use Illuminate\Support\Facades\Broadcast;
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class BroadcastServiceProvider extends ServiceProvider
|
class BroadcastServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Events\GroupDeleting;
|
use App\Events\GroupDeleting;
|
||||||
use App\Events\TwoFAccountDeleted;
|
|
||||||
use App\Events\ScanForNewReleaseCalled;
|
use App\Events\ScanForNewReleaseCalled;
|
||||||
use App\Listeners\ReleaseRadar;
|
use App\Events\TwoFAccountDeleted;
|
||||||
use App\Listeners\CleanIconStorage;
|
use App\Listeners\CleanIconStorage;
|
||||||
use App\Listeners\DissociateTwofaccountFromGroup;
|
use App\Listeners\DissociateTwofaccountFromGroup;
|
||||||
|
use App\Listeners\ReleaseRadar;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
use App\Factories\MigratorFactory;
|
use App\Factories\MigratorFactory;
|
||||||
use App\Factories\MigratorFactoryInterface;
|
use App\Factories\MigratorFactoryInterface;
|
||||||
use App\Services\Migrators\GoogleAuthMigrator;
|
|
||||||
use App\Services\Migrators\AegisMigrator;
|
use App\Services\Migrators\AegisMigrator;
|
||||||
|
use App\Services\Migrators\GoogleAuthMigrator;
|
||||||
use App\Services\Migrators\PlainTextMigrator;
|
use App\Services\Migrators\PlainTextMigrator;
|
||||||
use App\Services\Migrators\TwoFASMigrator;
|
use App\Services\Migrators\TwoFASMigrator;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Services\LogoService;
|
|
||||||
use App\Services\SettingService;
|
|
||||||
use App\Services\ReleaseRadarService;
|
|
||||||
use App\Services\TwoFAccountService;
|
|
||||||
use App\Factories\MigratorFactoryInterface;
|
use App\Factories\MigratorFactoryInterface;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use App\Services\LogoService;
|
||||||
|
use App\Services\ReleaseRadarService;
|
||||||
|
use App\Services\SettingService;
|
||||||
|
use App\Services\TwoFAccountService;
|
||||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class TwoFAuthServiceProvider extends ServiceProvider implements DeferrableProvider
|
class TwoFAuthServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||||
{
|
{
|
||||||
@ -46,7 +46,6 @@ public function boot()
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the services provided by the provider.
|
* Get the services provided by the provider.
|
||||||
*
|
*
|
||||||
|
@ -30,12 +30,14 @@ public function passes($attribute, $value)
|
|||||||
->whereRaw('email = \'' . strtolower($value) . '\'' . ('sqlite' === config('database.default') ? ' COLLATE NOCASE' : ''))
|
->whereRaw('email = \'' . strtolower($value) . '\'' . ('sqlite' === config('database.default') ? ' COLLATE NOCASE' : ''))
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
return !$user ? false : true;
|
return ! $user ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation error message.
|
* Get the validation error message.
|
||||||
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
* @return array|string
|
* @return array|string
|
||||||
*/
|
*/
|
||||||
public function message()
|
public function message()
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
namespace App\Services\Auth;
|
namespace App\Services\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Auth\GuardHelpers;
|
||||||
use Illuminate\Contracts\Auth\Guard;
|
use Illuminate\Contracts\Auth\Guard;
|
||||||
use Illuminate\Contracts\Auth\UserProvider;
|
use Illuminate\Contracts\Auth\UserProvider;
|
||||||
use Illuminate\Auth\GuardHelpers;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ReverseProxyGuard implements Guard
|
class ReverseProxyGuard implements Guard
|
||||||
@ -33,7 +33,7 @@ public function __construct(UserProvider $provider)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
@ -47,17 +47,17 @@ public function user()
|
|||||||
// Get the user identifier from $_SERVER or apache filtered headers
|
// Get the user identifier from $_SERVER or apache filtered headers
|
||||||
$remoteUserHeader = config('auth.auth_proxy_headers.user');
|
$remoteUserHeader = config('auth.auth_proxy_headers.user');
|
||||||
$remoteUserHeader = $remoteUserHeader ?: 'REMOTE_USER';
|
$remoteUserHeader = $remoteUserHeader ?: 'REMOTE_USER';
|
||||||
$identifier = array();
|
$identifier = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$identifier['user'] = request()->server($remoteUserHeader) ?? apache_request_headers()[$remoteUserHeader] ?? null;
|
$identifier['user'] = request()->server($remoteUserHeader) ?? apache_request_headers()[$remoteUserHeader] ?? null;
|
||||||
}
|
} catch (\Throwable $e) {
|
||||||
catch (\Throwable $e) {
|
|
||||||
$identifier['user'] = null;
|
$identifier['user'] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$identifier['user'] || is_array($identifier['user'])) {
|
if (! $identifier['user'] || is_array($identifier['user'])) {
|
||||||
Log::error(sprintf('Proxy remote-user header "%s" is empty or missing.', $remoteUserHeader));
|
Log::error(sprintf('Proxy remote-user header "%s" is empty or missing.', $remoteUserHeader));
|
||||||
|
|
||||||
return $this->user = null;
|
return $this->user = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,9 +66,8 @@ public function user()
|
|||||||
|
|
||||||
if ($remoteEmailHeader) {
|
if ($remoteEmailHeader) {
|
||||||
try {
|
try {
|
||||||
$remoteEmail = (string)(request()->server($remoteEmailHeader) ?? apache_request_headers()[$remoteEmailHeader] ?? null);
|
$remoteEmail = (string) (request()->server($remoteEmailHeader) ?? apache_request_headers()[$remoteEmailHeader] ?? null);
|
||||||
}
|
} catch (\Throwable $e) {
|
||||||
catch (\Throwable $e) {
|
|
||||||
$remoteEmail = null;
|
$remoteEmail = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Facades\Settings;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
use App\Facades\Settings;
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
|
|
||||||
class GroupService
|
class GroupService
|
||||||
{
|
{
|
||||||
@ -29,7 +28,7 @@ public static function getAll() : Collection
|
|||||||
|
|
||||||
// Create the pseudo group
|
// Create the pseudo group
|
||||||
$allGroup = new Group([
|
$allGroup = new Group([
|
||||||
'name' => __('commons.all')
|
'name' => __('commons.all'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$allGroup->id = 0;
|
$allGroup->id = 0;
|
||||||
@ -38,7 +37,6 @@ public static function getAll() : Collection
|
|||||||
return $groups->prepend($allGroup);
|
return $groups->prepend($allGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a group
|
* Creates a group
|
||||||
*
|
*
|
||||||
@ -58,7 +56,6 @@ public static function create(array $data) : Group
|
|||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a group using a list of parameters
|
* Updates a group using a list of parameters
|
||||||
*
|
*
|
||||||
@ -77,7 +74,6 @@ public static function update(Group $group, array $data) : Group
|
|||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes one or more groups
|
* Deletes one or more groups
|
||||||
*
|
*
|
||||||
@ -112,7 +108,6 @@ public static function delete($ids) : int
|
|||||||
return $deleted;
|
return $deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign one or more accounts to a group
|
* Assign one or more accounts to a group
|
||||||
*
|
*
|
||||||
@ -122,15 +117,15 @@ public static function delete($ids) : int
|
|||||||
*/
|
*/
|
||||||
public static function assign($ids, Group $group = null) : void
|
public static function assign($ids, Group $group = null) : void
|
||||||
{
|
{
|
||||||
if (!$group) {
|
if (! $group) {
|
||||||
$group = self::defaultGroup();
|
$group = self::defaultGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($group) {
|
if ($group) {
|
||||||
// saveMany() expect an iterable so we pass an array to
|
// saveMany() expect an iterable so we pass an array to
|
||||||
// find() to always obtain a list of TwoFAccount
|
// find() to always obtain a list of TwoFAccount
|
||||||
if (!is_array($ids)) {
|
if (! is_array($ids)) {
|
||||||
$ids = array($ids);
|
$ids = [$ids];
|
||||||
}
|
}
|
||||||
$twofaccounts = TwoFAccount::find($ids);
|
$twofaccounts = TwoFAccount::find($ids);
|
||||||
|
|
||||||
@ -138,11 +133,11 @@ public static function assign($ids, Group $group = null) : void
|
|||||||
$group->loadCount('twofaccounts');
|
$group->loadCount('twofaccounts');
|
||||||
|
|
||||||
Log::info(sprintf('Twofaccounts #%s assigned to groups %s', implode(',#', $ids), var_export($group->name, true)));
|
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');
|
||||||
}
|
}
|
||||||
else Log::info('Cannot find a group to assign the TwoFAccounts to');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds twofaccounts assigned to the group
|
* Finds twofaccounts assigned to the group
|
||||||
*
|
*
|
||||||
@ -156,7 +151,6 @@ public static function getAccounts(Group $group) : Collection
|
|||||||
return $twofaccounts;
|
return $twofaccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the destination group
|
* Determines the destination group
|
||||||
*
|
*
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class LogoService
|
class LogoService
|
||||||
@ -25,13 +25,11 @@ class LogoService
|
|||||||
*/
|
*/
|
||||||
const TFA_URL = 'https://2fa.directory/api/v3/tfa.json';
|
const TFA_URL = 'https://2fa.directory/api/v3/tfa.json';
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->setTfaCollection();
|
$this->setTfaCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a logo for the given service and save it as an icon
|
* Fetch a logo for the given service and save it as an icon
|
||||||
*
|
*
|
||||||
@ -43,12 +41,13 @@ public function getIcon($serviceName)
|
|||||||
$logoFilename = $this->getLogo(strval($serviceName));
|
$logoFilename = $this->getLogo(strval($serviceName));
|
||||||
|
|
||||||
if ($logoFilename) {
|
if ($logoFilename) {
|
||||||
$iconFilename = Str::random(40).'.svg';
|
$iconFilename = Str::random(40) . '.svg';
|
||||||
return $this->copyToIcons($logoFilename, $iconFilename) ? $iconFilename : null;
|
|
||||||
}
|
|
||||||
else return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return $this->copyToIcons($logoFilename, $iconFilename) ? $iconFilename : null;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the logo's filename for a given service
|
* Return the logo's filename for a given service
|
||||||
@ -59,16 +58,15 @@ public function getIcon($serviceName)
|
|||||||
protected function getLogo($serviceName)
|
protected function getLogo($serviceName)
|
||||||
{
|
{
|
||||||
$domain = $this->tfas->get($this->cleanDomain(strval($serviceName)));
|
$domain = $this->tfas->get($this->cleanDomain(strval($serviceName)));
|
||||||
$logoFilename = $domain.'.svg';
|
$logoFilename = $domain . '.svg';
|
||||||
|
|
||||||
if ($domain && !Storage::disk('logos')->exists($logoFilename)) {
|
if ($domain && ! Storage::disk('logos')->exists($logoFilename)) {
|
||||||
$this->fetchLogo($logoFilename);
|
$this->fetchLogo($logoFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Storage::disk('logos')->exists($logoFilename) ? $logoFilename : null;
|
return Storage::disk('logos')->exists($logoFilename) ? $logoFilename : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build and set the TFA directoy collection
|
* Build and set the TFA directoy collection
|
||||||
*
|
*
|
||||||
@ -90,7 +88,6 @@ protected function setTfaCollection() : void
|
|||||||
: collect([]);
|
: collect([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch and cache fresh TFA.Directory data using the https://2fa.directory API
|
* Fetch and cache fresh TFA.Directory data using the https://2fa.directory API
|
||||||
*
|
*
|
||||||
@ -104,22 +101,18 @@ protected function cacheTfaDirectorySource() : void
|
|||||||
$coll = collect(json_decode(htmlspecialchars_decode($response->body()), true)) /** @phpstan-ignore-line */
|
$coll = collect(json_decode(htmlspecialchars_decode($response->body()), true)) /** @phpstan-ignore-line */
|
||||||
->mapWithKeys(function ($item, $key) {
|
->mapWithKeys(function ($item, $key) {
|
||||||
return [
|
return [
|
||||||
strtolower(head($item)) => $item[1]["domain"]
|
strtolower(head($item)) => $item[1]['domain'],
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
Storage::disk('logos')->put(self::TFA_JSON, $coll->toJson())
|
Storage::disk('logos')->put(self::TFA_JSON, $coll->toJson())
|
||||||
? Log::info('Fresh tfa.json saved to logos dir')
|
? Log::info('Fresh tfa.json saved to logos dir')
|
||||||
: Log::notice('Cannot save tfa.json to logos dir');
|
: Log::notice('Cannot save tfa.json to logos dir');
|
||||||
|
} catch (\Exception $e) {
|
||||||
}
|
|
||||||
catch (\Exception $e) {
|
|
||||||
Log::error('Caching of tfa.json failed');
|
Log::error('Caching of tfa.json failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch and cache a logo from 2fa.Directory repository
|
* Fetch and cache a logo from 2fa.Directory repository
|
||||||
*
|
*
|
||||||
@ -130,20 +123,18 @@ protected function fetchLogo(string $logoFile) : void
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$response = Http::retry(3, 100)
|
$response = Http::retry(3, 100)
|
||||||
->get('https://raw.githubusercontent.com/2factorauth/twofactorauth/master/img/'.$logoFile[0].'/'.$logoFile);
|
->get('https://raw.githubusercontent.com/2factorauth/twofactorauth/master/img/' . $logoFile[0] . '/' . $logoFile);
|
||||||
|
|
||||||
if ($response->successful()) {
|
if ($response->successful()) {
|
||||||
Storage::disk('logos')->put($logoFile, $response->body())
|
Storage::disk('logos')->put($logoFile, $response->body())
|
||||||
? Log::info(sprintf('Logo "%s" saved to logos dir.', $logoFile))
|
? Log::info(sprintf('Logo "%s" saved to logos dir.', $logoFile))
|
||||||
: Log::notice(sprintf('Cannot save logo "%s" to logos dir', $logoFile));
|
: Log::notice(sprintf('Cannot save logo "%s" to logos dir', $logoFile));
|
||||||
}
|
}
|
||||||
}
|
} catch (\Exception $exception) {
|
||||||
catch (\Exception $exception) {
|
|
||||||
Log::error(sprintf('Fetching of logo "%s" failed.', $logoFile));
|
Log::error(sprintf('Fetching of logo "%s" failed.', $logoFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare and make some replacement to optimize logo fetching
|
* Prepare and make some replacement to optimize logo fetching
|
||||||
*
|
*
|
||||||
@ -155,7 +146,6 @@ protected function cleanDomain(string $domain) : string
|
|||||||
return strtolower(str_replace(['+'], ['plus'], $domain));
|
return strtolower(str_replace(['+'], ['plus'], $domain));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy a logo file to the icons disk with a new name
|
* Copy a logo file to the icons disk with a new name
|
||||||
*
|
*
|
||||||
|
@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Services\Migrators;
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
use App\Services\Migrators\Migrator;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use App\Exceptions\InvalidMigrationDataException;
|
use App\Exceptions\InvalidMigrationDataException;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use App\Helpers\Helpers;
|
|
||||||
use App\Facades\TwoFAccounts;
|
use App\Facades\TwoFAccounts;
|
||||||
|
use App\Helpers\Helpers;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class AegisMigrator extends Migrator
|
class AegisMigrator extends Migrator
|
||||||
{
|
{
|
||||||
@ -33,7 +32,6 @@ class AegisMigrator extends Migrator
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert migration data to a TwoFAccounts collection.
|
* Convert migration data to a TwoFAccounts collection.
|
||||||
*
|
*
|
||||||
@ -49,11 +47,10 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
throw new InvalidMigrationDataException('Aegis');
|
throw new InvalidMigrationDataException('Aegis');
|
||||||
}
|
}
|
||||||
|
|
||||||
$twofaccounts = array();
|
$twofaccounts = [];
|
||||||
|
|
||||||
foreach ($json['db']['entries'] as $key => $otp_parameters) {
|
foreach ($json['db']['entries'] as $key => $otp_parameters) {
|
||||||
|
$parameters = [];
|
||||||
$parameters = array();
|
|
||||||
$parameters['otp_type'] = $otp_parameters['type'] == 'steam' ? TwoFAccount::STEAM_TOTP : $otp_parameters['type'];
|
$parameters['otp_type'] = $otp_parameters['type'] == 'steam' ? TwoFAccount::STEAM_TOTP : $otp_parameters['type'];
|
||||||
$parameters['service'] = $otp_parameters['issuer'];
|
$parameters['service'] = $otp_parameters['issuer'];
|
||||||
$parameters['account'] = $otp_parameters['name'];
|
$parameters['account'] = $otp_parameters['name'];
|
||||||
@ -92,17 +89,14 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
Log::info(sprintf('Image %s successfully stored for import', $filename));
|
Log::info(sprintf('Image %s successfully stored for import', $filename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (\Exception) {
|
||||||
catch (\Exception) {
|
|
||||||
// we do nothing
|
// we do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$twofaccounts[$key] = new TwoFAccount;
|
$twofaccounts[$key] = new TwoFAccount;
|
||||||
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
||||||
}
|
} catch (\Exception $exception) {
|
||||||
catch (\Exception $exception) {
|
|
||||||
|
|
||||||
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
||||||
Log::error($exception->getMessage());
|
Log::error($exception->getMessage());
|
||||||
|
|
||||||
|
@ -2,23 +2,21 @@
|
|||||||
|
|
||||||
namespace App\Services\Migrators;
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
use Exception;
|
use App\Exceptions\InvalidMigrationDataException;
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
use App\Services\Migrators\Migrator;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use ParagonIE\ConstantTime\Base32;
|
|
||||||
use App\Protobuf\GAuthValueMapping;
|
use App\Protobuf\GAuthValueMapping;
|
||||||
use App\Protobuf\GoogleAuth\Payload;
|
use App\Protobuf\GoogleAuth\Payload;
|
||||||
use App\Protobuf\GoogleAuth\Payload\OtpType;
|
|
||||||
use App\Protobuf\GoogleAuth\Payload\Algorithm;
|
use App\Protobuf\GoogleAuth\Payload\Algorithm;
|
||||||
use App\Protobuf\GoogleAuth\Payload\DigitCount;
|
use App\Protobuf\GoogleAuth\Payload\DigitCount;
|
||||||
use App\Exceptions\InvalidMigrationDataException;
|
use App\Protobuf\GoogleAuth\Payload\OtpType;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use ParagonIE\ConstantTime\Base32;
|
||||||
|
|
||||||
class GoogleAuthMigrator extends Migrator
|
class GoogleAuthMigrator extends Migrator
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert Google Authenticator migration URI to a set of TwoFAccount objects.
|
* Convert Google Authenticator migration URI to a set of TwoFAccount objects.
|
||||||
*
|
*
|
||||||
@ -32,23 +30,21 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
$protobuf = new Payload();
|
$protobuf = new Payload();
|
||||||
$protobuf->mergeFromString($migrationData);
|
$protobuf->mergeFromString($migrationData);
|
||||||
$otpParameters = $protobuf->getOtpParameters();
|
$otpParameters = $protobuf->getOtpParameters();
|
||||||
}
|
} catch (Exception $ex) {
|
||||||
catch (Exception $ex) {
|
Log::error('Protobuf failed to get OTP parameters from provided migration URI');
|
||||||
Log::error("Protobuf failed to get OTP parameters from provided migration URI");
|
|
||||||
Log::error($ex->getMessage());
|
Log::error($ex->getMessage());
|
||||||
|
|
||||||
throw new InvalidMigrationDataException('Google Authenticator');
|
throw new InvalidMigrationDataException('Google Authenticator');
|
||||||
}
|
}
|
||||||
|
|
||||||
$twofaccounts = array();
|
$twofaccounts = [];
|
||||||
|
|
||||||
foreach ($otpParameters->getIterator() as $key => $otp_parameters) {
|
foreach ($otpParameters->getIterator() as $key => $otp_parameters) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$parameters = array();
|
$parameters = [];
|
||||||
$parameters['otp_type'] = GAuthValueMapping::OTP_TYPE[OtpType::name($otp_parameters->getType())];
|
$parameters['otp_type'] = GAuthValueMapping::OTP_TYPE[OtpType::name($otp_parameters->getType())];
|
||||||
$parameters['service'] = $otp_parameters->getIssuer();
|
$parameters['service'] = $otp_parameters->getIssuer();
|
||||||
$parameters['account'] = str_replace($parameters['service'].':', '', $otp_parameters->getName());
|
$parameters['account'] = str_replace($parameters['service'] . ':', '', $otp_parameters->getName());
|
||||||
$parameters['secret'] = Base32::encodeUpper($otp_parameters->getSecret());
|
$parameters['secret'] = Base32::encodeUpper($otp_parameters->getSecret());
|
||||||
$parameters['algorithm'] = GAuthValueMapping::ALGORITHM[Algorithm::name($otp_parameters->getAlgorithm())];
|
$parameters['algorithm'] = GAuthValueMapping::ALGORITHM[Algorithm::name($otp_parameters->getAlgorithm())];
|
||||||
$parameters['digits'] = GAuthValueMapping::DIGIT_COUNT[DigitCount::name($otp_parameters->getDigits())];
|
$parameters['digits'] = GAuthValueMapping::DIGIT_COUNT[DigitCount::name($otp_parameters->getDigits())];
|
||||||
@ -57,9 +53,7 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
|
|
||||||
$twofaccounts[$key] = new TwoFAccount;
|
$twofaccounts[$key] = new TwoFAccount;
|
||||||
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
||||||
}
|
} catch (Exception $exception) {
|
||||||
catch (Exception $exception) {
|
|
||||||
|
|
||||||
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
||||||
Log::error($exception->getMessage());
|
Log::error($exception->getMessage());
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ abstract class Migrator
|
|||||||
*/
|
*/
|
||||||
abstract public function migrate(mixed $migrationPayload) : Collection;
|
abstract public function migrate(mixed $migrationPayload) : Collection;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pad a string to 8 chars min
|
* Pad a string to 8 chars min
|
||||||
*
|
*
|
||||||
@ -25,5 +24,4 @@ protected function padToValidBase32Secret(string $string)
|
|||||||
{
|
{
|
||||||
return str_pad($string, 8, '=');
|
return str_pad($string, 8, '=');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Services\Migrators;
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
use App\Services\Migrators\Migrator;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use App\Exceptions\InvalidMigrationDataException;
|
use App\Exceptions\InvalidMigrationDataException;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class PlainTextMigrator extends Migrator
|
class PlainTextMigrator extends Migrator
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert migration data to a TwoFAccounts collection.
|
* Convert migration data to a TwoFAccounts collection.
|
||||||
*
|
*
|
||||||
@ -32,13 +30,10 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($otpauthURIs as $key => $uri) {
|
foreach ($otpauthURIs as $key => $uri) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$twofaccounts[$key] = new TwoFAccount;
|
$twofaccounts[$key] = new TwoFAccount;
|
||||||
$twofaccounts[$key]->fillWithURI($uri);
|
$twofaccounts[$key]->fillWithURI($uri);
|
||||||
}
|
} catch (\Exception $exception) {
|
||||||
catch (\Exception $exception) {
|
|
||||||
|
|
||||||
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
||||||
Log::error($exception->getMessage());
|
Log::error($exception->getMessage());
|
||||||
|
|
||||||
|
@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Services\Migrators;
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
use App\Services\Migrators\Migrator;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use App\Exceptions\InvalidMigrationDataException;
|
use App\Exceptions\InvalidMigrationDataException;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class TwoFASMigrator extends Migrator
|
class TwoFASMigrator extends Migrator
|
||||||
{
|
{
|
||||||
@ -65,7 +64,6 @@ class TwoFASMigrator extends Migrator
|
|||||||
// "appVersionName": "3.20.1"
|
// "appVersionName": "3.20.1"
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert migration data to a TwoFAccounts collection.
|
* Convert migration data to a TwoFAccounts collection.
|
||||||
*
|
*
|
||||||
@ -81,11 +79,10 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
throw new InvalidMigrationDataException('2FAS Auth');
|
throw new InvalidMigrationDataException('2FAS Auth');
|
||||||
}
|
}
|
||||||
|
|
||||||
$twofaccounts = array();
|
$twofaccounts = [];
|
||||||
|
|
||||||
foreach ($json['services'] as $key => $otp_parameters) {
|
foreach ($json['services'] as $key => $otp_parameters) {
|
||||||
|
$parameters = [];
|
||||||
$parameters = array();
|
|
||||||
$parameters['otp_type'] = $otp_parameters['otp']['tokenType'];
|
$parameters['otp_type'] = $otp_parameters['otp']['tokenType'];
|
||||||
$parameters['service'] = $otp_parameters['name'];
|
$parameters['service'] = $otp_parameters['name'];
|
||||||
$parameters['account'] = $otp_parameters['otp']['account'] ?? $parameters['service'];
|
$parameters['account'] = $otp_parameters['otp']['account'] ?? $parameters['service'];
|
||||||
@ -98,9 +95,7 @@ public function migrate(mixed $migrationPayload) : Collection
|
|||||||
try {
|
try {
|
||||||
$twofaccounts[$key] = new TwoFAccount;
|
$twofaccounts[$key] = new TwoFAccount;
|
||||||
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
||||||
}
|
} catch (\Exception $exception) {
|
||||||
catch (\Exception $exception) {
|
|
||||||
|
|
||||||
Log::error(sprintf('Cannot instanciate a TwoFAccount object with 2FAS imported item #%s', $key));
|
Log::error(sprintf('Cannot instanciate a TwoFAccount object with 2FAS imported item #%s', $key));
|
||||||
Log::error($exception->getMessage());
|
Log::error($exception->getMessage());
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use Zxing\QrReader;
|
use chillerlan\QRCode\QRCode;
|
||||||
|
use chillerlan\QRCode\QROptions;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use chillerlan\QRCode\{QRCode, QROptions};
|
use Zxing\QrReader;
|
||||||
|
|
||||||
class QrCodeService
|
class QrCodeService
|
||||||
{
|
{
|
||||||
@ -12,7 +13,6 @@ class QrCodeService
|
|||||||
* Encode a string into a QR code image
|
* Encode a string into a QR code image
|
||||||
*
|
*
|
||||||
* @param string $data The string to encode
|
* @param string $data The string to encode
|
||||||
*
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public static function encode(string $data)
|
public static function encode(string $data)
|
||||||
@ -29,7 +29,6 @@ public static function encode(string $data)
|
|||||||
return $qrcode->render($data);
|
return $qrcode->render($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode an uploaded QR code image
|
* Decode an uploaded QR code image
|
||||||
*
|
*
|
||||||
@ -41,7 +40,7 @@ public static function decode(\Illuminate\Http\UploadedFile $file)
|
|||||||
$qrcode = new QrReader($file->get(), QrReader::SOURCE_TYPE_BLOB);
|
$qrcode = new QrReader($file->get(), QrReader::SOURCE_TYPE_BLOB);
|
||||||
$data = urldecode($qrcode->text());
|
$data = urldecode($qrcode->text());
|
||||||
|
|
||||||
if(!$data) {
|
if (! $data) {
|
||||||
throw new \App\Exceptions\InvalidQrCodeException;
|
throw new \App\Exceptions\InvalidQrCodeException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ public function scheduledScan() : void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a manual release scan
|
* Run a manual release scan
|
||||||
*
|
*
|
||||||
@ -39,8 +38,7 @@ public function manualScan() : false|string
|
|||||||
*/
|
*/
|
||||||
protected function newRelease() : false|string
|
protected function newRelease() : false|string
|
||||||
{
|
{
|
||||||
if ($latestReleaseData = json_decode($this->getLatestReleaseData()))
|
if ($latestReleaseData = json_decode($this->getLatestReleaseData())) {
|
||||||
{
|
|
||||||
$githubVersion = Helpers::cleanVersionNumber($latestReleaseData->tag_name);
|
$githubVersion = Helpers::cleanVersionNumber($latestReleaseData->tag_name);
|
||||||
$installedVersion = Helpers::cleanVersionNumber(config('2fauth.version'));
|
$installedVersion = Helpers::cleanVersionNumber(config('2fauth.version'));
|
||||||
|
|
||||||
@ -48,8 +46,7 @@ protected function newRelease() : false|string
|
|||||||
Settings::set('latestRelease', $latestReleaseData->tag_name);
|
Settings::set('latestRelease', $latestReleaseData->tag_name);
|
||||||
|
|
||||||
return $latestReleaseData->tag_name;
|
return $latestReleaseData->tag_name;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
Settings::delete('latestRelease');
|
Settings::delete('latestRelease');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +56,6 @@ protected function newRelease() : false|string
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch releases on Github
|
* Fetch releases on Github
|
||||||
*
|
*
|
||||||
@ -74,8 +70,7 @@ protected function getLatestReleaseData() : string|null
|
|||||||
if ($response->successful()) {
|
if ($response->successful()) {
|
||||||
return $response->body();
|
return $response->body();
|
||||||
}
|
}
|
||||||
}
|
} catch (\Exception $exception) {
|
||||||
catch (\Exception $exception) {
|
|
||||||
Log::error('cannot reach latestReleaseUrl endpoint');
|
Log::error('cannot reach latestReleaseUrl endpoint');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,19 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use Throwable;
|
use App\Exceptions\DbEncryptionException;
|
||||||
use Exception;
|
|
||||||
use App\Models\Option;
|
use App\Models\Option;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Crypt;
|
use Throwable;
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
use App\Exceptions\DbEncryptionException;
|
|
||||||
|
|
||||||
class SettingService
|
class SettingService
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All user settings
|
* All user settings
|
||||||
*
|
*
|
||||||
@ -23,7 +22,6 @@ class SettingService
|
|||||||
*/
|
*/
|
||||||
private Collection $settings;
|
private Collection $settings;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -32,7 +30,6 @@ public function __construct()
|
|||||||
self::build();
|
self::build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a setting
|
* Get a setting
|
||||||
*
|
*
|
||||||
@ -44,7 +41,6 @@ public function get($setting)
|
|||||||
return $this->settings->get($setting);
|
return $this->settings->get($setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all settings
|
* Get all settings
|
||||||
*
|
*
|
||||||
@ -55,20 +51,18 @@ public function all() : Collection
|
|||||||
return $this->settings;
|
return $this->settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a setting
|
* Set a setting
|
||||||
*
|
*
|
||||||
* @param string|array $setting A single setting name or an associative array of name:value settings
|
* @param string|array $setting A single setting name or an associative array of name:value settings
|
||||||
* @param string|int|boolean|null $value The value for single setting
|
* @param string|int|bool|null $value The value for single setting
|
||||||
*/
|
*/
|
||||||
public function set($setting, $value = null) : void
|
public function set($setting, $value = null) : void
|
||||||
{
|
{
|
||||||
$settings = is_array($setting) ? $setting : [$setting => $value];
|
$settings = is_array($setting) ? $setting : [$setting => $value];
|
||||||
|
|
||||||
foreach ($settings as $setting => $value) {
|
foreach ($settings as $setting => $value) {
|
||||||
if( $setting === 'useEncryption')
|
if ($setting === 'useEncryption') {
|
||||||
{
|
|
||||||
$this->setEncryptionTo($value);
|
$this->setEncryptionTo($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +77,6 @@ public function set($setting, $value = null) : void
|
|||||||
self::build();
|
self::build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a setting
|
* Delete a setting
|
||||||
*
|
*
|
||||||
@ -95,7 +88,6 @@ public function delete(string $name) : void
|
|||||||
Log::info(sprintf('Setting %s deleted', var_export($name, true)));
|
Log::info(sprintf('Setting %s deleted', var_export($name, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the given setting has been customized by the user
|
* Determine if the given setting has been customized by the user
|
||||||
*
|
*
|
||||||
@ -107,7 +99,6 @@ public function isUserDefined($key) : bool
|
|||||||
return DB::table('options')->where('key', $key)->exists();
|
return DB::table('options')->where('key', $key)->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the settings collection
|
* Set the settings collection
|
||||||
*
|
*
|
||||||
@ -123,15 +114,13 @@ private function build()
|
|||||||
|
|
||||||
// Merge 2fauth/app config values as fallback values
|
// Merge 2fauth/app config values as fallback values
|
||||||
$settings = collect(config('2fauth.options'))->merge($userOptions); /** @phpstan-ignore-line */
|
$settings = collect(config('2fauth.options'))->merge($userOptions); /** @phpstan-ignore-line */
|
||||||
|
if (! Arr::has($settings, 'lang')) {
|
||||||
if(!Arr::has($settings, 'lang')) {
|
|
||||||
$settings['lang'] = 'browser';
|
$settings['lang'] = 'browser';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces boolean by a patterned string as appstrack/laravel-options package does not support var type
|
* Replaces boolean by a patterned string as appstrack/laravel-options package does not support var type
|
||||||
*
|
*
|
||||||
@ -143,7 +132,6 @@ private function replaceBoolean(mixed $value)
|
|||||||
return is_bool($value) ? '{{' . $value . '}}' : $value;
|
return is_bool($value) ? '{{' . $value . '}}' : $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces patterned string that represent booleans with real booleans
|
* Replaces patterned string that represent booleans with real booleans
|
||||||
*
|
*
|
||||||
@ -154,22 +142,20 @@ private function restoreType(mixed $value)
|
|||||||
{
|
{
|
||||||
$value = is_numeric($value) ? (int) $value : $value;
|
$value = is_numeric($value) ? (int) $value : $value;
|
||||||
|
|
||||||
if( $value === '{{}}' ) {
|
if ($value === '{{}}') {
|
||||||
return false;
|
return false;
|
||||||
}
|
} elseif ($value === '{{1}}') {
|
||||||
else if( $value === '{{1}}' ) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable or Disable encryption of 2FAccounts sensible data
|
* Enable or Disable encryption of 2FAccounts sensible data
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
* @throws DbEncryptionException Something failed, everything have been rolled back
|
* @throws DbEncryptionException Something failed, everything have been rolled back
|
||||||
*/
|
*/
|
||||||
private function setEncryptionTo(bool $state) : void
|
private function setEncryptionTo(bool $state) : void
|
||||||
@ -177,39 +163,37 @@ private function setEncryptionTo(bool $state) : void
|
|||||||
// We don't want the records to be encrypted/decrypted multiple successive times
|
// We don't want the records to be encrypted/decrypted multiple successive times
|
||||||
$isInUse = $this->get('useEncryption');
|
$isInUse = $this->get('useEncryption');
|
||||||
|
|
||||||
if ($isInUse === !$state) {
|
if ($isInUse === ! $state) {
|
||||||
if ($this->updateRecords($state)) {
|
if ($this->updateRecords($state)) {
|
||||||
if ($state) {
|
if ($state) {
|
||||||
Log::notice('Sensible data are now encrypted');
|
Log::notice('Sensible data are now encrypted');
|
||||||
|
} else {
|
||||||
|
Log::notice('Sensible data are now decrypted');
|
||||||
}
|
}
|
||||||
else Log::notice('Sensible data are now decrypted');
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log::warning('Some data cannot be encrypted/decrypted, the useEncryption setting remain unchanged');
|
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'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt/Decrypt accounts in database
|
* Encrypt/Decrypt accounts in database
|
||||||
*
|
*
|
||||||
* @param boolean $encrypted Whether the record should be encrypted or not
|
* @param bool $encrypted Whether the record should be encrypted or not
|
||||||
* @return boolean Whether the operation completed successfully
|
* @return bool Whether the operation completed successfully
|
||||||
*/
|
*/
|
||||||
private function updateRecords(bool $encrypted) : bool
|
private function updateRecords(bool $encrypted) : bool
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$twofaccounts = DB::table('twofaccounts')->get();
|
$twofaccounts = DB::table('twofaccounts')->get();
|
||||||
|
|
||||||
$twofaccounts->each(function ($item, $key) use(&$success, $encrypted) {
|
$twofaccounts->each(function ($item, $key) use (&$success, $encrypted) {
|
||||||
try {
|
try {
|
||||||
$item->legacy_uri = $encrypted ? Crypt::encryptString($item->legacy_uri) : Crypt::decryptString($item->legacy_uri);
|
$item->legacy_uri = $encrypted ? Crypt::encryptString($item->legacy_uri) : Crypt::decryptString($item->legacy_uri);
|
||||||
$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 $ex) {
|
||||||
catch (Exception $ex) {
|
|
||||||
$success = false;
|
$success = false;
|
||||||
// Exit the each iteration
|
// Exit the each iteration
|
||||||
return false;
|
return false;
|
||||||
@ -228,20 +212,23 @@ private function updateRecords(bool $encrypted) : bool
|
|||||||
->update([
|
->update([
|
||||||
'legacy_uri' => $item->legacy_uri,
|
'legacy_uri' => $item->legacy_uri,
|
||||||
'account' => $item->account,
|
'account' => $item->account,
|
||||||
'secret' => $item->secret
|
'secret' => $item->secret,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
catch (Throwable $ex) {
|
catch (Throwable $ex) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,19 +2,18 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
use App\Factories\MigratorFactoryInterface;
|
use App\Factories\MigratorFactoryInterface;
|
||||||
use Illuminate\Support\Facades\Log;
|
use App\Models\TwoFAccount;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class TwoFAccountService
|
class TwoFAccountService
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var MigratorFactoryInterface $migratorFactory The Migration service
|
* @var MigratorFactoryInterface The Migration service
|
||||||
*/
|
*/
|
||||||
protected $migratorFactory;
|
protected $migratorFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -23,7 +22,6 @@ public function __construct(MigratorFactoryInterface $migratorFactory)
|
|||||||
$this->migratorFactory = $migratorFactory;
|
$this->migratorFactory = $migratorFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Withdraw one or more twofaccounts from their group
|
* Withdraw one or more twofaccounts from their group
|
||||||
*
|
*
|
||||||
@ -40,13 +38,12 @@ public static function withdraw($ids) : void
|
|||||||
|
|
||||||
TwoFAccount::whereIn('id', $ids)
|
TwoFAccount::whereIn('id', $ids)
|
||||||
->update(
|
->update(
|
||||||
['group_id' => NULL]
|
['group_id' => null]
|
||||||
);
|
);
|
||||||
|
|
||||||
Log::info(sprintf('TwoFAccounts #%s withdrawn', implode(',#', $ids)));
|
Log::info(sprintf('TwoFAccounts #%s withdrawn', implode(',#', $ids)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a migration payload to a set of TwoFAccount objects
|
* Convert a migration payload to a set of TwoFAccount objects
|
||||||
*
|
*
|
||||||
@ -61,7 +58,6 @@ public function migrate(string $migrationPayload) : Collection
|
|||||||
return self::markAsDuplicate($twofaccounts);
|
return self::markAsDuplicate($twofaccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete one or more twofaccounts
|
* Delete one or more twofaccounts
|
||||||
*
|
*
|
||||||
@ -73,13 +69,12 @@ public static function delete($ids) : int
|
|||||||
// $ids as string could be a comma-separated list of ids
|
// $ids as string could be a comma-separated list of ids
|
||||||
// so in this case we explode the string to an array
|
// so in this case we explode the string to an array
|
||||||
$ids = self::commaSeparatedToArray($ids);
|
$ids = self::commaSeparatedToArray($ids);
|
||||||
Log::info(sprintf('Deletion of TwoFAccounts #%s requested', is_array($ids) ? implode(',#', $ids) : $ids ));
|
Log::info(sprintf('Deletion of TwoFAccounts #%s requested', is_array($ids) ? implode(',#', $ids) : $ids));
|
||||||
$deleted = TwoFAccount::destroy($ids);
|
$deleted = TwoFAccount::destroy($ids);
|
||||||
|
|
||||||
return $deleted;
|
return $deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the given collection with items marked as Duplicates (using id=-1) if a similar record exists in database
|
* Return the given collection with items marked as Duplicates (using id=-1) if a similar record exists in database
|
||||||
*
|
*
|
||||||
@ -108,7 +103,6 @@ private static function markAsDuplicate(Collection $twofaccounts) : Collection
|
|||||||
return $twofaccounts;
|
return $twofaccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Explode a comma separated list of IDs to an array of IDs
|
* Explode a comma separated list of IDs to an array of IDs
|
||||||
*
|
*
|
||||||
@ -116,8 +110,7 @@ private static function markAsDuplicate(Collection $twofaccounts) : Collection
|
|||||||
*/
|
*/
|
||||||
private static function commaSeparatedToArray($ids) : mixed
|
private static function commaSeparatedToArray($ids) : mixed
|
||||||
{
|
{
|
||||||
if(is_string($ids))
|
if (is_string($ids)) {
|
||||||
{
|
|
||||||
$regex = "/^\d+(,{1}\d+)*$/";
|
$regex = "/^\d+(,{1}\d+)*$/";
|
||||||
if (preg_match($regex, $ids)) {
|
if (preg_match($regex, $ids)) {
|
||||||
$ids = explode(',', $ids);
|
$ids = explode(',', $ids);
|
||||||
|
25
pint.json
25
pint.json
@ -1,3 +1,26 @@
|
|||||||
{
|
{
|
||||||
"preset": "laravel"
|
"preset": "laravel",
|
||||||
|
"exclude": [
|
||||||
|
"app/Protobuf",
|
||||||
|
"bootstrap",
|
||||||
|
"config",
|
||||||
|
"database",
|
||||||
|
"public",
|
||||||
|
"resources"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"binary_operator_spaces": {
|
||||||
|
"default": "single_space",
|
||||||
|
"operators": {
|
||||||
|
"=>": "align_single_space_minimal",
|
||||||
|
"=": "align_single_space_minimal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"concat_space": {
|
||||||
|
"spacing": "one"
|
||||||
|
},
|
||||||
|
"return_type_declaration": {
|
||||||
|
"space_before": "one"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,18 +12,16 @@ class UserControllerTest extends FeatureTestCase
|
|||||||
*/
|
*/
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function setUp(): void
|
public function setUp() : void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->user = User::factory()->create();
|
$this->user = User::factory()->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -39,7 +37,6 @@ public function test_show_existing_user_when_authenticated_returns_success()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -52,7 +49,6 @@ public function test_show_existing_user_when_anonymous_returns_success()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -69,5 +65,4 @@ public function test_show_missing_user_returns_success_with_null_name()
|
|||||||
'email' => $this->user->email,
|
'email' => $this->user->email,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
namespace Tests\Api\v1\Controllers;
|
namespace Tests\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use Tests\FeatureTestCase;
|
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Models\User;
|
||||||
|
use Tests\FeatureTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \App\Api\v1\Controllers\GroupController
|
* @covers \App\Api\v1\Controllers\GroupController
|
||||||
@ -19,18 +18,16 @@ class GroupControllerTest extends FeatureTestCase
|
|||||||
*/
|
*/
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function setUp(): void
|
public function setUp() : void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->user = User::factory()->create();
|
$this->user = User::factory()->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -47,7 +44,7 @@ public function test_index_returns_group_collection_with_pseudo_group()
|
|||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
'twofaccounts_count',
|
'twofaccounts_count',
|
||||||
]
|
],
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -56,7 +53,6 @@ public function test_index_returns_group_collection_with_pseudo_group()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -73,7 +69,6 @@ public function test_store_returns_created_group_resource()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -86,7 +81,6 @@ public function test_store_invalid_data_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -105,7 +99,6 @@ public function test_show_returns_group_resource()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -115,11 +108,10 @@ public function test_show_missing_group_returns_not_found()
|
|||||||
->json('GET', '/api/v1/groups/1000')
|
->json('GET', '/api/v1/groups/1000')
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -138,7 +130,6 @@ public function test_update_returns_updated_group_resource()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -150,11 +141,10 @@ public function test_update_missing_group_returns_not_found()
|
|||||||
])
|
])
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -169,7 +159,6 @@ public function test_update_with_invalid_data_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -190,7 +179,6 @@ public function test_assign_accounts_returns_updated_group_resource()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -204,11 +192,10 @@ public function test_assign_accounts_to_missing_group_returns_not_found()
|
|||||||
])
|
])
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -224,7 +211,6 @@ public function test_assign_invalid_accounts_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -252,12 +238,11 @@ public function test_get_assigned_accounts_returns_twofaccounts_collection()
|
|||||||
'digits',
|
'digits',
|
||||||
'algorithm',
|
'algorithm',
|
||||||
'period',
|
'period',
|
||||||
'counter'
|
'counter',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -286,12 +271,11 @@ public function test_get_assigned_accounts_returns_twofaccounts_collection_with_
|
|||||||
'digits',
|
'digits',
|
||||||
'algorithm',
|
'algorithm',
|
||||||
'period',
|
'period',
|
||||||
'counter'
|
'counter',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -301,11 +285,10 @@ public function test_get_assigned_accounts_of_missing_group_returns_not_found()
|
|||||||
->json('GET', '/api/v1/groups/1000/twofaccounts')
|
->json('GET', '/api/v1/groups/1000/twofaccounts')
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test Group deletion via API
|
* test Group deletion via API
|
||||||
*
|
*
|
||||||
@ -320,7 +303,6 @@ public function test_destroy_group_returns_success()
|
|||||||
->assertNoContent();
|
->assertNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test Group deletion via API
|
* test Group deletion via API
|
||||||
*
|
*
|
||||||
@ -332,7 +314,7 @@ public function test_destroy_missing_group_returns_not_found()
|
|||||||
->json('DELETE', '/api/v1/groups/1000')
|
->json('DELETE', '/api/v1/groups/1000')
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
namespace Tests\Api\v1\Controllers;
|
namespace Tests\Api\v1\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\UploadedFile;
|
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
use Tests\FeatureTestCase;
|
use Tests\FeatureTestCase;
|
||||||
|
|
||||||
use App\Models\TwoFAccount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \App\Api\v1\Controllers\IconController
|
* @covers \App\Api\v1\Controllers\IconController
|
||||||
*/
|
*/
|
||||||
class IconControllerTest extends FeatureTestCase
|
class IconControllerTest extends FeatureTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -29,11 +25,10 @@ public function test_upload_icon_returns_filename()
|
|||||||
])
|
])
|
||||||
->assertCreated()
|
->assertCreated()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'filename'
|
'filename',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -45,7 +40,6 @@ public function test_upload_with_invalid_data_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -55,7 +49,6 @@ public function test_delete_icon_returns_success()
|
|||||||
->assertNoContent(204);
|
->assertNoContent(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -63,7 +56,5 @@ public function test_delete_invalid_icon_returns_success()
|
|||||||
{
|
{
|
||||||
$response = $this->json('DELETE', '/api/v1/icons/null')
|
$response = $this->json('DELETE', '/api/v1/icons/null')
|
||||||
->assertNoContent(204);
|
->assertNoContent(204);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,35 +2,31 @@
|
|||||||
|
|
||||||
namespace Tests\Api\v1\Controllers;
|
namespace Tests\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Tests\FeatureTestCase;
|
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Models\User;
|
||||||
use Tests\Classes\LocalFile;
|
use Tests\Classes\LocalFile;
|
||||||
|
use Tests\FeatureTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \App\Api\v1\Controllers\QrCodeController
|
* @covers \App\Api\v1\Controllers\QrCodeController
|
||||||
*/
|
*/
|
||||||
class QrCodeControllerTest extends FeatureTestCase
|
class QrCodeControllerTest extends FeatureTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \App\Models\User
|
* @var \App\Models\User
|
||||||
*/
|
*/
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function setUp(): void
|
public function setUp() : void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->user = User::factory()->create();
|
$this->user = User::factory()->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -57,7 +53,6 @@ public function test_show_qrcode_returns_base64_image()
|
|||||||
$this->assertStringStartsWith('data:image/png;base64', $response->getData()->qrcode);
|
$this->assertStringStartsWith('data:image/png;base64', $response->getData()->qrcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -67,11 +62,10 @@ public function test_show_missing_qrcode_returns_not_found()
|
|||||||
->json('GET', '/api/v1/twofaccounts/1000/qrcode')
|
->json('GET', '/api/v1/twofaccounts/1000/qrcode')
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -83,7 +77,7 @@ public function test_decode_qrcode_return_success()
|
|||||||
->actingAs($this->user, 'api-guard')
|
->actingAs($this->user, 'api-guard')
|
||||||
->json('POST', '/api/v1/qrcode/decode', [
|
->json('POST', '/api/v1/qrcode/decode', [
|
||||||
'qrcode' => $file,
|
'qrcode' => $file,
|
||||||
'inputFormat' => 'fileUpload'
|
'inputFormat' => 'fileUpload',
|
||||||
])
|
])
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertExactJson([
|
->assertExactJson([
|
||||||
@ -91,7 +85,6 @@ public function test_decode_qrcode_return_success()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -104,7 +97,6 @@ public function test_decode_missing_qrcode_return_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -116,7 +108,7 @@ public function test_decode_invalid_qrcode_return_bad_request()
|
|||||||
->actingAs($this->user, 'api-guard')
|
->actingAs($this->user, 'api-guard')
|
||||||
->json('POST', '/api/v1/qrcode/decode', [
|
->json('POST', '/api/v1/qrcode/decode', [
|
||||||
'qrcode' => $file,
|
'qrcode' => $file,
|
||||||
'inputFormat' => 'fileUpload'
|
'inputFormat' => 'fileUpload',
|
||||||
])
|
])
|
||||||
->assertStatus(400)
|
->assertStatus(400)
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
namespace Tests\Api\v1\Controllers;
|
namespace Tests\Api\v1\Controllers;
|
||||||
|
|
||||||
|
use App\Facades\Settings;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Tests\FeatureTestCase;
|
use Tests\FeatureTestCase;
|
||||||
use App\Facades\Settings;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \App\Api\v1\Controllers\SettingController
|
* @covers \App\Api\v1\Controllers\SettingController
|
||||||
@ -19,26 +18,31 @@ class SettingControllerTest extends FeatureTestCase
|
|||||||
|
|
||||||
private const SETTING_JSON_STRUCTURE = [
|
private const SETTING_JSON_STRUCTURE = [
|
||||||
'key',
|
'key',
|
||||||
'value'
|
'value',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const TWOFAUTH_NATIVE_SETTING = 'showTokenAsDot';
|
private const TWOFAUTH_NATIVE_SETTING = 'showTokenAsDot';
|
||||||
|
|
||||||
private const TWOFAUTH_NATIVE_SETTING_DEFAULT_VALUE = false;
|
private const TWOFAUTH_NATIVE_SETTING_DEFAULT_VALUE = false;
|
||||||
|
|
||||||
private const TWOFAUTH_NATIVE_SETTING_CHANGED_VALUE = true;
|
private const TWOFAUTH_NATIVE_SETTING_CHANGED_VALUE = true;
|
||||||
|
|
||||||
private const USER_DEFINED_SETTING = 'mySetting';
|
private const USER_DEFINED_SETTING = 'mySetting';
|
||||||
|
|
||||||
private const USER_DEFINED_SETTING_VALUE = 'mySetting';
|
private const USER_DEFINED_SETTING_VALUE = 'mySetting';
|
||||||
|
|
||||||
private const USER_DEFINED_SETTING_CHANGED_VALUE = 'mySetting';
|
private const USER_DEFINED_SETTING_CHANGED_VALUE = 'mySetting';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function setUp(): void
|
public function setUp() : void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->user = User::factory()->create();
|
$this->user = User::factory()->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -48,11 +52,10 @@ public function test_index_returns_setting_collection()
|
|||||||
->json('GET', '/api/v1/settings')
|
->json('GET', '/api/v1/settings')
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'*' => self::SETTING_JSON_STRUCTURE
|
'*' => self::SETTING_JSON_STRUCTURE,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -67,7 +70,6 @@ public function test_show_native_unchanged_setting_returns_consistent_value()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -84,7 +86,6 @@ public function test_show_native_changed_setting_returns_consistent_value()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -101,7 +102,6 @@ public function test_show_custom_user_setting_returns_consistent_value()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -112,7 +112,6 @@ public function test_show_missing_setting_returns_not_found()
|
|||||||
->assertNotFound();
|
->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -130,7 +129,6 @@ public function test_store_custom_user_setting_returns_success()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -144,7 +142,6 @@ public function test_store_invalid_custom_user_setting_returns_validation_error(
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -160,7 +157,6 @@ public function test_store_existing_custom_user_setting_returns_validation_error
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -177,7 +173,6 @@ public function test_update_unchanged_native_setting_returns_updated_setting()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -196,7 +191,6 @@ public function test_update_custom_user_setting_returns_updated_setting()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -213,7 +207,6 @@ public function test_update_missing_user_setting_returns_created_setting()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -226,7 +219,6 @@ public function test_destroy_user_setting_returns_success()
|
|||||||
->assertNoContent();
|
->assertNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -241,7 +233,6 @@ public function test_destroy_native_setting_returns_bad_request()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -251,6 +242,4 @@ public function test_destroy_missing_user_setting_returns_not_found()
|
|||||||
->json('DELETE', '/api/v1/settings/' . self::USER_DEFINED_SETTING)
|
->json('DELETE', '/api/v1/settings/' . self::USER_DEFINED_SETTING)
|
||||||
->assertNotFound();
|
->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
namespace Tests\Api\v1\Controllers;
|
namespace Tests\Api\v1\Controllers;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Group;
|
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
use Tests\FeatureTestCase;
|
use App\Models\Group;
|
||||||
use Tests\Classes\OtpTestData;
|
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Tests\Classes\LocalFile;
|
use Tests\Classes\LocalFile;
|
||||||
|
use Tests\Classes\OtpTestData;
|
||||||
|
use Tests\FeatureTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \App\Api\v1\Controllers\TwoFAccountController
|
* @covers \App\Api\v1\Controllers\TwoFAccountController
|
||||||
@ -30,8 +29,6 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
*/
|
*/
|
||||||
protected $group;
|
protected $group;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private const VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET = [
|
private const VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET = [
|
||||||
'id',
|
'id',
|
||||||
'group_id',
|
'group_id',
|
||||||
@ -42,8 +39,9 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
'digits',
|
'digits',
|
||||||
'algorithm',
|
'algorithm',
|
||||||
'period',
|
'period',
|
||||||
'counter'
|
'counter',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const VALID_RESOURCE_STRUCTURE_WITH_SECRET = [
|
private const VALID_RESOURCE_STRUCTURE_WITH_SECRET = [
|
||||||
'id',
|
'id',
|
||||||
'group_id',
|
'group_id',
|
||||||
@ -55,19 +53,22 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
'digits',
|
'digits',
|
||||||
'algorithm',
|
'algorithm',
|
||||||
'period',
|
'period',
|
||||||
'counter'
|
'counter',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const VALID_OTP_RESOURCE_STRUCTURE_FOR_TOTP = [
|
private const VALID_OTP_RESOURCE_STRUCTURE_FOR_TOTP = [
|
||||||
'generated_at',
|
'generated_at',
|
||||||
'otp_type',
|
'otp_type',
|
||||||
'password',
|
'password',
|
||||||
'period',
|
'period',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const VALID_OTP_RESOURCE_STRUCTURE_FOR_HOTP = [
|
private const VALID_OTP_RESOURCE_STRUCTURE_FOR_HOTP = [
|
||||||
'otp_type',
|
'otp_type',
|
||||||
'password',
|
'password',
|
||||||
'counter',
|
'counter',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const JSON_FRAGMENTS_FOR_CUSTOM_TOTP = [
|
private const JSON_FRAGMENTS_FOR_CUSTOM_TOTP = [
|
||||||
'service' => OtpTestData::SERVICE,
|
'service' => OtpTestData::SERVICE,
|
||||||
'account' => OtpTestData::ACCOUNT,
|
'account' => OtpTestData::ACCOUNT,
|
||||||
@ -78,6 +79,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
'period' => OtpTestData::PERIOD_CUSTOM,
|
'period' => OtpTestData::PERIOD_CUSTOM,
|
||||||
'counter' => null,
|
'counter' => null,
|
||||||
];
|
];
|
||||||
|
|
||||||
private const JSON_FRAGMENTS_FOR_DEFAULT_TOTP = [
|
private const JSON_FRAGMENTS_FOR_DEFAULT_TOTP = [
|
||||||
'service' => null,
|
'service' => null,
|
||||||
'account' => OtpTestData::ACCOUNT,
|
'account' => OtpTestData::ACCOUNT,
|
||||||
@ -88,6 +90,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
'period' => OtpTestData::PERIOD_DEFAULT,
|
'period' => OtpTestData::PERIOD_DEFAULT,
|
||||||
'counter' => null,
|
'counter' => null,
|
||||||
];
|
];
|
||||||
|
|
||||||
private const JSON_FRAGMENTS_FOR_CUSTOM_HOTP = [
|
private const JSON_FRAGMENTS_FOR_CUSTOM_HOTP = [
|
||||||
'service' => OtpTestData::SERVICE,
|
'service' => OtpTestData::SERVICE,
|
||||||
'account' => OtpTestData::ACCOUNT,
|
'account' => OtpTestData::ACCOUNT,
|
||||||
@ -98,6 +101,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
'period' => null,
|
'period' => null,
|
||||||
'counter' => OtpTestData::COUNTER_CUSTOM,
|
'counter' => OtpTestData::COUNTER_CUSTOM,
|
||||||
];
|
];
|
||||||
|
|
||||||
private const JSON_FRAGMENTS_FOR_DEFAULT_HOTP = [
|
private const JSON_FRAGMENTS_FOR_DEFAULT_HOTP = [
|
||||||
'service' => null,
|
'service' => null,
|
||||||
'account' => OtpTestData::ACCOUNT,
|
'account' => OtpTestData::ACCOUNT,
|
||||||
@ -108,17 +112,17 @@ class TwoFAccountControllerTest extends FeatureTestCase
|
|||||||
'period' => null,
|
'period' => null,
|
||||||
'counter' => OtpTestData::COUNTER_DEFAULT,
|
'counter' => OtpTestData::COUNTER_DEFAULT,
|
||||||
];
|
];
|
||||||
|
|
||||||
private const ARRAY_OF_INVALID_PARAMETERS = [
|
private const ARRAY_OF_INVALID_PARAMETERS = [
|
||||||
'account' => null,
|
'account' => null,
|
||||||
'otp_type' => 'totp',
|
'otp_type' => 'totp',
|
||||||
'secret' => OtpTestData::SECRET,
|
'secret' => OtpTestData::SECRET,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function setUp(): void
|
public function setUp() : void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
@ -126,7 +130,6 @@ public function setUp(): void
|
|||||||
$this->group = Group::factory()->create();
|
$this->group = Group::factory()->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*
|
*
|
||||||
@ -137,15 +140,14 @@ public function test_index_returns_twofaccount_collection($urlParameter, $expect
|
|||||||
TwoFAccount::factory()->count(3)->create();
|
TwoFAccount::factory()->count(3)->create();
|
||||||
|
|
||||||
$response = $this->actingAs($this->user, 'api-guard')
|
$response = $this->actingAs($this->user, 'api-guard')
|
||||||
->json('GET', '/api/v1/twofaccounts'.$urlParameter)
|
->json('GET', '/api/v1/twofaccounts' . $urlParameter)
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonCount(3, $key = null)
|
->assertJsonCount(3, $key = null)
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'*' => $expected
|
'*' => $expected,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide data for index tests
|
* Provide data for index tests
|
||||||
*/
|
*/
|
||||||
@ -154,16 +156,15 @@ public function indexUrlParameterProvider()
|
|||||||
return [
|
return [
|
||||||
'VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET' => [
|
'VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET' => [
|
||||||
'',
|
'',
|
||||||
self::VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET
|
self::VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET,
|
||||||
],
|
],
|
||||||
'VALID_RESOURCE_STRUCTURE_WITH_SECRET' => [
|
'VALID_RESOURCE_STRUCTURE_WITH_SECRET' => [
|
||||||
'?withSecret=1',
|
'?withSecret=1',
|
||||||
self::VALID_RESOURCE_STRUCTURE_WITH_SECRET
|
self::VALID_RESOURCE_STRUCTURE_WITH_SECRET,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -177,7 +178,6 @@ public function test_show_twofaccount_returns_twofaccount_resource_with_secret()
|
|||||||
->assertJsonStructure(self::VALID_RESOURCE_STRUCTURE_WITH_SECRET);
|
->assertJsonStructure(self::VALID_RESOURCE_STRUCTURE_WITH_SECRET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -191,7 +191,6 @@ public function test_show_twofaccount_returns_twofaccount_resource_without_secre
|
|||||||
->assertJsonStructure(self::VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET);
|
->assertJsonStructure(self::VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -217,7 +216,6 @@ public function test_show_twofaccount_returns_twofaccount_resource_without_secre
|
|||||||
// ]);
|
// ]);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -227,11 +225,10 @@ public function test_show_missing_twofaccount_returns_not_found()
|
|||||||
->json('GET', '/api/v1/twofaccounts/1000')
|
->json('GET', '/api/v1/twofaccounts/1000')
|
||||||
->assertNotFound()
|
->assertNotFound()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider accountCreationProvider
|
* @dataProvider accountCreationProvider
|
||||||
* @test
|
* @test
|
||||||
@ -248,7 +245,6 @@ public function test_store_without_encryption_returns_success_with_consistent_re
|
|||||||
->assertJsonFragment($expected);
|
->assertJsonFragment($expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider accountCreationProvider
|
* @dataProvider accountCreationProvider
|
||||||
* @test
|
* @test
|
||||||
@ -265,7 +261,6 @@ public function test_store_with_encryption_returns_success_with_consistent_resou
|
|||||||
->assertJsonFragment($expected);
|
->assertJsonFragment($expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide data for TwoFAccount store tests
|
* Provide data for TwoFAccount store tests
|
||||||
*/
|
*/
|
||||||
@ -276,46 +271,45 @@ public function accountCreationProvider()
|
|||||||
[
|
[
|
||||||
'uri' => OtpTestData::TOTP_FULL_CUSTOM_URI,
|
'uri' => OtpTestData::TOTP_FULL_CUSTOM_URI,
|
||||||
],
|
],
|
||||||
self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP
|
self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP,
|
||||||
],
|
],
|
||||||
'TOTP_SHORT_URI' => [
|
'TOTP_SHORT_URI' => [
|
||||||
[
|
[
|
||||||
'uri' => OtpTestData::TOTP_SHORT_URI,
|
'uri' => OtpTestData::TOTP_SHORT_URI,
|
||||||
],
|
],
|
||||||
self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP
|
self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP,
|
||||||
],
|
],
|
||||||
'ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP' => [
|
'ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP' => [
|
||||||
OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP,
|
OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP,
|
||||||
self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP
|
self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP,
|
||||||
],
|
],
|
||||||
'ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP' => [
|
'ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP' => [
|
||||||
OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP,
|
OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP,
|
||||||
self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP
|
self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP,
|
||||||
],
|
],
|
||||||
'HOTP_FULL_CUSTOM_URI' => [
|
'HOTP_FULL_CUSTOM_URI' => [
|
||||||
[
|
[
|
||||||
'uri' => OtpTestData::HOTP_FULL_CUSTOM_URI,
|
'uri' => OtpTestData::HOTP_FULL_CUSTOM_URI,
|
||||||
],
|
],
|
||||||
self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP
|
self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP,
|
||||||
],
|
],
|
||||||
'HOTP_SHORT_URI' => [
|
'HOTP_SHORT_URI' => [
|
||||||
[
|
[
|
||||||
'uri' => OtpTestData::HOTP_SHORT_URI,
|
'uri' => OtpTestData::HOTP_SHORT_URI,
|
||||||
],
|
],
|
||||||
self::JSON_FRAGMENTS_FOR_DEFAULT_HOTP
|
self::JSON_FRAGMENTS_FOR_DEFAULT_HOTP,
|
||||||
],
|
],
|
||||||
'ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_HOTP' => [
|
'ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_HOTP' => [
|
||||||
OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_HOTP,
|
OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_HOTP,
|
||||||
self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP
|
self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP,
|
||||||
],
|
],
|
||||||
'ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_HOTP' => [
|
'ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_HOTP' => [
|
||||||
OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_HOTP,
|
OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_HOTP,
|
||||||
self::JSON_FRAGMENTS_FOR_DEFAULT_HOTP
|
self::JSON_FRAGMENTS_FOR_DEFAULT_HOTP,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -328,7 +322,6 @@ public function test_store_with_invalid_uri_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -342,11 +335,10 @@ public function test_store_assigns_created_account_when_default_group_is_a_speci
|
|||||||
'uri' => OtpTestData::TOTP_SHORT_URI,
|
'uri' => OtpTestData::TOTP_SHORT_URI,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'group_id' => $this->group->id
|
'group_id' => $this->group->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -362,11 +354,10 @@ public function test_store_assigns_created_account_when_default_group_is_the_act
|
|||||||
'uri' => OtpTestData::TOTP_SHORT_URI,
|
'uri' => OtpTestData::TOTP_SHORT_URI,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'group_id' => $this->group->id
|
'group_id' => $this->group->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -380,11 +371,10 @@ public function test_store_assigns_created_account_when_default_group_is_no_grou
|
|||||||
'uri' => OtpTestData::TOTP_SHORT_URI,
|
'uri' => OtpTestData::TOTP_SHORT_URI,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'group_id' => null
|
'group_id' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -398,11 +388,10 @@ public function test_store_assigns_created_account_when_default_group_does_not_e
|
|||||||
'uri' => OtpTestData::TOTP_SHORT_URI,
|
'uri' => OtpTestData::TOTP_SHORT_URI,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'group_id' => null
|
'group_id' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -416,7 +405,6 @@ public function test_update_totp_returns_success_with_updated_resource()
|
|||||||
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP);
|
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -430,7 +418,6 @@ public function test_update_hotp_returns_success_with_updated_resource()
|
|||||||
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP);
|
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -441,7 +428,6 @@ public function test_update_missing_twofaccount_returns_not_found()
|
|||||||
->assertNotFound();
|
->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -454,7 +440,6 @@ public function test_update_twofaccount_with_invalid_data_returns_validation_err
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -476,7 +461,7 @@ public function test_import_valid_gauth_payload_returns_success_with_consistent_
|
|||||||
'digits' => OtpTestData::DIGITS_DEFAULT,
|
'digits' => OtpTestData::DIGITS_DEFAULT,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
||||||
'period' => OtpTestData::PERIOD_DEFAULT,
|
'period' => OtpTestData::PERIOD_DEFAULT,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -487,11 +472,10 @@ public function test_import_valid_gauth_payload_returns_success_with_consistent_
|
|||||||
'digits' => OtpTestData::DIGITS_DEFAULT,
|
'digits' => OtpTestData::DIGITS_DEFAULT,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
||||||
'period' => OtpTestData::PERIOD_DEFAULT,
|
'period' => OtpTestData::PERIOD_DEFAULT,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -504,7 +488,6 @@ public function test_import_with_invalid_gauth_payload_returns_validation_error(
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -534,7 +517,6 @@ public function test_import_gauth_payload_with_duplicates_returns_negative_ids()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -546,11 +528,10 @@ public function test_import_invalid_gauth_payload_returns_bad_request()
|
|||||||
])
|
])
|
||||||
->assertStatus(400)
|
->assertStatus(400)
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -575,7 +556,7 @@ public function test_import_valid_aegis_json_file_returns_success()
|
|||||||
'digits' => OtpTestData::DIGITS_DEFAULT,
|
'digits' => OtpTestData::DIGITS_DEFAULT,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
||||||
'period' => OtpTestData::PERIOD_DEFAULT,
|
'period' => OtpTestData::PERIOD_DEFAULT,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -586,7 +567,7 @@ public function test_import_valid_aegis_json_file_returns_success()
|
|||||||
'digits' => OtpTestData::DIGITS_CUSTOM,
|
'digits' => OtpTestData::DIGITS_CUSTOM,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_CUSTOM,
|
'algorithm' => OtpTestData::ALGORITHM_CUSTOM,
|
||||||
'period' => OtpTestData::PERIOD_CUSTOM,
|
'period' => OtpTestData::PERIOD_CUSTOM,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -597,7 +578,7 @@ public function test_import_valid_aegis_json_file_returns_success()
|
|||||||
'digits' => OtpTestData::DIGITS_DEFAULT,
|
'digits' => OtpTestData::DIGITS_DEFAULT,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
||||||
'period' => null,
|
'period' => null,
|
||||||
'counter' => OtpTestData::COUNTER_DEFAULT
|
'counter' => OtpTestData::COUNTER_DEFAULT,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -619,11 +600,10 @@ public function test_import_valid_aegis_json_file_returns_success()
|
|||||||
'digits' => OtpTestData::DIGITS_STEAM,
|
'digits' => OtpTestData::DIGITS_STEAM,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
||||||
'period' => OtpTestData::PERIOD_DEFAULT,
|
'period' => OtpTestData::PERIOD_DEFAULT,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*
|
*
|
||||||
@ -639,7 +619,6 @@ public function test_import_invalid_aegis_json_file_returns_bad_request($file)
|
|||||||
->assertStatus(400);
|
->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide invalid Aegis JSON files for import tests
|
* Provide invalid Aegis JSON files for import tests
|
||||||
*/
|
*/
|
||||||
@ -647,15 +626,14 @@ public function invalidAegisJsonFileProvider()
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'validPlainTextFile' => [
|
'validPlainTextFile' => [
|
||||||
LocalFile::fake()->encryptedAegisJsonFile()
|
LocalFile::fake()->encryptedAegisJsonFile(),
|
||||||
],
|
],
|
||||||
'validPlainTextFileWithNewLines' => [
|
'validPlainTextFileWithNewLines' => [
|
||||||
LocalFile::fake()->invalidAegisJsonFile()
|
LocalFile::fake()->invalidAegisJsonFile(),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*
|
*
|
||||||
@ -680,7 +658,7 @@ public function test_import_valid_plain_text_file_returns_success($file)
|
|||||||
'digits' => OtpTestData::DIGITS_CUSTOM,
|
'digits' => OtpTestData::DIGITS_CUSTOM,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_CUSTOM,
|
'algorithm' => OtpTestData::ALGORITHM_CUSTOM,
|
||||||
'period' => OtpTestData::PERIOD_CUSTOM,
|
'period' => OtpTestData::PERIOD_CUSTOM,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -691,7 +669,7 @@ public function test_import_valid_plain_text_file_returns_success($file)
|
|||||||
'digits' => OtpTestData::DIGITS_CUSTOM,
|
'digits' => OtpTestData::DIGITS_CUSTOM,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_CUSTOM,
|
'algorithm' => OtpTestData::ALGORITHM_CUSTOM,
|
||||||
'period' => null,
|
'period' => null,
|
||||||
'counter' => OtpTestData::COUNTER_CUSTOM
|
'counter' => OtpTestData::COUNTER_CUSTOM,
|
||||||
])
|
])
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
@ -702,11 +680,10 @@ public function test_import_valid_plain_text_file_returns_success($file)
|
|||||||
'digits' => OtpTestData::DIGITS_STEAM,
|
'digits' => OtpTestData::DIGITS_STEAM,
|
||||||
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
|
||||||
'period' => OtpTestData::PERIOD_DEFAULT,
|
'period' => OtpTestData::PERIOD_DEFAULT,
|
||||||
'counter' => null
|
'counter' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide valid Plain Text files for import tests
|
* Provide valid Plain Text files for import tests
|
||||||
*/
|
*/
|
||||||
@ -714,15 +691,14 @@ public function validPlainTextFileProvider()
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'validPlainTextFile' => [
|
'validPlainTextFile' => [
|
||||||
LocalFile::fake()->validPlainTextFile()
|
LocalFile::fake()->validPlainTextFile(),
|
||||||
],
|
],
|
||||||
'validPlainTextFileWithNewLines' => [
|
'validPlainTextFileWithNewLines' => [
|
||||||
LocalFile::fake()->validPlainTextFileWithNewLines()
|
LocalFile::fake()->validPlainTextFileWithNewLines(),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*
|
*
|
||||||
@ -730,7 +706,6 @@ public function validPlainTextFileProvider()
|
|||||||
*/
|
*/
|
||||||
public function test_import_invalid_plain_text_file_returns_bad_request($file)
|
public function test_import_invalid_plain_text_file_returns_bad_request($file)
|
||||||
{
|
{
|
||||||
|
|
||||||
$response = $this->withHeaders(['Content-Type' => 'multipart/form-data'])
|
$response = $this->withHeaders(['Content-Type' => 'multipart/form-data'])
|
||||||
->actingAs($this->user, 'api-guard')
|
->actingAs($this->user, 'api-guard')
|
||||||
->json('POST', '/api/v1/twofaccounts/migration', [
|
->json('POST', '/api/v1/twofaccounts/migration', [
|
||||||
@ -739,7 +714,6 @@ public function test_import_invalid_plain_text_file_returns_bad_request($file)
|
|||||||
->assertStatus(400);
|
->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide invalid Plain Text files for import tests
|
* Provide invalid Plain Text files for import tests
|
||||||
*/
|
*/
|
||||||
@ -747,21 +721,20 @@ public function invalidPlainTextFileProvider()
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'validPlainTextFile' => [
|
'validPlainTextFile' => [
|
||||||
LocalFile::fake()->invalidPlainTextFileEmpty()
|
LocalFile::fake()->invalidPlainTextFileEmpty(),
|
||||||
],
|
],
|
||||||
'validPlainTextFileWithNewLines' => [
|
'validPlainTextFileWithNewLines' => [
|
||||||
LocalFile::fake()->invalidPlainTextFileNoUri()
|
LocalFile::fake()->invalidPlainTextFileNoUri(),
|
||||||
],
|
],
|
||||||
'validPlainTextFileWithNewLines' => [
|
'validPlainTextFileWithNewLines' => [
|
||||||
LocalFile::fake()->invalidPlainTextFileWithInvalidUri()
|
LocalFile::fake()->invalidPlainTextFileWithInvalidUri(),
|
||||||
],
|
],
|
||||||
'validPlainTextFileWithNewLines' => [
|
'validPlainTextFileWithNewLines' => [
|
||||||
LocalFile::fake()->invalidPlainTextFileWithInvalidLine()
|
LocalFile::fake()->invalidPlainTextFileWithInvalidLine(),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -771,14 +744,13 @@ public function test_reorder_returns_success()
|
|||||||
|
|
||||||
$response = $this->actingAs($this->user, 'api-guard')
|
$response = $this->actingAs($this->user, 'api-guard')
|
||||||
->json('POST', '/api/v1/twofaccounts/reorder', [
|
->json('POST', '/api/v1/twofaccounts/reorder', [
|
||||||
'orderedIds' => [3,2,1]])
|
'orderedIds' => [3, 2, 1], ])
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'message'
|
'message',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -788,11 +760,10 @@ public function test_reorder_with_invalid_data_returns_validation_error()
|
|||||||
|
|
||||||
$response = $this->actingAs($this->user, 'api-guard')
|
$response = $this->actingAs($this->user, 'api-guard')
|
||||||
->json('POST', '/api/v1/twofaccounts/reorder', [
|
->json('POST', '/api/v1/twofaccounts/reorder', [
|
||||||
'orderedIds' => '3,2,1'])
|
'orderedIds' => '3,2,1', ])
|
||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -806,7 +777,6 @@ public function test_preview_returns_success_with_resource()
|
|||||||
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP);
|
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -819,7 +789,6 @@ public function test_preview_with_invalid_data_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -831,11 +800,10 @@ public function test_preview_with_unreachable_image_returns_success()
|
|||||||
])
|
])
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
'icon' => null
|
'icon' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -863,7 +831,6 @@ public function test_get_otp_using_totp_twofaccount_id_returns_consistent_resour
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -881,7 +848,6 @@ public function test_get_otp_by_posting_totp_uri_returns_consistent_resource()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -897,7 +863,6 @@ public function test_get_otp_by_posting_totp_parameters_returns_consistent_resou
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -925,7 +890,6 @@ public function test_get_otp_using_hotp_twofaccount_id_returns_consistent_resour
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -943,7 +907,6 @@ public function test_get_otp_by_posting_hotp_uri_returns_consistent_resource()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -959,7 +922,6 @@ public function test_get_otp_by_posting_hotp_parameters_returns_consistent_resou
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -977,7 +939,6 @@ public function test_get_otp_by_posting_multiple_inputs_returns_bad_request()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1001,7 +962,6 @@ public function test_get_otp_using_indecipherable_twofaccount_id_returns_bad_req
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1012,7 +972,6 @@ public function test_get_otp_using_missing_twofaccount_id_returns_not_found()
|
|||||||
->assertNotFound();
|
->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1025,7 +984,6 @@ public function test_get_otp_by_posting_invalid_uri_returns_validation_error()
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1036,7 +994,6 @@ public function test_get_otp_by_posting_invalid_parameters_returns_validation_er
|
|||||||
->assertStatus(422);
|
->assertStatus(422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1048,11 +1005,10 @@ public function test_count_returns_right_number_of_twofaccount()
|
|||||||
->json('GET', '/api/v1/twofaccounts/count')
|
->json('GET', '/api/v1/twofaccounts/count')
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertExactJson([
|
->assertExactJson([
|
||||||
'count' => 3
|
'count' => 3,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1069,7 +1025,6 @@ public function test_withdraw_returns_success()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1087,7 +1042,6 @@ public function test_withdraw_too_many_ids_returns_bad_request()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1100,7 +1054,6 @@ public function test_destroy_twofaccount_returns_success()
|
|||||||
->assertNoContent();
|
->assertNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1113,7 +1066,6 @@ public function test_destroy_missing_twofaccount_returns_not_found()
|
|||||||
->assertNotFound();
|
->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1127,7 +1079,6 @@ public function test_batch_destroy_twofaccount_returns_success()
|
|||||||
->assertNoContent();
|
->assertNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@ -1144,5 +1095,4 @@ public function test_batch_destroy_too_many_twofaccounts_returns_bad_request()
|
|||||||
'reason',
|
'reason',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\GroupAssignRequest;
|
use App\Api\v1\Requests\GroupAssignRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class GroupAssignRequestTest extends TestCase
|
class GroupAssignRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,8 +45,8 @@ public function provideValidData() : array
|
|||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'ids' => [
|
'ids' => [
|
||||||
1, 2, 3
|
1, 2, 3,
|
||||||
]
|
],
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -70,22 +69,21 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'ids' => null // required
|
'ids' => null, // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => '1,2,3' // array
|
'ids' => '1,2,3', // array
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => [
|
'ids' => [
|
||||||
'a', 'b', 'c' // array of integers
|
'a', 'b', 'c', // array of integers
|
||||||
]
|
],
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => [
|
'ids' => [
|
||||||
true, false // array of integers
|
true, false, // array of integers
|
||||||
]
|
],
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
namespace Tests\Api\v1\Requests;
|
namespace Tests\Api\v1\Requests;
|
||||||
|
|
||||||
use App\Models\Group;
|
|
||||||
use App\Api\v1\Requests\GroupStoreRequest;
|
use App\Api\v1\Requests\GroupStoreRequest;
|
||||||
|
use App\Models\Group;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\FeatureTestCase;
|
use Tests\FeatureTestCase;
|
||||||
|
|
||||||
class GroupStoreRequestTest extends FeatureTestCase
|
class GroupStoreRequestTest extends FeatureTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected String $uniqueGroupName = 'MyGroup';
|
protected String $uniqueGroupName = 'MyGroup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +47,7 @@ public function provideValidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'name' => 'validWord'
|
'name' => 'validWord',
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -80,21 +76,20 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'name' => '' // required
|
'name' => '', // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'name' => true // string
|
'name' => true, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'name' => 8 // string
|
'name' => 8, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'name' => 'mmmmmmoooooorrrrrreeeeeeettttttthhhhhhaaaaaaannnnnn32cccccchhhhhaaaaaarrrrrrsssssss' // max:32
|
'name' => 'mmmmmmoooooorrrrrreeeeeeettttttthhhhhhaaaaaaannnnnn32cccccchhhhhaaaaaarrrrrrsssssss', // max:32
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'name' => $this->uniqueGroupName // unique
|
'name' => $this->uniqueGroupName, // unique
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,14 +4,13 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\QrCodeDecodeRequest;
|
use App\Api\v1\Requests\QrCodeDecodeRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\Classes\LocalFile;
|
use Tests\Classes\LocalFile;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class QrCodeDecodeRequestTest extends TestCase
|
class QrCodeDecodeRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +47,7 @@ public function provideValidData() : array
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'qrcode' => $file
|
'qrcode' => $file,
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -71,18 +70,17 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'qrcode' => null // required
|
'qrcode' => null, // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'qrcode' => true // image
|
'qrcode' => true, // image
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'qrcode' => 8 // image
|
'qrcode' => 8, // image
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'qrcode' => 'string' // image
|
'qrcode' => 'string', // image
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,20 +3,16 @@
|
|||||||
namespace Tests\Api\v1\Requests;
|
namespace Tests\Api\v1\Requests;
|
||||||
|
|
||||||
use App\Api\v1\Requests\SettingStoreRequest;
|
use App\Api\v1\Requests\SettingStoreRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Tests\FeatureTestCase;
|
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Tests\FeatureTestCase;
|
||||||
|
|
||||||
class SettingStoreRequestTest extends FeatureTestCase
|
class SettingStoreRequestTest extends FeatureTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected String $uniqueKey = 'UniqueKey';
|
protected String $uniqueKey = 'UniqueKey';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,15 +48,15 @@ public function provideValidData() : array
|
|||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'key' => 'MyKey',
|
'key' => 'MyKey',
|
||||||
'value' => true
|
'value' => true,
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'key' => 'MyKey',
|
'key' => 'MyKey',
|
||||||
'value' => 'MyValue'
|
'value' => 'MyValue',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'key' => 'MyKey',
|
'key' => 'MyKey',
|
||||||
'value' => 10
|
'value' => 10,
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -86,25 +82,24 @@ public function provideInvalidData() : array
|
|||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'key' => null, // required
|
'key' => null, // required
|
||||||
'value' => ''
|
'value' => '',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'key' => 'my-key', // alpha
|
'key' => 'my-key', // alpha
|
||||||
'value' => 'MyValue'
|
'value' => 'MyValue',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'key' => 10, // alpha
|
'key' => 10, // alpha
|
||||||
'value' => 'MyValue'
|
'value' => 'MyValue',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'key' => 'mmmmmmoooooorrrrrreeeeeeettttttthhhhhhaaaaaaannnnnn128cccccchhhhhaaaaaarrrrrraaaaaaaccccccttttttttteeeeeeeeerrrrrrrrsssssss', // max:128
|
'key' => 'mmmmmmoooooorrrrrreeeeeeettttttthhhhhhaaaaaaannnnnn128cccccchhhhhaaaaaarrrrrraaaaaaaccccccttttttttteeeeeeeeerrrrrrrrsssssss', // max:128
|
||||||
'value' => 'MyValue'
|
'value' => 'MyValue',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'key' => $this->uniqueKey, // unique
|
'key' => $this->uniqueKey, // unique
|
||||||
'value' => 'MyValue'
|
'value' => 'MyValue',
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\SettingUpdateRequest;
|
use App\Api\v1\Requests\SettingUpdateRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class SettingUpdateRequestTest extends TestCase
|
class SettingUpdateRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,13 +44,13 @@ public function provideValidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'value' => true
|
'value' => true,
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'value' => 'MyValue'
|
'value' => 'MyValue',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'value' => 10
|
'value' => 10,
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -74,12 +73,11 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'value' => '' // required
|
'value' => '', // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'value' => null // required
|
'value' => null, // required
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountBatchRequest;
|
use App\Api\v1\Requests\TwoFAccountBatchRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountBatchRequestTest extends TestCase
|
class TwoFAccountBatchRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,10 +44,10 @@ public function provideValidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'ids' => '1'
|
'ids' => '1',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => '1,2,5'
|
'ids' => '1,2,5',
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -71,42 +70,41 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'ids' => '' // required
|
'ids' => '', // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => null // required
|
'ids' => null, // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => true // string
|
'ids' => true, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => 10 // string
|
'ids' => 10, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => 'notaCommaSeparatedList' // regex
|
'ids' => 'notaCommaSeparatedList', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => 'a,b' // regex
|
'ids' => 'a,b', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => 'a,1' // regex
|
'ids' => 'a,1', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => ',1,2' // regex
|
'ids' => ',1,2', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => '1,,2' // regex
|
'ids' => '1,,2', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => '1,2,' // regex
|
'ids' => '1,2,', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => ',1,2,' // regex
|
'ids' => ',1,2,', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'ids' => '1;2' // regex
|
'ids' => '1;2', // regex
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,16 +3,14 @@
|
|||||||
namespace Tests\Api\v1\Requests;
|
namespace Tests\Api\v1\Requests;
|
||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountDynamicRequest;
|
use App\Api\v1\Requests\TwoFAccountDynamicRequest;
|
||||||
use App\Api\v1\Requests\TwoFAccountUriRequest;
|
|
||||||
use App\Api\v1\Requests\TwoFAccountStoreRequest;
|
use App\Api\v1\Requests\TwoFAccountStoreRequest;
|
||||||
|
use App\Api\v1\Requests\TwoFAccountUriRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountDynamicRequestTest extends TestCase
|
class TwoFAccountDynamicRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,5 +49,4 @@ public function test_returns_TwoFAccountStoreRequest_rules_otherwise()
|
|||||||
|
|
||||||
$this->assertEquals($twofaccountStoreRequest->rules(), $request->rules());
|
$this->assertEquals($twofaccountStoreRequest->rules(), $request->rules());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountImportRequest;
|
use App\Api\v1\Requests\TwoFAccountImportRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountImportRequestTest extends TestCase
|
class TwoFAccountImportRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +44,7 @@ public function provideValidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'payload' => 'otpauth-migration://offline?data=AEoATACEAEYASAA'
|
'payload' => 'otpauth-migration://offline?data=AEoATACEAEYASAA',
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -68,18 +67,17 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'payload' => null // required
|
'payload' => null, // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'payload' => '' // required
|
'payload' => '', // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'payload' => true // string
|
'payload' => true, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'payload' => 8 // string
|
'payload' => 8, // string
|
||||||
]]
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountReorderRequest;
|
use App\Api\v1\Requests\TwoFAccountReorderRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountReorderRequestTest extends TestCase
|
class TwoFAccountReorderRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,10 +44,10 @@ public function provideValidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'orderedIds' => [1,2,5]
|
'orderedIds' => [1, 2, 5],
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'orderedIds' => [5]
|
'orderedIds' => [5],
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -71,21 +70,20 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'orderedIds' => [] // required
|
'orderedIds' => [], // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'orderedIds' => null // required
|
'orderedIds' => null, // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'orderedIds' => 0 // array
|
'orderedIds' => 0, // array
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'orderedIds' => 'string' // array
|
'orderedIds' => 'string', // array
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'orderedIds' => true // array
|
'orderedIds' => true, // array
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountStoreRequest;
|
use App\Api\v1\Requests\TwoFAccountStoreRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountStoreRequestTest extends TestCase
|
class TwoFAccountStoreRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,5 +166,4 @@ public function provideInvalidData() : array
|
|||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountUpdateRequest;
|
use App\Api\v1\Requests\TwoFAccountUpdateRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountUpdateRequestTest extends TestCase
|
class TwoFAccountUpdateRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,5 +217,4 @@ public function provideInvalidData() : array
|
|||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,13 +4,12 @@
|
|||||||
|
|
||||||
use App\Api\v1\Requests\TwoFAccountUriRequest;
|
use App\Api\v1\Requests\TwoFAccountUriRequest;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class TwoFAccountUriRequestTest extends TestCase
|
class TwoFAccountUriRequestTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use WithoutMiddleware;
|
use WithoutMiddleware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,14 +44,14 @@ public function provideValidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test'
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpauth://hotp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test'
|
'uri' => 'otpauth://hotp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
'custom_otp' => 'steamtotp'
|
'custom_otp' => 'steamtotp',
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -75,33 +74,32 @@ public function provideInvalidData() : array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[[
|
[[
|
||||||
'uri' => null // required
|
'uri' => null, // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => '' // required
|
'uri' => '', // required
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => true // string
|
'uri' => true, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 8 // string
|
'uri' => 8, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpXauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test' // regex
|
'uri' => 'otpXauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test', // regex
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
'custom_otp' => 'notSteam' // not in
|
'custom_otp' => 'notSteam', // not in
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
'custom_otp' => 0 // string
|
'custom_otp' => 0, // string
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
'custom_otp' => true // string
|
'custom_otp' => true, // string
|
||||||
]],
|
]],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
class LocalFile extends SymfonyUploadedFile
|
class LocalFile extends SymfonyUploadedFile
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin creating a new local file fake.
|
* Begin creating a new local file fake.
|
||||||
*
|
*
|
||||||
@ -16,5 +15,4 @@ public static function fake()
|
|||||||
{
|
{
|
||||||
return new LocalFileFactory;
|
return new LocalFileFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user