mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-06-19 03:16:49 +02:00
Refactor Import feature to support more sources of export
This commit is contained in:
parent
062d809a28
commit
41387453d5
55
app/Api/v1/Controllers/ImportController.php
Normal file
55
app/Api/v1/Controllers/ImportController.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Api\v1\Controllers;
|
||||||
|
|
||||||
|
use App\Api\v1\Requests\TwoFAccountImportRequest;
|
||||||
|
use App\Api\v1\Resources\TwoFAccountCollection;
|
||||||
|
use App\Contracts\MigrationService;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class ImportController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var $migrator The Migration service
|
||||||
|
*/
|
||||||
|
protected $migrator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct(MigrationService $migrationService)
|
||||||
|
{
|
||||||
|
$this->migrator = $migrationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Google Auth data to a TwoFAccounts collection
|
||||||
|
*
|
||||||
|
* @param \App\Api\v1\Requests\TwoFAccountImportRequest $request
|
||||||
|
* @return \App\Api\v1\Resources\TwoFAccountCollection
|
||||||
|
*/
|
||||||
|
public function googleAuth(TwoFAccountImportRequest $request)
|
||||||
|
{
|
||||||
|
$request->merge(['withSecret' => true]);
|
||||||
|
$twofaccounts = $this->migrator->migrate($request->uri);
|
||||||
|
|
||||||
|
return new TwoFAccountCollection($twofaccounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Aegis data to a TwoFAccounts collection
|
||||||
|
*
|
||||||
|
* @param \App\Api\v1\Requests\TwoFAccountImportRequest $request
|
||||||
|
* @return \App\Api\v1\Resources\TwoFAccountCollection
|
||||||
|
*/
|
||||||
|
public function aegis(TwoFAccountImportRequest $request)
|
||||||
|
{
|
||||||
|
$request->merge(['withSecret' => true]);
|
||||||
|
$twofaccounts = $this->migrator->migrate($request->uri);
|
||||||
|
|
||||||
|
return new TwoFAccountCollection($twofaccounts);
|
||||||
|
}
|
||||||
|
}
|
@ -102,21 +102,6 @@ class TwoFAccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dry-import Google authenticator data
|
|
||||||
*
|
|
||||||
* @param \App\Api\v1\Requests\TwoFAccountImportRequest $request
|
|
||||||
* @return \App\Api\v1\Resources\TwoFAccountCollection
|
|
||||||
*/
|
|
||||||
public function import(TwoFAccountImportRequest $request)
|
|
||||||
{
|
|
||||||
$request->merge(['withSecret' => true]);
|
|
||||||
$twofaccounts = TwoFAccounts::convertMigrationFromGA($request->uri);
|
|
||||||
|
|
||||||
return new TwoFAccountCollection($twofaccounts);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save 2FA accounts order
|
* Save 2FA accounts order
|
||||||
*
|
*
|
||||||
|
16
app/Contracts/MigrationService.php
Normal file
16
app/Contracts/MigrationService.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Contracts;
|
||||||
|
|
||||||
|
use \Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
interface MigrationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert migration data to a 2FAccounts collection.
|
||||||
|
*
|
||||||
|
* @param mixed $migrationPayload
|
||||||
|
* @return \Illuminate\Support\Collection The converted accounts
|
||||||
|
*/
|
||||||
|
public function migrate(mixed $migrationPayload) : Collection;
|
||||||
|
}
|
62
app/Providers/MigrationServiceProvider.php
Normal file
62
app/Providers/MigrationServiceProvider.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Api\v1\Controllers\ImportController;
|
||||||
|
use App\Contracts\MigrationService;
|
||||||
|
use App\Services\Migrators\GoogleAuthMigrator;
|
||||||
|
use App\Services\Migrators\AegisMigrator;
|
||||||
|
use App\Services\Migrators\PlainTextMigrator;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||||
|
|
||||||
|
class MigrationServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->when(ImportController::class)
|
||||||
|
->needs(MigrationService::class)
|
||||||
|
->give(function () {
|
||||||
|
switch (request()->route()->getName()) {
|
||||||
|
case 'import.googleAuth':
|
||||||
|
return $this->app->get(GoogleAuthMigrator::class);
|
||||||
|
|
||||||
|
case 'import.aegis':
|
||||||
|
return $this->app->get(AegisMigrator::class);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return $this->app->get(PlainTextMigrator::class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the services provided by the provider.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function provides()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
GoogleAuthMigrator::class,
|
||||||
|
AegisMigrator::class,
|
||||||
|
PlainTextMigrator::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
20
app/Services/Migrators/AegisMigrator.php
Normal file
20
app/Services/Migrators/AegisMigrator.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
|
use App\Contracts\MigrationService;
|
||||||
|
use \Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class AegisMigrator implements MigrationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert migration data to a 2FAccounts collection.
|
||||||
|
*
|
||||||
|
* @param mixed $migrationPayload
|
||||||
|
* @return \Illuminate\Support\Collection The converted accounts
|
||||||
|
*/
|
||||||
|
public function migrate(mixed $migrationPayload) : Collection
|
||||||
|
{
|
||||||
|
return Collect(['collected from aegisMigrator']);
|
||||||
|
}
|
||||||
|
}
|
83
app/Services/Migrators/GoogleAuthMigrator.php
Normal file
83
app/Services/Migrators/GoogleAuthMigrator.php
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use App\Contracts\MigrationService;
|
||||||
|
use \Illuminate\Support\Collection;
|
||||||
|
use ParagonIE\ConstantTime\Base32;
|
||||||
|
use App\Protobuf\GAuthValueMapping;
|
||||||
|
use App\Protobuf\GoogleAuth\Payload;
|
||||||
|
use App\Protobuf\GoogleAuth\Payload\OtpType;
|
||||||
|
use App\Protobuf\GoogleAuth\Payload\Algorithm;
|
||||||
|
use App\Protobuf\GoogleAuth\Payload\DigitCount;
|
||||||
|
use App\Exceptions\InvalidGoogleAuthMigration;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class GoogleAuthMigrator extends Migrator implements MigrationService
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Google Authenticator migration URI to a set of TwoFAccount objects.
|
||||||
|
*
|
||||||
|
* @param mixed $migrationPayload migration uri provided by Google Authenticator export feature
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Support\Collection The converted accounts
|
||||||
|
*/
|
||||||
|
public function migrate(mixed $migrationPayload) : Collection
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$migrationData = base64_decode(urldecode(Str::replace('otpauth-migration://offline?data=', '', $migrationPayload)));
|
||||||
|
$protobuf = new Payload();
|
||||||
|
$protobuf->mergeFromString($migrationData);
|
||||||
|
$otpParameters = $protobuf->getOtpParameters();
|
||||||
|
}
|
||||||
|
catch (Exception $ex) {
|
||||||
|
Log::error("Protobuf failed to get OTP parameters from provided migration URI");
|
||||||
|
Log::error($ex->getMessage());
|
||||||
|
|
||||||
|
throw new InvalidGoogleAuthMigration();
|
||||||
|
}
|
||||||
|
|
||||||
|
$twofaccounts = array();
|
||||||
|
|
||||||
|
foreach ($otpParameters->getIterator() as $key => $otp_parameters) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$parameters = array();
|
||||||
|
$parameters['otp_type'] = GAuthValueMapping::OTP_TYPE[OtpType::name($otp_parameters->getType())];
|
||||||
|
$parameters['service'] = $otp_parameters->getIssuer();
|
||||||
|
$parameters['account'] = str_replace($parameters['service'].':', '', $otp_parameters->getName());
|
||||||
|
$parameters['secret'] = Base32::encodeUpper($otp_parameters->getSecret());
|
||||||
|
$parameters['algorithm'] = GAuthValueMapping::ALGORITHM[Algorithm::name($otp_parameters->getAlgorithm())];
|
||||||
|
$parameters['digits'] = GAuthValueMapping::DIGIT_COUNT[DigitCount::name($otp_parameters->getDigits())];
|
||||||
|
$parameters['counter'] = $parameters['otp_type'] === TwoFAccount::HOTP ? $otp_parameters->getCounter() : null;
|
||||||
|
$parameters['period'] = $parameters['otp_type'] === TwoFAccount::TOTP ? $otp_parameters->getPeriod() : null;
|
||||||
|
|
||||||
|
$twofaccounts[$key] = new TwoFAccount;
|
||||||
|
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
||||||
|
}
|
||||||
|
catch (Exception $exception) {
|
||||||
|
|
||||||
|
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
||||||
|
Log::error($exception->getMessage());
|
||||||
|
|
||||||
|
// The token failed to generate a valid account so we create a fake account to be returned.
|
||||||
|
$fakeAccount = new TwoFAccount();
|
||||||
|
$fakeAccount->id = -2;
|
||||||
|
$fakeAccount->otp_type = $fakeAccount::TOTP;
|
||||||
|
// Only basic fields are filled to limit the risk of another exception.
|
||||||
|
$fakeAccount->account = $otp_parameters->getName();
|
||||||
|
$fakeAccount->service = $otp_parameters->getIssuer();
|
||||||
|
// The secret field is used to pass the error, not very clean but will do the job for now.
|
||||||
|
$fakeAccount->secret = $exception->getMessage();
|
||||||
|
|
||||||
|
$twofaccounts[$key] = $fakeAccount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::markAsDuplicate(collect($twofaccounts));
|
||||||
|
}
|
||||||
|
}
|
39
app/Services/Migrators/Migrator.php
Normal file
39
app/Services/Migrators/Migrator.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
|
use App\Models\TwoFAccount;
|
||||||
|
use \Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
abstract class Migrator
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the given collection with items marked as Duplicates (using id=-1) if a similar record exists in database
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Support\Collection $twofaccounts
|
||||||
|
* @return \Illuminate\Support\Collection
|
||||||
|
*/
|
||||||
|
protected static function markAsDuplicate(Collection $twofaccounts) : Collection
|
||||||
|
{
|
||||||
|
$storage = TwoFAccount::all();
|
||||||
|
|
||||||
|
$twofaccounts = $twofaccounts->map(function ($twofaccount, $key) use ($storage) {
|
||||||
|
if ($storage->contains(function ($value, $key) use ($twofaccount) {
|
||||||
|
return $value->secret == $twofaccount->secret
|
||||||
|
&& $value->service == $twofaccount->service
|
||||||
|
&& $value->account == $twofaccount->account
|
||||||
|
&& $value->otp_type == $twofaccount->otp_type
|
||||||
|
&& $value->digits == $twofaccount->digits
|
||||||
|
&& $value->algorithm == $twofaccount->algorithm;
|
||||||
|
})) {
|
||||||
|
$twofaccount->id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $twofaccount;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $twofaccounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
app/Services/Migrators/PlainTextMigrator.php
Normal file
20
app/Services/Migrators/PlainTextMigrator.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migrators;
|
||||||
|
|
||||||
|
use App\Contracts\MigrationService;
|
||||||
|
use \Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class PlainTextMigrator implements MigrationService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert migration data to a 2FAccounts collection.
|
||||||
|
*
|
||||||
|
* @param mixed $migrationPayload
|
||||||
|
* @return \Illuminate\Support\Collection The converted accounts
|
||||||
|
*/
|
||||||
|
public function migrate(mixed $migrationPayload) : Collection
|
||||||
|
{
|
||||||
|
return Collect(['collected from plainTextMigrator']);
|
||||||
|
}
|
||||||
|
}
|
@ -3,17 +3,7 @@
|
|||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Models\TwoFAccount;
|
use App\Models\TwoFAccount;
|
||||||
use App\Exceptions\InvalidGoogleAuthMigration;
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use ParagonIE\ConstantTime\Base32;
|
|
||||||
use App\Protobuf\GAuthValueMapping;
|
|
||||||
use App\Protobuf\GoogleAuth\Payload;
|
|
||||||
use App\Protobuf\GoogleAuth\Payload\OtpType;
|
|
||||||
use App\Protobuf\GoogleAuth\Payload\Algorithm;
|
|
||||||
use App\Protobuf\GoogleAuth\Payload\DigitCount;
|
|
||||||
|
|
||||||
class TwoFAccountService
|
class TwoFAccountService
|
||||||
{
|
{
|
||||||
@ -60,70 +50,6 @@ class TwoFAccountService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Google Authenticator migration URI to a set of TwoFAccount objects
|
|
||||||
*
|
|
||||||
* @param string $migrationUri migration uri provided by Google Authenticator export feature
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Support\Collection The converted accounts
|
|
||||||
*/
|
|
||||||
public static function convertMigrationFromGA($migrationUri) : Collection
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$migrationData = base64_decode(urldecode(Str::replace('otpauth-migration://offline?data=', '', $migrationUri)));
|
|
||||||
$protobuf = new Payload();
|
|
||||||
$protobuf->mergeFromString($migrationData);
|
|
||||||
$otpParameters = $protobuf->getOtpParameters();
|
|
||||||
}
|
|
||||||
catch (Exception $ex) {
|
|
||||||
Log::error("Protobuf failed to get OTP parameters from provided migration URI");
|
|
||||||
Log::error($ex->getMessage());
|
|
||||||
|
|
||||||
throw new InvalidGoogleAuthMigration();
|
|
||||||
}
|
|
||||||
|
|
||||||
$twofaccounts = array();
|
|
||||||
|
|
||||||
foreach ($otpParameters->getIterator() as $key => $otp_parameters) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
$parameters = array();
|
|
||||||
$parameters['otp_type'] = GAuthValueMapping::OTP_TYPE[OtpType::name($otp_parameters->getType())];
|
|
||||||
$parameters['service'] = $otp_parameters->getIssuer();
|
|
||||||
$parameters['account'] = str_replace($parameters['service'].':', '', $otp_parameters->getName());
|
|
||||||
$parameters['secret'] = Base32::encodeUpper($otp_parameters->getSecret());
|
|
||||||
$parameters['algorithm'] = GAuthValueMapping::ALGORITHM[Algorithm::name($otp_parameters->getAlgorithm())];
|
|
||||||
$parameters['digits'] = GAuthValueMapping::DIGIT_COUNT[DigitCount::name($otp_parameters->getDigits())];
|
|
||||||
$parameters['counter'] = $parameters['otp_type'] === TwoFAccount::HOTP ? $otp_parameters->getCounter() : null;
|
|
||||||
$parameters['period'] = $parameters['otp_type'] === TwoFAccount::TOTP ? $otp_parameters->getPeriod() : null;
|
|
||||||
|
|
||||||
$twofaccounts[$key] = new TwoFAccount;
|
|
||||||
$twofaccounts[$key]->fillWithOtpParameters($parameters);
|
|
||||||
}
|
|
||||||
catch (Exception $exception) {
|
|
||||||
|
|
||||||
Log::error(sprintf('Cannot instanciate a TwoFAccount object with OTP parameters from imported item #%s', $key));
|
|
||||||
Log::error($exception->getMessage());
|
|
||||||
|
|
||||||
// The token failed to generate a valid account so we create a fake account to be returned.
|
|
||||||
$fakeAccount = new TwoFAccount();
|
|
||||||
$fakeAccount->id = -2;
|
|
||||||
$fakeAccount->otp_type = $fakeAccount::TOTP;
|
|
||||||
// Only basic fields are filled to limit the risk of another exception.
|
|
||||||
$fakeAccount->account = $otp_parameters->getName();
|
|
||||||
$fakeAccount->service = $otp_parameters->getIssuer();
|
|
||||||
// The secret field is used to pass the error, not very clean but will do the job for now.
|
|
||||||
$fakeAccount->secret = $exception->getMessage();
|
|
||||||
|
|
||||||
$twofaccounts[$key] = $fakeAccount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::markAsDuplicate(collect($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
|
||||||
*
|
*
|
||||||
@ -141,33 +67,4 @@ class TwoFAccountService
|
|||||||
|
|
||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the given collection with items marked as Duplicates (using id=-1) if a similar record exists in database
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Support\Collection $twofaccounts
|
|
||||||
* @return \Illuminate\Support\Collection
|
|
||||||
*/
|
|
||||||
private static function markAsDuplicate(Collection $twofaccounts) : Collection
|
|
||||||
{
|
|
||||||
$storage = TwoFAccount::all();
|
|
||||||
|
|
||||||
$twofaccounts = $twofaccounts->map(function ($twofaccount, $key) use ($storage) {
|
|
||||||
if ($storage->contains(function ($value, $key) use ($twofaccount) {
|
|
||||||
return $value->secret == $twofaccount->secret
|
|
||||||
&& $value->service == $twofaccount->service
|
|
||||||
&& $value->account == $twofaccount->account
|
|
||||||
&& $value->otp_type == $twofaccount->otp_type
|
|
||||||
&& $value->digits == $twofaccount->digits
|
|
||||||
&& $value->algorithm == $twofaccount->algorithm;
|
|
||||||
})) {
|
|
||||||
$twofaccount->id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $twofaccount;
|
|
||||||
});
|
|
||||||
|
|
||||||
return $twofaccounts;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -175,6 +175,7 @@ return [
|
|||||||
App\Providers\EventServiceProvider::class,
|
App\Providers\EventServiceProvider::class,
|
||||||
App\Providers\RouteServiceProvider::class,
|
App\Providers\RouteServiceProvider::class,
|
||||||
App\Providers\TwoFAuthServiceProvider::class,
|
App\Providers\TwoFAuthServiceProvider::class,
|
||||||
|
App\Providers\MigrationServiceProvider::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -145,8 +145,8 @@
|
|||||||
if( this.$route.params.migrationUri ) {
|
if( this.$route.params.migrationUri ) {
|
||||||
this.migrationUri = this.$route.params.migrationUri
|
this.migrationUri = this.$route.params.migrationUri
|
||||||
this.isFetching = true
|
this.isFetching = true
|
||||||
|
|
||||||
await this.axios.post('/api/v1/twofaccounts/import', { uri: this.migrationUri }).then(response => {
|
await this.axios.post('/api/v1/import/google-auth', { uri: this.migrationUri }).then(response => {
|
||||||
response.data.forEach((data) => {
|
response.data.forEach((data) => {
|
||||||
data.imported = -1;
|
data.imported = -1;
|
||||||
this.exportedAccounts.push(data)
|
this.exportedAccounts.push(data)
|
||||||
|
@ -27,7 +27,6 @@ Route::group(['middleware' => 'auth:api-guard'], function () {
|
|||||||
Route::delete('settings/{settingName}', 'SettingController@destroy')->name('settings.destroy');
|
Route::delete('settings/{settingName}', 'SettingController@destroy')->name('settings.destroy');
|
||||||
|
|
||||||
Route::delete('twofaccounts', 'TwoFAccountController@batchDestroy')->name('twofaccounts.batchDestroy');
|
Route::delete('twofaccounts', 'TwoFAccountController@batchDestroy')->name('twofaccounts.batchDestroy');
|
||||||
Route::post('twofaccounts/import', 'TwoFAccountController@import')->name('twofaccounts.import');
|
|
||||||
Route::patch('twofaccounts/withdraw', 'TwoFAccountController@withdraw')->name('twofaccounts.withdraw');
|
Route::patch('twofaccounts/withdraw', 'TwoFAccountController@withdraw')->name('twofaccounts.withdraw');
|
||||||
Route::post('twofaccounts/reorder', 'TwoFAccountController@reorder')->name('twofaccounts.reorder');
|
Route::post('twofaccounts/reorder', 'TwoFAccountController@reorder')->name('twofaccounts.reorder');
|
||||||
Route::post('twofaccounts/preview', 'TwoFAccountController@preview')->name('twofaccounts.preview');
|
Route::post('twofaccounts/preview', 'TwoFAccountController@preview')->name('twofaccounts.preview');
|
||||||
@ -37,6 +36,9 @@ Route::group(['middleware' => 'auth:api-guard'], function () {
|
|||||||
Route::post('twofaccounts/otp', 'TwoFAccountController@otp')->name('twofaccounts.otp');
|
Route::post('twofaccounts/otp', 'TwoFAccountController@otp')->name('twofaccounts.otp');
|
||||||
Route::apiResource('twofaccounts', 'TwoFAccountController');
|
Route::apiResource('twofaccounts', 'TwoFAccountController');
|
||||||
|
|
||||||
|
Route::post('import/google-auth', 'ImportController@googleAuth')->name('import.googleAuth');
|
||||||
|
Route::post('import/aegis', 'ImportController@aegis')->name('import.aegis');
|
||||||
|
|
||||||
Route::get('groups/{group}/twofaccounts', 'GroupController@accounts')->name('groups.show.twofaccounts');
|
Route::get('groups/{group}/twofaccounts', 'GroupController@accounts')->name('groups.show.twofaccounts');
|
||||||
Route::post('groups/{group}/assign', 'GroupController@assignAccounts')->name('groups.assign.twofaccounts');
|
Route::post('groups/{group}/assign', 'GroupController@assignAccounts')->name('groups.assign.twofaccounts');
|
||||||
Route::apiResource('groups', 'GroupController');
|
Route::apiResource('groups', 'GroupController');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user