Compare commits
2 Commits
9580fb1cd9
...
b1067e1378
Author | SHA1 | Date | |
---|---|---|---|
b1067e1378 | |||
45fb023d8a |
@ -1,3 +1,4 @@
|
||||
APP_ADMIN=
|
||||
APP_DEBUG=false
|
||||
APP_NAME=OSB
|
||||
APP_NAME_HTML_LONG="<b>Graytech</b>Hosting"
|
||||
@ -7,6 +8,8 @@ APP_KEY=
|
||||
APP_TIMEZONE=Australia/Melbourne
|
||||
APP_URL=https://www.graytech.net.au
|
||||
|
||||
AUTH_PASSWORD_RESET_TOKEN_TABLE=password_resets
|
||||
|
||||
LOG_CHANNEL=daily
|
||||
|
||||
DB_CONNECTION=pgsql
|
||||
|
@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Models\{ProviderOauth,Site,User};
|
||||
use App\Jobs\AccountingAccountSync as Job;
|
||||
|
||||
/**
|
||||
* Synchronise Customers with Accounts
|
||||
*/
|
||||
class AccountingAccountSync extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:account:sync'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Synchronise accounts with accounting system';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
Job::dispatchSync($to);
|
||||
}
|
||||
}
|
@ -1,33 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Intuit\Jobs\AccountingCustomerUpdate;
|
||||
use Intuit\Models\Customer as AccAccount;
|
||||
|
||||
use App\Models\{Account,ProviderOauth,Site,User};
|
||||
use App\Models\{Account,ProviderOauth,User};
|
||||
|
||||
class AccountingAccountAdd extends Command
|
||||
class AccountAdd extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:account:add'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}'
|
||||
.' {id : Account ID}';
|
||||
protected $signature = 'intuit:account:add'
|
||||
.' {id : Account ID}'
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Add an account to the accounting provider';
|
||||
protected $description = 'Add an account to quickbooks';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
@ -36,12 +35,9 @@ class AccountingAccountAdd extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
@ -1,33 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Intuit\Exceptions\ConnectionIssueException;
|
||||
|
||||
use App\Models\{ProviderOauth,Site,User};
|
||||
use App\Models\{ProviderOauth,User};
|
||||
|
||||
class AccountingAccountGet extends Command
|
||||
class AccountGet extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:account:get'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}'
|
||||
.' {id : Account ID}';
|
||||
protected $signature = 'intuit:account:get'
|
||||
.' {id : Account ID}'
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Get an account from the accounting provider';
|
||||
protected $description = 'Get an account from quickbooks';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
@ -36,12 +35,9 @@ class AccountingAccountGet extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
@ -52,7 +48,9 @@ class AccountingAccountGet extends Command
|
||||
} catch (ConnectException|ConnectionIssueException $e) {
|
||||
$this->error($e->getMessage());
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
49
app/Console/Commands/Intuit/AccountSync.php
Normal file
49
app/Console/Commands/Intuit/AccountSync.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use App\Models\{ProviderOauth,User};
|
||||
use App\Jobs\AccountingAccountSync as Job;
|
||||
|
||||
/**
|
||||
* Synchronise Customers with Accounts
|
||||
*/
|
||||
class AccountSync extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'intuit:account:sync'
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Synchronise accounts with quickbooks';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
Job::dispatchSync($to);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -1,26 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Intuit\Jobs\AccountingInvoiceUpdate;
|
||||
use Intuit\Models\Invoice as AccInvoice;
|
||||
|
||||
use App\Models\{Invoice,ProviderOauth,Site,User};
|
||||
use App\Models\{Invoice,ProviderOauth,User};
|
||||
|
||||
class AccountingInvoiceAdd extends Command
|
||||
class InvoiceAdd extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:invoice:add'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}'
|
||||
.' {id : Invoice ID}';
|
||||
.' {id : Invoice ID}'
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -33,15 +32,13 @@ class AccountingInvoiceAdd extends Command
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
@ -78,12 +75,14 @@ class AccountingInvoiceAdd extends Command
|
||||
// Some validation
|
||||
if (! ($ref=$key->product->provider_ref($so))) {
|
||||
$this->error(sprintf('Accounting not defined in product [%d]',$key->product_id));
|
||||
exit(1);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
if ($key->taxes->count() !== 1) {
|
||||
$this->error(sprintf('Cannot handle when there is not just 1 tax line [%d]',$key->id));
|
||||
exit(1);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$c++;
|
@ -1,33 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Intuit\Exceptions\ConnectionIssueException;
|
||||
|
||||
use App\Models\{ProviderOauth,Site,User};
|
||||
use App\Models\{ProviderOauth,User};
|
||||
|
||||
class AccountingInvoiceGet extends Command
|
||||
class InvoiceGet extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:invoice:get'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}'
|
||||
.' {id : Invoice ID}';
|
||||
protected $signature = 'intuit:invoice:get'
|
||||
.' {id : Invoice ID}'
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Get an invoice from the accounting provider';
|
||||
protected $description = 'Get an invoice from the quickbooks';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
@ -36,12 +35,9 @@ class AccountingInvoiceGet extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
@ -52,7 +48,9 @@ class AccountingInvoiceGet extends Command
|
||||
} catch (ConnectException|ConnectionIssueException $e) {
|
||||
$this->error($e->getMessage());
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -1,25 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Models\{Product, ProviderOauth, Site, User};
|
||||
use App\Models\{Product,ProviderOauth,User};
|
||||
use App\Jobs\AccountingItemSync as Job;
|
||||
|
||||
class AccountingItemList extends Command
|
||||
class ItemList extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:item:list'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}';
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -35,12 +33,9 @@ class AccountingItemList extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (($x=$so->tokens->where('user_id',$uo->id))->count() !== 1)
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
@ -67,5 +62,7 @@ class AccountingItemList extends Command
|
||||
else
|
||||
$this->info(sprintf('Product [%d](%s) set to accounting [%s]',$po->id,$po->name,$po->accounting));
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -1,27 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Intuit\Exceptions\ConnectionIssueException;
|
||||
|
||||
use App\Jobs\AccountingPaymentSync as Job;
|
||||
use App\Models\{ProviderOauth,Site,User};
|
||||
use App\Models\{ProviderOauth,User};
|
||||
|
||||
class AccountingPaymentGet extends Command
|
||||
class PaymentGet extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:payment:get'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}'
|
||||
.' {id : Payment ID}';
|
||||
.' {id : Payment ID}'
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -37,12 +36,9 @@ class AccountingPaymentGet extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
@ -59,5 +55,7 @@ class AccountingPaymentGet extends Command
|
||||
|
||||
if ($acc)
|
||||
Job::dispatchSync($to,$acc);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -1,24 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Models\{ProviderOauth,Site,User};
|
||||
use App\Models\{ProviderOauth,User};
|
||||
use App\Jobs\AccountingPaymentSync as Job;
|
||||
|
||||
class AccountingPaymentSync extends Command
|
||||
class PaymentSync extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:payment:sync'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}';
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -34,17 +33,16 @@ class AccountingPaymentSync extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
$api = $to->API();
|
||||
foreach ($api->getPayments() as $acc)
|
||||
Job::dispatchSync($to,$acc);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -1,27 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
namespace App\Console\Commands\Intuit;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
use App\Models\{ProviderOauth,Site,User};
|
||||
use App\Models\{ProviderOauth,User};
|
||||
use App\Jobs\AccountingTaxSync as Job;
|
||||
|
||||
/**
|
||||
* Synchronise TAX ids with our taxes.
|
||||
*/
|
||||
class AccountingTaxSync extends Command
|
||||
class TaxSync extends Command
|
||||
{
|
||||
private const provider = 'intuit';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'accounting:tax:sync'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Provider Name}'
|
||||
.' {user : User Email}';
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -37,15 +36,14 @@ class AccountingTaxSync extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$so = ProviderOauth::where('name',self::provider)->singleOrFail();
|
||||
if (! ($to=$so->token($uo)))
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
Job::dispatchSync($to);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -16,9 +16,8 @@ class ProviderTokenRefresh extends Command
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'provider:token:refresh'
|
||||
.' {siteid : Site ID}'
|
||||
.' {provider : Supplier Name}'
|
||||
.' {user : User Email}';
|
||||
.' {user? : User Email}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -34,15 +33,14 @@ class ProviderTokenRefresh extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$site = Site::findOrFail($this->argument('siteid'));
|
||||
Config::set('site',$site);
|
||||
$uo = User::where('email',$this->argument('user') ?: config('osb.admin'))->singleOrFail();
|
||||
|
||||
$so = ProviderOauth::where('name',$this->argument('provider'))->singleOrFail();
|
||||
$uo = User::where('email',$this->argument('user'))->singleOrFail();
|
||||
|
||||
if (($x=$so->tokens->where('user_id',$uo->id))->count() !== 1)
|
||||
abort(500,sprintf('Unknown Tokens for [%s]',$uo->email));
|
||||
|
||||
Job::dispatchSync($x->pop());
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
@ -19,4 +19,14 @@ class ForgotPasswordController extends Controller
|
||||
*/
|
||||
|
||||
use SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Display the form to request a password reset link.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showLinkRequestForm()
|
||||
{
|
||||
return view('adminlte::auth.passwords.email');
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
@ -26,4 +27,23 @@ class ResetPasswordController extends Controller
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = '/home';
|
||||
|
||||
/**
|
||||
* Display the password reset view for the given token.
|
||||
*
|
||||
* If no token is present, display the link request form.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function showResetForm(Request $request)
|
||||
{
|
||||
$token = $request->route()->parameter('token');
|
||||
|
||||
return view('adminlte::auth.passwords.reset')
|
||||
->with([
|
||||
'token' => $token,
|
||||
'email' => $request->email
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,38 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Http\Requests\UserEdit;
|
||||
use App\Models\{Supplier,User};
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Update user settings
|
||||
*
|
||||
* @param UserEdit $request
|
||||
* @param User $o
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function edit(UserEdit $request,User $o): RedirectResponse
|
||||
{
|
||||
foreach (Arr::except($request->validated(),['password']) as $field => $value)
|
||||
$o->{$field} = $value;
|
||||
|
||||
if ($x=$request->validated('password'))
|
||||
$o->password = Hash::make($x);
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('success',($o->isDirty() && $o->save()) ? 'User Updated' : 'No Changes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a supplier to a user's profile
|
||||
*
|
||||
|
39
app/Http/Requests/UserEdit.php
Normal file
39
app/Http/Requests/UserEdit.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
|
||||
class UserEdit extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Auth::id() === $this->route('o')->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'email'=>'required|email|min:5',
|
||||
'password'=>['nullable','confirmed',Password::min(8)],
|
||||
'firstname'=>'required|min:2',
|
||||
'lastname'=>'required|min:2',
|
||||
'address1'=>'required|min:8',
|
||||
'address2'=>'nullable|min:8',
|
||||
'city'=>'required|min:4',
|
||||
'state'=>'required|min:3|max:3',
|
||||
'postcode'=>'required|min:4|max:4',
|
||||
'country_id'=>'required|exists:countries,id'
|
||||
];
|
||||
}
|
||||
}
|
@ -3,9 +3,12 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Leenooks\Traits\ScopeActive;
|
||||
|
||||
class Country extends Model
|
||||
{
|
||||
use ScopeActive;
|
||||
|
||||
public $timestamps = FALSE;
|
||||
|
||||
/* RELATIONS */
|
||||
|
@ -29,6 +29,7 @@ class User extends Authenticatable implements IDs
|
||||
|
||||
protected $casts = [
|
||||
'last_access' => 'datetime:Y-m-d H:i:s',
|
||||
'passkey' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
|
||||
@ -15,17 +16,19 @@ class ResetPassword extends ResetPasswordNotification implements ShouldQueue
|
||||
* Build the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
* @return MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
public function toMail($notifiable): MailMessage
|
||||
{
|
||||
$site = Site::findOrFail($notifiable->site_id);
|
||||
|
||||
if (static::$toMailCallback) {
|
||||
return call_user_func(static::$toMailCallback, $notifiable, $this->token);
|
||||
}
|
||||
|
||||
return (new MailMessage)
|
||||
->markdown('email.user.passwordreset',[
|
||||
'site'=>$notifiable->site,
|
||||
'site'=>$site,
|
||||
'user'=>$notifiable,
|
||||
'reset_link'=>route('password.reset',$this->token,true),
|
||||
]);
|
||||
|
@ -4,11 +4,13 @@ namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Intuit\Traits\IntuitSocialite;
|
||||
use Leenooks\Traits\SingleOrFail;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
use SingleOrFail;
|
||||
use IntuitSocialite;
|
||||
|
||||
/**
|
||||
* Register any application services.
|
||||
@ -32,5 +34,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
Gate::define('reseller', function ($user) {
|
||||
return $user->isReseller();
|
||||
});
|
||||
|
||||
$this->bootIntuitSocialite();
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
use Leenooks\Http\Middleware\ActiveUser;
|
||||
|
||||
use App\Http\Middleware\{Role,SetSite};
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
@ -12,11 +15,12 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
$middleware->append([
|
||||
\App\Http\Middleware\SetSite::class,
|
||||
SetSite::class,
|
||||
]);
|
||||
|
||||
$middleware->alias([
|
||||
'role' => \App\Http\Middleware\Role::class,
|
||||
'activeuser' => ActiveUser::class,
|
||||
'role' => Role::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions) {
|
||||
|
@ -14,10 +14,11 @@
|
||||
"laravel/dreamscape": "^0.1.0",
|
||||
"laravel/framework": "^11.0",
|
||||
"laravel/intuit": "^0.1.7",
|
||||
"laravel/leenooks": "^11.0",
|
||||
"laravel/passport": "^12.0",
|
||||
"laravel/socialite": "^5.15",
|
||||
"laravel/ui": "^4.5",
|
||||
"leenooks/laravel": "^11.1",
|
||||
"leenooks/passkey": "^0.2",
|
||||
"paypal/paypal-checkout-sdk": "^1.0",
|
||||
"repat/laravel-job-models": "^0.9",
|
||||
"web-auth/webauthn-lib": "^4.4"
|
||||
@ -61,6 +62,10 @@
|
||||
"laravel-console-summary": {
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/leenooks/laravel-console-summary"
|
||||
},
|
||||
"passkey": {
|
||||
"type": "vcs",
|
||||
"url": "https://gitea.dege.au/laravel/passkey.git"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
585
composer.lock
generated
585
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -3,4 +3,5 @@
|
||||
return [
|
||||
'language_id' => 1,
|
||||
'invoice_text' => 'Thank you for using our Internet Services.',
|
||||
'admin' => env('APP_ADMIN'),
|
||||
];
|
258
public/passkey/passkey.js
vendored
Normal file
258
public/passkey/passkey.js
vendored
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Passkey Implementation
|
||||
*/
|
||||
let passkey_debug = false;
|
||||
|
||||
/**
|
||||
* Convert a ArrayBuffer to Base64
|
||||
* @param {ArrayBuffer} buffer
|
||||
* @returns {String}
|
||||
*/
|
||||
function arrayBufferToBase64(buffer) {
|
||||
let binary = '';
|
||||
let bytes = new Uint8Array(buffer);
|
||||
let len = bytes.byteLength;
|
||||
for (let i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode( bytes[ i ] );
|
||||
}
|
||||
return window.btoa(binary);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert RFC 1342-like base64 strings to array buffer
|
||||
* @param {mixed} obj
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function recursiveBase64StrToArrayBuffer(obj) {
|
||||
let prefix = '=?BINARY?B?';
|
||||
let suffix = '?=';
|
||||
if (typeof obj === 'object') {
|
||||
for (let key in obj) {
|
||||
if (typeof obj[key] === 'string') {
|
||||
let str = obj[key];
|
||||
if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {
|
||||
str = str.substring(prefix.length, str.length - suffix.length);
|
||||
|
||||
let binary_string = window.atob(str);
|
||||
let len = binary_string.length;
|
||||
let bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
obj[key] = bytes.buffer;
|
||||
}
|
||||
} else {
|
||||
recursiveBase64StrToArrayBuffer(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function passkey_check_browser()
|
||||
{
|
||||
// check browser support
|
||||
if ((! window.fetch) || (! navigator.credentials) || (! navigator.credentials.create))
|
||||
throw new Error('Browser not supported.');
|
||||
|
||||
/*
|
||||
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
|
||||
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.
|
||||
// `isConditionalMediationAvailable` means the feature detection is usable.
|
||||
if (window.PublicKeyCredential &&
|
||||
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
|
||||
PublicKeyCredential.isConditionalMediationAvailable) {
|
||||
// Check if user verifying platform authenticator is available.
|
||||
Promise.all([
|
||||
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
|
||||
PublicKeyCredential.isConditionalMediationAvailable(),
|
||||
]).then(results => {
|
||||
if (results.every(r => r === true)) {
|
||||
// Display "Create a new passkey" button
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Browser OK');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register/Create a passkey for a user
|
||||
*/
|
||||
async function passkey_register(csrf_token,icon_dom,icon,icon_shell_current,icon_shell_success,icon_shell_fail)
|
||||
{
|
||||
try {
|
||||
if (! passkey_check_browser())
|
||||
return;
|
||||
|
||||
// Change our icon so that it is obvious we are doing something
|
||||
icon_dom.find('i').removeClass(icon).addClass('spinner-grow spinner-grow-sm');
|
||||
|
||||
// Get our arguments
|
||||
var createArgs;
|
||||
$.ajax({
|
||||
url: '/passkey/register',
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
async: false,
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Get Register Success');
|
||||
|
||||
recursiveBase64StrToArrayBuffer(data);
|
||||
createArgs = data;
|
||||
},
|
||||
error: function(e,status,error) {
|
||||
throw new Error(status || 'Unknown error occurred');
|
||||
}
|
||||
});
|
||||
|
||||
// Create credentials
|
||||
try {
|
||||
const cred = await navigator.credentials.create(createArgs);
|
||||
|
||||
const authenticatorAttestationResponse = {
|
||||
id: cred.id,
|
||||
rawId: arrayBufferToBase64(cred.rawId),
|
||||
transports: cred.response.getTransports ? cred.response.getTransports() : null,
|
||||
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
|
||||
attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null,
|
||||
authenticatorAttachment: cred.authenticatorAttachment,
|
||||
_token: csrf_token,
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/passkey/check',
|
||||
type: 'POST',
|
||||
data: authenticatorAttestationResponse,
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Registration Success');
|
||||
|
||||
icon_dom.find('i').addClass(icon).removeClass('spinner-grow spinner-grow-sm');
|
||||
icon_dom.removeClass(icon_shell_current).addClass(icon_shell_success);
|
||||
},
|
||||
error: function(e,status,error) {
|
||||
throw new Error(status || 'Unknown error occurred');
|
||||
}
|
||||
});
|
||||
|
||||
} catch (status) {
|
||||
if (passkey_debug)
|
||||
console.log(status || 'Passkey: User Aborted Register');
|
||||
|
||||
// Restore the icon
|
||||
icon_dom.removeClass(icon_shell_current).addClass(icon_shell_fail).find('i').addClass(icon).removeClass('spinner-grow spinner-grow-sm');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
window.alert(err || 'An UNKNOWN error occurred?');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a passkey being presented
|
||||
*/
|
||||
async function passkey_check(csrf_token,redirect)
|
||||
{
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Check User Passkey');
|
||||
|
||||
try {
|
||||
if (! passkey_check_browser())
|
||||
return;
|
||||
|
||||
// Get our arguments
|
||||
var getArgs;
|
||||
$.ajax({
|
||||
url: '/passkey/get',
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
async: false,
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Get Args Success');
|
||||
|
||||
recursiveBase64StrToArrayBuffer(data);
|
||||
getArgs = data;
|
||||
},
|
||||
error: function(e,status,error) {
|
||||
throw new Error(status || 'Unknown error occurred');
|
||||
}
|
||||
});
|
||||
|
||||
// check credentials with hardware
|
||||
const cred = await navigator.credentials.get(getArgs);
|
||||
|
||||
// create object for transmission to server
|
||||
const authenticatorAttestationResponse = {
|
||||
id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
|
||||
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
|
||||
authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
|
||||
signature: cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null,
|
||||
userHandle: cred.response.userHandle ? arrayBufferToBase64(cred.response.userHandle) : null,
|
||||
_token: csrf_token
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/passkey/process',
|
||||
type: 'POST',
|
||||
data: authenticatorAttestationResponse,
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Process Success');
|
||||
|
||||
// Direct to the home page
|
||||
window.location.href = (redirect !== undefined) ? redirect : '/';
|
||||
},
|
||||
error: function(e,status,error) {
|
||||
throw new Error(status || 'Unknown error occurred');
|
||||
}
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
window.alert(err || 'An UNKNOWN error occurred?');
|
||||
}
|
||||
}
|
||||
|
||||
function passkey_create(object,csrf,icon,icon_class_current,icon_class_success,icon_class_nop)
|
||||
{
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Create Click');
|
||||
|
||||
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
|
||||
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.
|
||||
// `sConditionalMediationAvailable` means the feature detection is usable.
|
||||
if (window.PublicKeyCredential &&
|
||||
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
|
||||
PublicKeyCredential.isConditionalMediationAvailable) {
|
||||
// Check if user verifying platform authenticator is available.
|
||||
Promise.all([
|
||||
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
|
||||
PublicKeyCredential.isConditionalMediationAvailable(),
|
||||
]).then(results => {
|
||||
if (passkey_debug)
|
||||
console.log('Passkey: Browser Supported');
|
||||
|
||||
if (results.every(r => r === true)) {
|
||||
passkey_register(csrf,object,icon,icon_class_current,icon_class_success,icon_class_nop);
|
||||
} else {
|
||||
alert('It seems that passkey is NOT supported by your browse (B)');
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
alert('It seems that passkey is NOT supported by your browser (A)');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
126
resources/views/theme/backend/adminlte/user/settings.blade.php
Normal file
126
resources/views/theme/backend/adminlte/user/settings.blade.php
Normal file
@ -0,0 +1,126 @@
|
||||
@extends('adminlte::layouts.app')
|
||||
|
||||
@section('htmlheader_title')
|
||||
{{ ($o??$user)->role }} Settings
|
||||
@endsection
|
||||
@section('page_title')
|
||||
{{ ($o??$user)->name_full }}
|
||||
@endsection
|
||||
|
||||
@section('contentheader_title')
|
||||
{{ ($o??$user)->name_full }}
|
||||
@endsection
|
||||
@section('contentheader_description')
|
||||
{{ ($o??$user)->role }}
|
||||
@endsection
|
||||
|
||||
@use(App\Models\Country)
|
||||
<!-- ($o??$user)=User::class -->
|
||||
@section('main-content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">Update Settings</div>
|
||||
@session('success')<x-leenooks::success class="float-right">{{ $value }}</x-leenooks::success>@endsession
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url(request()->path(),[($o??$user)->id]) }}">
|
||||
@csrf
|
||||
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<x-leenooks::form.email id="email" name="email" icon="fa-at" label="Email" :value="($o??$user)->email ?? ''"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<x-leenooks::form.password id="password" name="password" icon="fa-lock" label="Password"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<x-leenooks::form.password id="password_confirm" name="password_confirmation" icon="fa-lock" label="Password Confirm"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col pb-3">
|
||||
<button type="reset" id="passkey" name="passkey" @class(['btn','btn-success'=>$x=($o??$user)->passkey,'btn-outline-secondary'=>! $x])><i class="fas fa-fw fa-key"></i> Passkey</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<x-leenooks::form.text name="firstname" icon="fa-headset" label="First Name" :value="($o??$user)->firstname ?? ''"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<x-leenooks::form.text name="lastname" icon="fa-signature" label="Last Name" :value="($o??$user)->lastname ?? ''"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<x-leenooks::form.text name="address1" icon="fa-map" label="Address" :value="($o??$user)->address1 ?? ''"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<x-leenooks::form.text name="address2" :value="($o??$user)->address2 ?? ''"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-4">
|
||||
<x-leenooks::form.text name="city" label="City" :value="($o??$user)->city ?? ''"/>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<x-leenooks::form.text name="state" label="State" :value="($o??$user)->state ?? ''"/>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<x-leenooks::form.text name="postcode" label="Post Code" :value="($o??$user)->postcode ?? ''"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<x-leenooks::form.select id="country" name="country_id" icon="fa-globe" label="Country" :value="($o??$user)->country_id ?? ''" :options="Country::select(['id','name'])->active()->get()->map(function($item) { $item->value = $item->name; return $item; })->toArray()"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pt-3">
|
||||
<div class="col">
|
||||
<button type="reset" name="cancel" class="btn btn-danger">Cancel</button>
|
||||
<button type="submit" name="submit" class="btn btn-success float-right">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
<!-- Passkeys -->
|
||||
<script type='text/javascript' src='{{ asset('/passkey/passkey.js') }}'></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#passkey').on('click',function(item) {
|
||||
return passkey_create($(this),'{{ csrf_token() }}','fa-key','{{ ($o??$user)->passkey ? 'btn-success' : 'btn-outline-secondary' }}','btn-success','{{ ($o??$user)->passkey ? 'btn-secondary' : 'btn-outline-secondary' }}');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@append
|
161
resources/views/vendor/adminlte/layouts/partials/mainheader.blade.php
vendored
Normal file
161
resources/views/vendor/adminlte/layouts/partials/mainheader.blade.php
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
<!-- Main Header -->
|
||||
<!-- Navbar -->
|
||||
<nav class="main-header navbar navbar-expand bg-white navbar-light border-bottom">
|
||||
<!-- Left navbar links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- SEARCH FORM -->
|
||||
<form class="form-inline ml-3">
|
||||
<div class="input-group input-group-sm">
|
||||
<input class="form-control form-control-navbar" name="q" type="search" placeholder="Search" aria-label="Search" autocomplete="off">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<span class="p-1 d-none" name="searching"><i class="fas fa-spinner fa-spin" style="margin-top: .33em; width: 1em; height: 1em;"></i></span>
|
||||
</div>
|
||||
<div id="search_results"></div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
@include('adminlte::layouts.partials.topmenu')
|
||||
|
||||
@if(Auth::check())
|
||||
<!-- Profile Settings -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" data-toggle="dropdown" href="#">
|
||||
<i class="fas fa-cog"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
|
||||
<span class="dropdown-item dropdown-header @if($user->switched) bg-danger @endif">
|
||||
@if($user->switched)
|
||||
SUDO (<small>{{ $user->name ?: 'User Name' }}</small>)
|
||||
@else
|
||||
{{ $user->name ?: 'User Name' }}
|
||||
@endif
|
||||
</span>
|
||||
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{{ url('u/settings') }}" class="dropdown-item">
|
||||
<i class="fas fa-user mr-2"></i> Settings
|
||||
</a>
|
||||
|
||||
<div class="dropdown-divider"></div>
|
||||
@if ($user->switched)
|
||||
<a href="{{ url('/admin/switch/stop') }}" class="dropdown-item">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> {{ trans('adminlte_lang::message.switchoff') }}
|
||||
</a>
|
||||
@else
|
||||
<a href="{{ url('logout') }}" class="dropdown-item">
|
||||
<i class="fas fa-sign-out-alt mr-2"></i> Log Out
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</li>
|
||||
@else
|
||||
<a href="{{ url()->current().'?login=1' }}" class="text-muted pr-2"><i class="fas fa-lock"></i></a>
|
||||
@endif
|
||||
|
||||
<!-- Control Side Bar -->
|
||||
@isset($controlsidebar)
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#">
|
||||
<i class="fas fa-th"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endisset
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@section('page-scripts')
|
||||
<style>
|
||||
/* Solid border */
|
||||
div.typeahead.dropdown-menu > .dropdown-header {
|
||||
color: #000000;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('input[name=q]').typeahead({
|
||||
autoSelect: false,
|
||||
scrollHeight: 10,
|
||||
theme: 'bootstrap4',
|
||||
delay: 500,
|
||||
minLength: 2,
|
||||
items: {{ isset($search_limit) ? $search_limit : 100 }},
|
||||
fitToElement: false,
|
||||
selectOnBlur: false,
|
||||
appendTo: "#search_results",
|
||||
source: function (query,process) {
|
||||
search('{{ url("search",['date'=>isset($ido) ? $ido->id : NULL]) }}',query,process);
|
||||
},
|
||||
|
||||
matcher: function () { return true; },
|
||||
|
||||
// Disable sorting and just return the items (items should by the ajax method)
|
||||
sorter: function(items) {
|
||||
return items;
|
||||
},
|
||||
|
||||
updater: function (item) {
|
||||
window.parent.location.href = item.value;
|
||||
},
|
||||
})
|
||||
.on('keyup keypress', function(event) {
|
||||
var key = event.keyCode || event.which;
|
||||
if (key === 13) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var c=0;
|
||||
var search = _.debounce(function(url,query,process,icon){
|
||||
$.ajax({
|
||||
url : url,
|
||||
type : 'GET',
|
||||
data : 'term=' + query,
|
||||
dataType : 'JSON',
|
||||
async : true,
|
||||
cache : false,
|
||||
beforeSend : function() {
|
||||
if (c++ == 0) {
|
||||
if (icon)
|
||||
$('i[name='+icon+']').addClass("fa-spin");
|
||||
else {
|
||||
$('span[name=searching]').removeClass("d-none");
|
||||
}
|
||||
}
|
||||
},
|
||||
success : function(data) {
|
||||
// if json is null, means no match, won't do again.
|
||||
if(data==null || (data.length===0)) return;
|
||||
|
||||
process(data);
|
||||
},
|
||||
complete : function() {
|
||||
if (--c == 0) {
|
||||
if (icon)
|
||||
$('i[name='+icon+']').removeClass("fa-spin");
|
||||
else {
|
||||
$('span[name=searching]').addClass("d-none");
|
||||
}
|
||||
}
|
||||
},
|
||||
statusCode: {
|
||||
401: function() {
|
||||
window.parent.location.href = '{{ route('login') }}';
|
||||
}
|
||||
}
|
||||
})
|
||||
}, 500);
|
||||
</script>
|
||||
@append
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Leenooks\Controllers\SwitchUserController;
|
||||
|
||||
use App\Http\Controllers\{AdminController,
|
||||
@ -8,7 +10,6 @@ use App\Http\Controllers\{AdminController,
|
||||
CheckoutController,
|
||||
HomeController,
|
||||
InvoiceController,
|
||||
MediaController,
|
||||
OrderController,
|
||||
PaypalController,
|
||||
ProductController,
|
||||
@ -16,7 +17,6 @@ use App\Http\Controllers\{AdminController,
|
||||
ServiceController,
|
||||
SupplierController,
|
||||
UserController,
|
||||
WelcomeController,
|
||||
Wholesale\ReportController};
|
||||
use App\Models\Supplier;
|
||||
|
||||
@ -44,6 +44,8 @@ Auth::routes([
|
||||
Route::get('logout',[LoginController::class,'logout'])
|
||||
->name('logout-get');
|
||||
|
||||
Route::redirect('passkey/loggedin','/home');
|
||||
|
||||
// Account linking to OPENID host
|
||||
Route::group([],function() {
|
||||
Route::get('auth/{socialProvider}',[SocialLoginController::class,'redirectToProvider']);
|
||||
@ -58,10 +60,6 @@ Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop'])
|
||||
->middleware('auth')
|
||||
->name('switch.stop');
|
||||
|
||||
// Generic Image Renderer - Render images that we dont have with a generic image
|
||||
Route::get('image/generic/{width}/{height}/{color}/{name?}',[MediaController::class,'image'])
|
||||
->name('image');
|
||||
|
||||
// Our Admin Routes - for wholesalers
|
||||
Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function() {
|
||||
// Site Setup
|
||||
@ -193,6 +191,9 @@ Route::group(['middleware'=>['auth'],'prefix'=>'u'],function() {
|
||||
Route::get('service/{o}/change/{status}',[ServiceController::class,'change'])
|
||||
->where('o','[0-9]+')
|
||||
->middleware('can:progress,o,status');
|
||||
|
||||
Route::view('settings','theme.backend.adminlte.user.settings');
|
||||
Route::post('settings/{o}',[UserController::class,'edit']);
|
||||
});
|
||||
|
||||
// Doorman Code Routes
|
||||
|
Loading…
Reference in New Issue
Block a user