mirror of
https://github.com/Bubka/2FAuth.git
synced 2024-11-22 08:13:11 +01:00
Bind TwoFAccounts to Users & Add relevant authorizations with policies
This commit is contained in:
parent
ed3a17a4fb
commit
3c77503fb1
@ -17,6 +17,7 @@
|
|||||||
use App\Facades\TwoFAccounts;
|
use App\Facades\TwoFAccounts;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Helpers\Helpers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ class TwoFAccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
return new TwoFAccountCollection(TwoFAccount::ordered()->get());
|
return new TwoFAccountCollection($request->user()->twofaccounts->sortBy('order_column'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,6 +41,8 @@ public function index(Request $request)
|
|||||||
*/
|
*/
|
||||||
public function show(TwoFAccount $twofaccount)
|
public function show(TwoFAccount $twofaccount)
|
||||||
{
|
{
|
||||||
|
$this->authorize('view', $twofaccount);
|
||||||
|
|
||||||
return new TwoFAccountReadResource($twofaccount);
|
return new TwoFAccountReadResource($twofaccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +54,8 @@ public function show(TwoFAccount $twofaccount)
|
|||||||
*/
|
*/
|
||||||
public function store(TwoFAccountDynamicRequest $request)
|
public function store(TwoFAccountDynamicRequest $request)
|
||||||
{
|
{
|
||||||
|
$this->authorize('create', TwoFAccount::class);
|
||||||
|
|
||||||
// Two possible cases :
|
// Two possible cases :
|
||||||
// - The most common case, an URI is provided by the QuickForm, thanks to a QR code live scan or file upload
|
// - The most common case, an URI is provided by the QuickForm, thanks to a QR code live scan or file upload
|
||||||
// -> We use that URI to define the account
|
// -> We use that URI to define the account
|
||||||
@ -65,7 +70,7 @@ public function store(TwoFAccountDynamicRequest $request)
|
|||||||
} else {
|
} else {
|
||||||
$twofaccount->fillWithOtpParameters($validated);
|
$twofaccount->fillWithOtpParameters($validated);
|
||||||
}
|
}
|
||||||
$twofaccount->save();
|
$request->user()->twofaccounts()->save($twofaccount);
|
||||||
|
|
||||||
// Possible group association
|
// Possible group association
|
||||||
Groups::assign($twofaccount->id);
|
Groups::assign($twofaccount->id);
|
||||||
@ -84,10 +89,12 @@ public function store(TwoFAccountDynamicRequest $request)
|
|||||||
*/
|
*/
|
||||||
public function update(TwoFAccountUpdateRequest $request, TwoFAccount $twofaccount)
|
public function update(TwoFAccountUpdateRequest $request, TwoFAccount $twofaccount)
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $twofaccount);
|
||||||
|
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
$twofaccount->fillWithOtpParameters($validated);
|
$twofaccount->fillWithOtpParameters($validated);
|
||||||
$twofaccount->save();
|
$request->user()->twofaccounts()->save($twofaccount);
|
||||||
|
|
||||||
return (new TwoFAccountReadResource($twofaccount))
|
return (new TwoFAccountReadResource($twofaccount))
|
||||||
->response()
|
->response()
|
||||||
@ -125,6 +132,9 @@ public function reorder(TwoFAccountReorderRequest $request)
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
|
$twofaccounts = TwoFAccount::whereIn('id', $validated['orderedIds'])->get();
|
||||||
|
$this->authorize('updateEach', [$twofaccounts[0], $twofaccounts]);
|
||||||
|
|
||||||
TwoFAccount::setNewOrder($validated['orderedIds']);
|
TwoFAccount::setNewOrder($validated['orderedIds']);
|
||||||
|
|
||||||
return response()->json(['message' => 'order saved'], 200);
|
return response()->json(['message' => 'order saved'], 200);
|
||||||
@ -161,7 +171,10 @@ public function export(TwoFAccountBatchRequest $request)
|
|||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TwoFAccountExportCollection(TwoFAccounts::export($validated['ids']));
|
$twofaccounts = TwoFAccounts::export($validated['ids']);
|
||||||
|
$this->authorize('viewEach', [$twofaccounts[0], $twofaccounts]);
|
||||||
|
|
||||||
|
return new TwoFAccountExportCollection($twofaccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,6 +191,7 @@ public function otp(Request $request, $id = null)
|
|||||||
// The request input is the ID of an existing account
|
// The request input is the ID of an existing account
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$twofaccount = TwoFAccount::findOrFail((int) $id);
|
$twofaccount = TwoFAccount::findOrFail((int) $id);
|
||||||
|
$this->authorize('view', $twofaccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The request input is an uri
|
// The request input is an uri
|
||||||
@ -213,7 +227,7 @@ 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' => $request->user()->twofaccounts->count()], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,7 +247,12 @@ public function withdraw(TwoFAccountBatchRequest $request)
|
|||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
TwoFAccounts::withdraw($validated['ids']);
|
$ids = Helpers::commaSeparatedToArray($validated['ids']);
|
||||||
|
$twofaccounts = TwoFAccount::whereIn('id', $ids)->get();
|
||||||
|
|
||||||
|
$this->authorize('updateEach', [$twofaccounts[0], $twofaccounts]);
|
||||||
|
|
||||||
|
TwoFAccounts::withdraw($ids);
|
||||||
|
|
||||||
return response()->json(['message' => 'accounts withdrawn'], 200);
|
return response()->json(['message' => 'accounts withdrawn'], 200);
|
||||||
}
|
}
|
||||||
@ -246,6 +265,8 @@ public function withdraw(TwoFAccountBatchRequest $request)
|
|||||||
*/
|
*/
|
||||||
public function destroy(TwoFAccount $twofaccount)
|
public function destroy(TwoFAccount $twofaccount)
|
||||||
{
|
{
|
||||||
|
$this->authorize('delete', $twofaccount);
|
||||||
|
|
||||||
TwoFAccounts::delete($twofaccount->id);
|
TwoFAccounts::delete($twofaccount->id);
|
||||||
|
|
||||||
return response()->json(null, 204);
|
return response()->json(null, 204);
|
||||||
@ -268,6 +289,11 @@ public function batchDestroy(TwoFAccountBatchRequest $request)
|
|||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ids = Helpers::commaSeparatedToArray($validated['ids']);
|
||||||
|
$twofaccounts = TwoFAccount::whereIn('id', $ids)->get();
|
||||||
|
|
||||||
|
$this->authorize('deleteEach', [$twofaccounts[0], $twofaccounts]);
|
||||||
|
|
||||||
TwoFAccounts::delete($validated['ids']);
|
TwoFAccounts::delete($validated['ids']);
|
||||||
|
|
||||||
return response()->json(null, 204);
|
return response()->json(null, 204);
|
||||||
|
@ -5,6 +5,14 @@
|
|||||||
use App\Services\TwoFAccountService;
|
use App\Services\TwoFAccountService;
|
||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static void withdraw(int|array|string $ids)
|
||||||
|
* @method \Illuminate\Support\Collection<int|string, \App\Models\TwoFAccount> migrate(string $migrationPayload)
|
||||||
|
* @method static \Illuminate\Support\Collection<int, \App\Models\TwoFAccount> export(int|array|string $ids)
|
||||||
|
* @method static int delete(int|array|string $ids)
|
||||||
|
*
|
||||||
|
* @see \App\Services\TwoFAccountService
|
||||||
|
*/
|
||||||
class TwoFAccounts extends Facade
|
class TwoFAccounts extends Facade
|
||||||
{
|
{
|
||||||
protected static function getFacadeAccessor()
|
protected static function getFacadeAccessor()
|
||||||
|
@ -26,4 +26,21 @@ public static function PadToBase32Format(?string $str) : string
|
|||||||
{
|
{
|
||||||
return blank($str) ? '' : strtoupper(str_pad($str, (int) ceil(strlen($str) / 8) * 8, '='));
|
return blank($str) ? '' : strtoupper(str_pad($str, (int) ceil(strlen($str) / 8) * 8, '='));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify comma separated list of values and explode it to an array of values
|
||||||
|
*
|
||||||
|
* @param mixed $ids
|
||||||
|
*/
|
||||||
|
public static function commaSeparatedToArray($ids) : mixed
|
||||||
|
{
|
||||||
|
if (is_string($ids)) {
|
||||||
|
$regex = "/^\d+(,{1}\d+)*$/";
|
||||||
|
if (preg_match($regex, $ids)) {
|
||||||
|
$ids = explode(',', $ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -695,4 +695,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function buildSortQuery()
|
||||||
|
{
|
||||||
|
return static::query()->where('user_id', $this->user_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Laragear\WebAuthn\WebAuthnAuthentication;
|
use Laragear\WebAuthn\WebAuthnAuthentication;
|
||||||
use Laravel\Passport\HasApiTokens;
|
use Laravel\Passport\HasApiTokens;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
|
|
||||||
class User extends Authenticatable implements WebAuthnAuthenticatable
|
class User extends Authenticatable implements WebAuthnAuthenticatable
|
||||||
{
|
{
|
||||||
@ -42,8 +41,9 @@ class User extends Authenticatable implements WebAuthnAuthenticatable
|
|||||||
* @var array<string,string>
|
* @var array<string,string>
|
||||||
*/
|
*/
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
'is_admin' => 'boolean',
|
'is_admin' => 'boolean',
|
||||||
|
'twofaccounts_count' => 'integer',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,4 +97,14 @@ static function ($query) use ($id) {
|
|||||||
}
|
}
|
||||||
)->first();
|
)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TwoFAccounts of the user.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany<TwoFAccount>
|
||||||
|
*/
|
||||||
|
public function twofaccounts()
|
||||||
|
{
|
||||||
|
return $this->hasMany(\App\Models\TwoFAccount::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
44
app/Policies/OwnershipTrait.php
Normal file
44
app/Policies/OwnershipTrait.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Contracts\Support\Arrayable;
|
||||||
|
|
||||||
|
trait OwnershipTrait
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ownership of single item condition
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param mixed $item
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isOwnerOf(User $user, mixed $item)
|
||||||
|
{
|
||||||
|
return $user->id === $item->user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ownership of collection condition
|
||||||
|
*
|
||||||
|
* @template TKey of array-key
|
||||||
|
* @template TValue
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isOwnerOfEach(User $user, $items)
|
||||||
|
{
|
||||||
|
foreach ($items as $item) {
|
||||||
|
if (! $this->isOwnerOf($user, $item)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
136
app/Policies/TwoFAccountPolicy.php
Normal file
136
app/Policies/TwoFAccountPolicy.php
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Access\Response;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
|
class TwoFAccountPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization, OwnershipTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function viewAny(User $user)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function view(User $user, TwoFAccount $twofaccount)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOf($user, $twofaccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view all provided models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @param \Illuminate\Support\Collection<int, \App\Models\TwoFAccount> $twofaccounts
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function viewEach(User $user, TwoFAccount $twofaccount, $twofaccounts)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOfEach($user, $twofaccounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function create(User $user)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function update(User $user, TwoFAccount $twofaccount)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOf($user, $twofaccount);
|
||||||
|
// ? Response::allow()
|
||||||
|
// : Response::deny('You do not own this post.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update all provided models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @param \Illuminate\Support\Collection<int, \App\Models\TwoFAccount> $twofaccounts
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function updateEach(User $user, TwoFAccount $twofaccount, $twofaccounts)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOfEach($user, $twofaccounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function delete(User $user, TwoFAccount $twofaccount)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOf($user, $twofaccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete all provided models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @param \Illuminate\Support\Collection<int, \App\Models\TwoFAccount> $twofaccounts
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function deleteEach(User $user, TwoFAccount $twofaccount, $twofaccounts)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOfEach($user, $twofaccounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function restore(User $user, TwoFAccount $twofaccount)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOf($user, $twofaccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @param \App\Models\TwoFAccount $twofaccount
|
||||||
|
* @return \Illuminate\Auth\Access\Response|bool
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, TwoFAccount $twofaccount)
|
||||||
|
{
|
||||||
|
return $this->isOwnerOf($user, $twofaccount);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@
|
|||||||
use App\Extensions\RemoteUserProvider;
|
use App\Extensions\RemoteUserProvider;
|
||||||
use App\Extensions\WebauthnCredentialBroker;
|
use App\Extensions\WebauthnCredentialBroker;
|
||||||
use App\Facades\Settings;
|
use App\Facades\Settings;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Policies\TwoFAccountPolicy;
|
||||||
use App\Services\Auth\ReverseProxyGuard;
|
use App\Services\Auth\ReverseProxyGuard;
|
||||||
use Illuminate\Auth\Passwords\DatabaseTokenRepository;
|
use Illuminate\Auth\Passwords\DatabaseTokenRepository;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
@ -20,7 +22,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
* @var array<class-string, class-string>
|
* @var array<class-string, class-string>
|
||||||
*/
|
*/
|
||||||
protected $policies = [
|
protected $policies = [
|
||||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
TwoFAccount::class => TwoFAccountPolicy::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use App\Factories\MigratorFactoryInterface;
|
use App\Factories\MigratorFactoryInterface;
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Helpers\Helpers;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ public static function withdraw($ids) : void
|
|||||||
{
|
{
|
||||||
// $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 = Helpers::commaSeparatedToArray($ids);
|
||||||
|
|
||||||
// whereIn() expects an array
|
// whereIn() expects an array
|
||||||
$ids = is_array($ids) ? $ids : func_get_args();
|
$ids = is_array($ids) ? $ids : func_get_args();
|
||||||
@ -66,7 +67,7 @@ public function migrate(string $migrationPayload) : Collection
|
|||||||
*/
|
*/
|
||||||
public static function export($ids) : Collection
|
public static function export($ids) : Collection
|
||||||
{
|
{
|
||||||
$ids = self::commaSeparatedToArray($ids);
|
$ids = Helpers::commaSeparatedToArray($ids);
|
||||||
$twofaccounts = TwoFAccount::whereIn('id', $ids)->get();
|
$twofaccounts = TwoFAccount::whereIn('id', $ids)->get();
|
||||||
|
|
||||||
return $twofaccounts;
|
return $twofaccounts;
|
||||||
@ -82,7 +83,7 @@ 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 = Helpers::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);
|
||||||
|
|
||||||
@ -116,21 +117,5 @@ private static function markAsDuplicate(Collection $twofaccounts) : Collection
|
|||||||
|
|
||||||
return $twofaccounts;
|
return $twofaccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Explode a comma separated list of IDs to an array of IDs
|
|
||||||
*
|
|
||||||
* @param int|array|string $ids
|
|
||||||
*/
|
|
||||||
private static function commaSeparatedToArray($ids) : mixed
|
|
||||||
{
|
|
||||||
if (is_string($ids)) {
|
|
||||||
$regex = "/^\d+(,{1}\d+)*$/";
|
|
||||||
if (preg_match($regex, $ids)) {
|
|
||||||
$ids = explode(',', $ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ids;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('twofaccounts', function (Blueprint $table) {
|
||||||
|
$table->unsignedInteger('user_id')
|
||||||
|
->after('id')
|
||||||
|
->nullable();
|
||||||
|
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('groups', function (Blueprint $table) {
|
||||||
|
$table->unsignedInteger('user_id')
|
||||||
|
->after('id')
|
||||||
|
->nullable();
|
||||||
|
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($legacySingleUser = DB::table('users')->first()) {
|
||||||
|
DB::table('twofaccounts')->update(['user_id' => $legacySingleUser->id]);
|
||||||
|
DB::table('groups')->update(['user_id' => $legacySingleUser->id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::whenTableHasColumn('twofaccounts', 'user_id', function (Blueprint $table) {
|
||||||
|
// cannot drop foreign keys in SQLite:
|
||||||
|
if (DB::getDriverName() !== 'sqlite') {
|
||||||
|
$table->dropForeign(['user_id']);
|
||||||
|
}
|
||||||
|
$table->dropColumn('user_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::whenTableHasColumn('groups', 'user_id', function (Blueprint $table) {
|
||||||
|
// cannot drop foreign keys in SQLite:
|
||||||
|
if (DB::getDriverName() !== 'sqlite') {
|
||||||
|
$table->dropForeign(['user_id']);
|
||||||
|
}
|
||||||
|
$table->dropColumn('user_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user