mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
b4b823e481
@ -61,3 +61,11 @@ SENTRY_LARAVEL_DSN=https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co
|
|||||||
|
|
||||||
GOOGLE_PLAY_PACKAGE_NAME=
|
GOOGLE_PLAY_PACKAGE_NAME=
|
||||||
APPSTORE_PASSWORD=
|
APPSTORE_PASSWORD=
|
||||||
|
|
||||||
|
MICROSOFT_CLIENT_ID=
|
||||||
|
MICROSOFT_CLIENT_SECRET=
|
||||||
|
MICROSOFT_REDIRECT_URI=
|
||||||
|
|
||||||
|
APPLE_CLIENT_ID=
|
||||||
|
APPLE_CLIENT_SECRET=
|
||||||
|
APPLE_REDIRECT_URI=
|
||||||
|
@ -1 +1 @@
|
|||||||
5.3.99
|
5.3.100
|
@ -92,7 +92,7 @@ class LoginController extends BaseController
|
|||||||
* @return void
|
* @return void
|
||||||
* deprecated .1 API ONLY we don't need to set any session variables
|
* deprecated .1 API ONLY we don't need to set any session variables
|
||||||
*/
|
*/
|
||||||
public function authenticated(Request $request, User $user) : void
|
public function authenticated(Request $request, User $user): void
|
||||||
{
|
{
|
||||||
//$this->setCurrentCompanyId($user->companies()->first()->account->default_company_id);
|
//$this->setCurrentCompanyId($user->companies()->first()->account->default_company_id);
|
||||||
}
|
}
|
||||||
@ -168,9 +168,9 @@ class LoginController extends BaseController
|
|||||||
$this->fireLockoutEvent($request);
|
$this->fireLockoutEvent($request);
|
||||||
|
|
||||||
return response()
|
return response()
|
||||||
->json(['message' => 'Too many login attempts, you are being throttled'], 401)
|
->json(['message' => 'Too many login attempts, you are being throttled'], 401)
|
||||||
->header('X-App-Version', config('ninja.app_version'))
|
->header('X-App-Version', config('ninja.app_version'))
|
||||||
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->attemptLogin($request)) {
|
if ($this->attemptLogin($request)) {
|
||||||
@ -250,7 +250,7 @@ class LoginController extends BaseController
|
|||||||
// $truth->setCompanyToken(CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $user->account->default_company->id)->first());
|
// $truth->setCompanyToken(CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $user->account->default_company->id)->first());
|
||||||
|
|
||||||
/*On the hosted platform, only owners can login for free/pro accounts*/
|
/*On the hosted platform, only owners can login for free/pro accounts*/
|
||||||
if(Ninja::isHosted() && !$cu->first()->is_owner && !$user->account->isEnterpriseClient())
|
if (Ninja::isHosted() && !$cu->first()->is_owner && !$user->account->isEnterpriseClient())
|
||||||
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
||||||
|
|
||||||
event(new UserLoggedIn($user, $user->account->default_company, Ninja::eventVars($user->id)));
|
event(new UserLoggedIn($user, $user->account->default_company, Ninja::eventVars($user->id)));
|
||||||
@ -267,9 +267,9 @@ class LoginController extends BaseController
|
|||||||
$this->incrementLoginAttempts($request);
|
$this->incrementLoginAttempts($request);
|
||||||
|
|
||||||
return response()
|
return response()
|
||||||
->json(['message' => ctrans('texts.invalid_credentials')], 401)
|
->json(['message' => ctrans('texts.invalid_credentials')], 401)
|
||||||
->header('X-App-Version', config('ninja.app_version'))
|
->header('X-App-Version', config('ninja.app_version'))
|
||||||
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,29 +317,28 @@ class LoginController extends BaseController
|
|||||||
{
|
{
|
||||||
$truth = app()->make(TruthSource::class);
|
$truth = app()->make(TruthSource::class);
|
||||||
|
|
||||||
if($truth->getCompanyToken())
|
if ($truth->getCompanyToken())
|
||||||
$company_token = $truth->getCompanyToken();
|
$company_token = $truth->getCompanyToken();
|
||||||
else
|
else
|
||||||
$company_token = CompanyToken::where('token', $request->header('X-API-TOKEN'))->first();
|
$company_token = CompanyToken::where('token', $request->header('X-API-TOKEN'))->first();
|
||||||
|
|
||||||
$cu = CompanyUser::query()
|
$cu = CompanyUser::query()
|
||||||
->where('user_id', $company_token->user_id);
|
->where('user_id', $company_token->user_id);
|
||||||
|
|
||||||
if($cu->count() == 0)
|
if ($cu->count() == 0)
|
||||||
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
||||||
|
|
||||||
$cu->first()->account->companies->each(function ($company) use($cu, $request){
|
$cu->first()->account->companies->each(function ($company) use ($cu, $request) {
|
||||||
|
|
||||||
if($company->tokens()->where('is_system', true)->count() == 0)
|
if ($company->tokens()->where('is_system', true)->count() == 0) {
|
||||||
{
|
|
||||||
CreateCompanyToken::dispatchNow($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
|
CreateCompanyToken::dispatchNow($company, $cu->first()->user, $request->server('HTTP_USER_AGENT'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if($request->has('current_company') && $request->input('current_company') == 'true')
|
if ($request->has('current_company') && $request->input('current_company') == 'true')
|
||||||
$cu->where("company_id", $company_token->company_id);
|
$cu->where("company_id", $company_token->company_id);
|
||||||
|
|
||||||
if(Ninja::isHosted() && !$cu->first()->is_owner && !$cu->first()->user->account->isEnterpriseClient())
|
if (Ninja::isHosted() && !$cu->first()->is_owner && !$cu->first()->user->account->isEnterpriseClient())
|
||||||
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
||||||
|
|
||||||
return $this->refreshResponse($cu);
|
return $this->refreshResponse($cu);
|
||||||
@ -359,24 +358,134 @@ class LoginController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function oauthApiLogin()
|
public function oauthApiLogin()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$message = 'Provider not supported';
|
||||||
if (request()->input('provider') == 'google') {
|
if (request()->input('provider') == 'google') {
|
||||||
return $this->handleGoogleOauth();
|
return $this->handleGoogleOauth();
|
||||||
|
} elseif (request()->input('provider') == 'microsoft') {
|
||||||
|
if (request()->has('token')) {
|
||||||
|
return $this->handleSocialiteLogin('microsoft', request()->get('token'));
|
||||||
|
} else {
|
||||||
|
$message = 'Bearer token missing for the microsoft login';
|
||||||
|
}
|
||||||
|
} elseif (request()->input('provider') == 'apple') {
|
||||||
|
if (request()->has('token')) {
|
||||||
|
return $this->handleSocialiteLogin('apple', request()->get('token'));
|
||||||
|
} else {
|
||||||
|
$message = 'Token is missing for the apple login';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()
|
return response()
|
||||||
->json(['message' => 'Provider not supported'], 400)
|
->json(['message' => $message], 400)
|
||||||
->header('X-App-Version', config('ninja.app_version'))
|
->header('X-App-Version', config('ninja.app_version'))
|
||||||
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function hydrateCompanyUser() :Builder
|
private function getSocialiteUser(string $provider, string $token)
|
||||||
|
{
|
||||||
|
return Socialite::driver($provider)->userFromToken($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleSocialiteLogin($provider, $token)
|
||||||
|
{
|
||||||
|
$user = $this->getSocialiteUser($provider, $token);
|
||||||
|
if ($user) {
|
||||||
|
return $this->loginOrCreateFromSocialite($user, $provider);
|
||||||
|
}
|
||||||
|
return response()
|
||||||
|
->json(['message' => ctrans('texts.invalid_credentials')], 401)
|
||||||
|
->header('X-App-Version', config('ninja.app_version'))
|
||||||
|
->header('X-Api-Version', config('ninja.minimum_client_version'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function loginOrCreateFromSocialite($user, $provider)
|
||||||
|
{
|
||||||
|
$query = [
|
||||||
|
'oauth_user_id' => $user->id,
|
||||||
|
'oauth_provider_id' => $provider,
|
||||||
|
];
|
||||||
|
if ($existing_user = MultiDB::hasUser($query)) {
|
||||||
|
|
||||||
|
if (!$existing_user->account)
|
||||||
|
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
|
||||||
|
|
||||||
|
Auth::login($existing_user, true);
|
||||||
|
|
||||||
|
$cu = $this->hydrateCompanyUser();
|
||||||
|
|
||||||
|
if ($cu->count() == 0)
|
||||||
|
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
||||||
|
|
||||||
|
if (Ninja::isHosted() && !$cu->first()->is_owner && !$existing_user->account->isEnterpriseClient())
|
||||||
|
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
||||||
|
|
||||||
|
return $this->timeConstrainedResponse($cu);
|
||||||
|
|
||||||
|
}
|
||||||
|
//If this is a result user/email combo - lets add their OAuth details details
|
||||||
|
if ($existing_login_user = MultiDB::hasUser(['email' => $user->email])) {
|
||||||
|
if (!$existing_login_user->account)
|
||||||
|
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
|
||||||
|
|
||||||
|
Auth::login($existing_login_user, true);
|
||||||
|
|
||||||
|
auth()->user()->update([
|
||||||
|
'oauth_user_id' => $user->id,
|
||||||
|
'oauth_provider_id' => $provider,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cu = $this->hydrateCompanyUser();
|
||||||
|
|
||||||
|
if ($cu->count() == 0)
|
||||||
|
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
||||||
|
|
||||||
|
if (Ninja::isHosted() && !$cu->first()->is_owner && !$existing_login_user->account->isEnterpriseClient())
|
||||||
|
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
||||||
|
|
||||||
|
return $this->timeConstrainedResponse($cu);
|
||||||
|
}
|
||||||
|
$name = OAuth::splitName($user->name);
|
||||||
|
|
||||||
|
$new_account = [
|
||||||
|
'first_name' => $name[0],
|
||||||
|
'last_name' => $name[1],
|
||||||
|
'password' => '',
|
||||||
|
'email' => $user->email,
|
||||||
|
'oauth_user_id' => $user->id,
|
||||||
|
'oauth_provider_id' => $provider,
|
||||||
|
];
|
||||||
|
|
||||||
|
MultiDB::setDefaultDatabase();
|
||||||
|
|
||||||
|
$account = CreateAccount::dispatchNow($new_account, request()->getClientIp());
|
||||||
|
|
||||||
|
Auth::login($account->default_company->owner(), true);
|
||||||
|
auth()->user()->email_verified_at = now();
|
||||||
|
auth()->user()->save();
|
||||||
|
|
||||||
|
$cu = $this->hydrateCompanyUser();
|
||||||
|
|
||||||
|
if ($cu->count() == 0)
|
||||||
|
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
||||||
|
|
||||||
|
if (Ninja::isHosted() && !$cu->first()->is_owner && !auth()->user()->account->isEnterpriseClient())
|
||||||
|
return response()->json(['message' => 'Pro / Free accounts only the owner can log in. Please upgrade'], 403);
|
||||||
|
|
||||||
|
return $this->timeConstrainedResponse($cu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function hydrateCompanyUser(): Builder
|
||||||
{
|
{
|
||||||
|
|
||||||
$cu = CompanyUser::query()->where('user_id', auth()->user()->id);
|
$cu = CompanyUser::query()->where('user_id', auth()->user()->id);
|
||||||
|
|
||||||
if(CompanyUser::query()->where('user_id', auth()->user()->id)->where('company_id', auth()->user()->account->default_company_id)->exists())
|
if (CompanyUser::query()->where('user_id', auth()->user()->id)->where('company_id', auth()->user()->account->default_company_id)->exists())
|
||||||
$set_company = auth()->user()->account->default_company;
|
$set_company = auth()->user()->account->default_company;
|
||||||
else{
|
else {
|
||||||
$set_company = $cu->first()->company;
|
$set_company = $cu->first()->company;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,14 +501,13 @@ class LoginController extends BaseController
|
|||||||
if($cu->count() == 0)
|
if($cu->count() == 0)
|
||||||
return $cu;
|
return $cu;
|
||||||
|
|
||||||
if(auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count())
|
if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) {
|
||||||
{
|
|
||||||
|
|
||||||
auth()->user()->companies->each(function($company){
|
auth()->user()->companies->each(function ($company) {
|
||||||
|
|
||||||
if(!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()){
|
if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()) {
|
||||||
|
|
||||||
CreateCompanyToken::dispatchNow($company, auth()->user(), "Google_O_Auth");
|
CreateCompanyToken::dispatchNow($company, auth()->user(), "Google_O_Auth");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +602,7 @@ class LoginController extends BaseController
|
|||||||
// $cu = CompanyUser::query()
|
// $cu = CompanyUser::query()
|
||||||
// ->where('user_id', auth()->user()->id);
|
// ->where('user_id', auth()->user()->id);
|
||||||
|
|
||||||
if($cu->count() == 0)
|
if ($cu->count() == 0)
|
||||||
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
|
||||||
|
|
||||||
if(Ninja::isHosted() && !$cu->first()->is_owner && !$existing_login_user->account->isEnterpriseClient())
|
if(Ninja::isHosted() && !$cu->first()->is_owner && !$existing_login_user->account->isEnterpriseClient())
|
||||||
|
@ -20,32 +20,38 @@ class RedirectIfAuthenticated
|
|||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Closure $next
|
* @param Closure $next
|
||||||
* @param string|null $guard
|
* @param string|null $guard
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next, $guard = null)
|
public function handle($request, Closure $next, $guard = null)
|
||||||
{
|
{
|
||||||
switch ($guard) {
|
switch ($guard) {
|
||||||
case 'contact':
|
case 'contact':
|
||||||
if (Auth::guard($guard)->check()) {
|
if (Auth::guard($guard)->check()) {
|
||||||
return redirect()->route('client.dashboard');
|
return redirect()->route('client.dashboard');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
Auth::logout();
|
Auth::logout();
|
||||||
// if (Auth::guard($guard)->check()) {
|
// if (Auth::guard($guard)->check()) {
|
||||||
// return redirect()->route('dashboard.index');
|
// return redirect()->route('dashboard.index');
|
||||||
// }
|
// }
|
||||||
break;
|
break;
|
||||||
default:
|
case 'vendor':
|
||||||
Auth::logout();
|
if (Auth::guard($guard)->check()) {
|
||||||
// if (Auth::guard($guard)->check()) {
|
//TODO create routes for vendor
|
||||||
// return redirect('/');
|
// return redirect()->route('vendor.dashboard');
|
||||||
// }
|
}
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
Auth::logout();
|
||||||
|
// if (Auth::guard($guard)->check()) {
|
||||||
|
// return redirect('/');
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ class ShowInvoiceRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
return auth()->guard('contact')->user()->client_id === (int)$this->invoice->client_id
|
return (int)auth()->guard('contact')->user()->client_id === (int)$this->invoice->client_id
|
||||||
&& auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES;
|
&& auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,8 @@ class CreatePaymentMethodRequest extends FormRequest
|
|||||||
$available_methods[] = $method['gateway_type_id'];
|
$available_methods[] = $method['gateway_type_id'];
|
||||||
});
|
});
|
||||||
|
|
||||||
if (in_array($this->query('method'), $available_methods)) {
|
if (in_array($this->query('method'), $available_methods))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ class OAuth
|
|||||||
const SOCIAL_LINKEDIN = 4;
|
const SOCIAL_LINKEDIN = 4;
|
||||||
const SOCIAL_TWITTER = 5;
|
const SOCIAL_TWITTER = 5;
|
||||||
const SOCIAL_BITBUCKET = 6;
|
const SOCIAL_BITBUCKET = 6;
|
||||||
|
const SOCIAL_MICROSOFT = 7;
|
||||||
|
const SOCIAL_APPLE = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Socialite $user
|
* @param Socialite $user
|
||||||
@ -38,8 +40,8 @@ class OAuth
|
|||||||
{
|
{
|
||||||
/** 1. Ensure user arrives on the correct provider **/
|
/** 1. Ensure user arrives on the correct provider **/
|
||||||
$query = [
|
$query = [
|
||||||
'oauth_user_id' =>$socialite_user->getId(),
|
'oauth_user_id' => $socialite_user->getId(),
|
||||||
'oauth_provider_id'=>$provider,
|
'oauth_provider_id' => $provider,
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($user = MultiDB::hasUser($query)) {
|
if ($user = MultiDB::hasUser($query)) {
|
||||||
@ -54,12 +56,12 @@ class OAuth
|
|||||||
{
|
{
|
||||||
$name = trim($name);
|
$name = trim($name);
|
||||||
$last_name = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name);
|
$last_name = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name);
|
||||||
$first_name = trim(preg_replace('#'.preg_quote($last_name, '/').'#', '', $name));
|
$first_name = trim(preg_replace('#' . preg_quote($last_name, '/') . '#', '', $name));
|
||||||
|
|
||||||
return [$first_name, $last_name];
|
return [$first_name, $last_name];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function providerToString(int $social_provider) : string
|
public static function providerToString(int $social_provider): string
|
||||||
{
|
{
|
||||||
switch ($social_provider) {
|
switch ($social_provider) {
|
||||||
case SOCIAL_GOOGLE:
|
case SOCIAL_GOOGLE:
|
||||||
@ -74,10 +76,14 @@ class OAuth
|
|||||||
return 'twitter';
|
return 'twitter';
|
||||||
case SOCIAL_BITBUCKET:
|
case SOCIAL_BITBUCKET:
|
||||||
return 'bitbucket';
|
return 'bitbucket';
|
||||||
|
case SOCIAL_MICROSOFT:
|
||||||
|
return 'microsoft';
|
||||||
|
case SOCIAL_APPLE:
|
||||||
|
return 'apple';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function providerToInt(string $social_provider) : int
|
public static function providerToInt(string $social_provider): int
|
||||||
{
|
{
|
||||||
switch ($social_provider) {
|
switch ($social_provider) {
|
||||||
case 'google':
|
case 'google':
|
||||||
@ -92,6 +98,10 @@ class OAuth
|
|||||||
return SOCIAL_TWITTER;
|
return SOCIAL_TWITTER;
|
||||||
case 'bitbucket':
|
case 'bitbucket':
|
||||||
return SOCIAL_BITBUCKET;
|
return SOCIAL_BITBUCKET;
|
||||||
|
case 'microsoft':
|
||||||
|
return SOCIAL_MICROSOFT;
|
||||||
|
case 'apple':
|
||||||
|
return SOCIAL_APPLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +113,6 @@ class OAuth
|
|||||||
$this->provider_id = self::SOCIAL_GOOGLE;
|
$this->provider_id = self::SOCIAL_GOOGLE;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
break;
|
break;
|
||||||
|
@ -486,7 +486,7 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->currency()->code == 'EUR' && in_array(GatewayType::BANK_TRANSFER, array_column($pms, 'gateway_type_id'))){
|
if($this->currency()->code == 'EUR' && (in_array(GatewayType::BANK_TRANSFER, array_column($pms, 'gateway_type_id')) || in_array(GatewayType::SEPA, array_column($pms, 'gateway_type_id'))) ){
|
||||||
|
|
||||||
foreach($pms as $pm){
|
foreach($pms as $pm){
|
||||||
|
|
||||||
@ -501,18 +501,6 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ($this->currency()->code == 'EUR' && in_array(GatewayType::SEPA, array_column($pms, 'gateway_type_id'))) {
|
|
||||||
// foreach ($pms as $pm) {
|
|
||||||
// if ($pm['gateway_type_id'] == GatewayType::SEPA) {
|
|
||||||
// $cg = CompanyGateway::find($pm['company_gateway_id']);
|
|
||||||
|
|
||||||
// if ($cg && $cg->fees_and_limits->{GatewayType::SEPA}->is_enabled) {
|
|
||||||
// return $cg;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if ($this->country && $this->country->iso_3166_3 == 'GBR' && in_array(GatewayType::DIRECT_DEBIT, array_column($pms, 'gateway_type_id'))) {
|
if ($this->country && $this->country->iso_3166_3 == 'GBR' && in_array(GatewayType::DIRECT_DEBIT, array_column($pms, 'gateway_type_id'))) {
|
||||||
foreach ($pms as $pm) {
|
foreach ($pms as $pm) {
|
||||||
if ($pm['gateway_type_id'] == GatewayType::DIRECT_DEBIT) {
|
if ($pm['gateway_type_id'] == GatewayType::DIRECT_DEBIT) {
|
||||||
|
@ -346,7 +346,7 @@ class Invoice extends BaseModel
|
|||||||
return '<h5><span class="badge badge-danger">'.ctrans('texts.overdue').'</span></h5>';
|
return '<h5><span class="badge badge-danger">'.ctrans('texts.overdue').'</span></h5>';
|
||||||
break;
|
break;
|
||||||
case self::STATUS_UNPAID:
|
case self::STATUS_UNPAID:
|
||||||
return '<h5><span class="badge badge-warning">'.ctrans('texts.unpaid').'</span></h5>';
|
return '<h5><span class="badge badge-warning text-white">'.ctrans('texts.unpaid').'</span></h5>';
|
||||||
break;
|
break;
|
||||||
case self::STATUS_REVERSED:
|
case self::STATUS_REVERSED:
|
||||||
return '<h5><span class="badge badge-info">'.ctrans('texts.reversed').'</span></h5>';
|
return '<h5><span class="badge badge-info">'.ctrans('texts.reversed').'</span></h5>';
|
||||||
|
@ -212,7 +212,7 @@ class Payment extends BaseModel
|
|||||||
return '<h6><span class="badge badge-secondary">'.ctrans('texts.payment_status_1').'</span></h6>';
|
return '<h6><span class="badge badge-secondary">'.ctrans('texts.payment_status_1').'</span></h6>';
|
||||||
break;
|
break;
|
||||||
case self::STATUS_CANCELLED:
|
case self::STATUS_CANCELLED:
|
||||||
return '<h6><span class="badge badge-warning">'.ctrans('texts.payment_status_2').'</span></h6>';
|
return '<h6><span class="badge badge-warning text-white">'.ctrans('texts.payment_status_2').'</span></h6>';
|
||||||
break;
|
break;
|
||||||
case self::STATUS_FAILED:
|
case self::STATUS_FAILED:
|
||||||
return '<h6><span class="badge badge-danger">'.ctrans('texts.payment_status_3').'</span></h6>';
|
return '<h6><span class="badge badge-danger">'.ctrans('texts.payment_status_3').'</span></h6>';
|
||||||
|
@ -264,9 +264,9 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $listen = [
|
protected $listen = [
|
||||||
AccountCreated::class =>[
|
AccountCreated::class => [
|
||||||
],
|
],
|
||||||
MessageSending::class =>[
|
MessageSending::class => [
|
||||||
],
|
],
|
||||||
MessageSent::class => [
|
MessageSent::class => [
|
||||||
MailSentListener::class,
|
MailSentListener::class,
|
||||||
@ -312,35 +312,35 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
PaymentWasVoided::class => [
|
PaymentWasVoided::class => [
|
||||||
PaymentVoidedActivity::class,
|
PaymentVoidedActivity::class,
|
||||||
],
|
],
|
||||||
PaymentWasRestored::class =>[
|
PaymentWasRestored::class => [
|
||||||
PaymentRestoredActivity::class,
|
PaymentRestoredActivity::class,
|
||||||
],
|
],
|
||||||
// Clients
|
// Clients
|
||||||
ClientWasCreated::class =>[
|
ClientWasCreated::class => [
|
||||||
CreatedClientActivity::class,
|
CreatedClientActivity::class,
|
||||||
],
|
],
|
||||||
ClientWasArchived::class =>[
|
ClientWasArchived::class => [
|
||||||
ArchivedClientActivity::class,
|
ArchivedClientActivity::class,
|
||||||
],
|
],
|
||||||
ClientWasUpdated::class =>[
|
ClientWasUpdated::class => [
|
||||||
ClientUpdatedActivity::class,
|
ClientUpdatedActivity::class,
|
||||||
],
|
],
|
||||||
ClientWasDeleted::class =>[
|
ClientWasDeleted::class => [
|
||||||
DeleteClientActivity::class,
|
DeleteClientActivity::class,
|
||||||
],
|
],
|
||||||
ClientWasRestored::class =>[
|
ClientWasRestored::class => [
|
||||||
RestoreClientActivity::class,
|
RestoreClientActivity::class,
|
||||||
],
|
],
|
||||||
// Documents
|
// Documents
|
||||||
DocumentWasCreated::class =>[
|
DocumentWasCreated::class => [
|
||||||
],
|
],
|
||||||
DocumentWasArchived::class =>[
|
DocumentWasArchived::class => [
|
||||||
],
|
],
|
||||||
DocumentWasUpdated::class =>[
|
DocumentWasUpdated::class => [
|
||||||
],
|
],
|
||||||
DocumentWasDeleted::class =>[
|
DocumentWasDeleted::class => [
|
||||||
],
|
],
|
||||||
DocumentWasRestored::class =>[
|
DocumentWasRestored::class => [
|
||||||
],
|
],
|
||||||
CreditWasCreated::class => [
|
CreditWasCreated::class => [
|
||||||
CreatedCreditActivity::class,
|
CreatedCreditActivity::class,
|
||||||
@ -404,11 +404,11 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
InvoiceWasCreated::class => [
|
InvoiceWasCreated::class => [
|
||||||
CreateInvoiceActivity::class,
|
CreateInvoiceActivity::class,
|
||||||
InvoiceCreatedNotification::class,
|
InvoiceCreatedNotification::class,
|
||||||
// CreateInvoicePdf::class,
|
// CreateInvoicePdf::class,
|
||||||
],
|
],
|
||||||
InvoiceWasPaid::class => [
|
InvoiceWasPaid::class => [
|
||||||
InvoicePaidActivity::class,
|
InvoicePaidActivity::class,
|
||||||
CreateInvoicePdf::class,
|
CreateInvoicePdf::class,
|
||||||
],
|
],
|
||||||
InvoiceWasViewed::class => [
|
InvoiceWasViewed::class => [
|
||||||
InvoiceViewedActivity::class,
|
InvoiceViewedActivity::class,
|
||||||
@ -593,7 +593,12 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
],
|
],
|
||||||
VendorWasUpdated::class => [
|
VendorWasUpdated::class => [
|
||||||
VendorUpdatedActivity::class,
|
VendorUpdatedActivity::class,
|
||||||
]
|
],
|
||||||
|
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
|
||||||
|
// ... Manager won't register drivers that are not added to this listener.
|
||||||
|
\SocialiteProviders\Apple\AppleExtendSocialite::class . '@handle',
|
||||||
|
\SocialiteProviders\Microsoft\MicrosoftExtendSocialite::class . '@handle',
|
||||||
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -121,4 +121,12 @@ class RouteServiceProvider extends ServiceProvider
|
|||||||
->namespace($this->namespace)
|
->namespace($this->namespace)
|
||||||
->group(base_path('routes/shop.php'));
|
->group(base_path('routes/shop.php'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function mapVendorsApiRoutes()
|
||||||
|
{
|
||||||
|
Route::prefix('')
|
||||||
|
->middleware('vendor')
|
||||||
|
->namespace($this->namespace)
|
||||||
|
->group(base_path('routes/vendor.php'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,8 @@
|
|||||||
"sentry/sentry-laravel": "^2",
|
"sentry/sentry-laravel": "^2",
|
||||||
"setasign/fpdf": "^1.8",
|
"setasign/fpdf": "^1.8",
|
||||||
"setasign/fpdi": "^2.3",
|
"setasign/fpdi": "^2.3",
|
||||||
|
"socialiteproviders/apple": "^5.2",
|
||||||
|
"socialiteproviders/microsoft": "^4.1",
|
||||||
"square/square": "13.0.0.20210721",
|
"square/square": "13.0.0.20210721",
|
||||||
"stripe/stripe-php": "^7.50",
|
"stripe/stripe-php": "^7.50",
|
||||||
"symfony/http-client": "^5.2",
|
"symfony/http-client": "^5.2",
|
||||||
|
949
composer.lock
generated
949
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,10 @@ return [
|
|||||||
'driver' => 'session',
|
'driver' => 'session',
|
||||||
'provider' => 'contacts',
|
'provider' => 'contacts',
|
||||||
],
|
],
|
||||||
|
'vendor' => [
|
||||||
|
'driver' => 'session',
|
||||||
|
'provider' => 'vendors',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -85,6 +89,11 @@ return [
|
|||||||
'driver' => 'eloquent',
|
'driver' => 'eloquent',
|
||||||
'model' => App\Models\ClientContact::class,
|
'model' => App\Models\ClientContact::class,
|
||||||
],
|
],
|
||||||
|
'vendors' => [
|
||||||
|
'driver' => 'eloquent',
|
||||||
|
'model' => App\Models\VendorContact::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
// 'users' => [
|
// 'users' => [
|
||||||
// 'driver' => 'database',
|
// 'driver' => 'database',
|
||||||
@ -120,6 +129,11 @@ return [
|
|||||||
'table' => 'password_resets',
|
'table' => 'password_resets',
|
||||||
'expire' => 60,
|
'expire' => 60,
|
||||||
],
|
],
|
||||||
|
'vendors' => [
|
||||||
|
'provider' => 'vendors',
|
||||||
|
'table' => 'password_resets',
|
||||||
|
'expire' => 60,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -14,8 +14,8 @@ return [
|
|||||||
'require_https' => env('REQUIRE_HTTPS', true),
|
'require_https' => env('REQUIRE_HTTPS', true),
|
||||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||||
'app_version' => '5.3.99',
|
'app_version' => '5.3.100',
|
||||||
'app_tag' => '5.3.99',
|
'app_tag' => '5.3.100',
|
||||||
'minimum_client_version' => '5.0.16',
|
'minimum_client_version' => '5.0.16',
|
||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', ''),
|
'api_secret' => env('API_SECRET', ''),
|
||||||
|
@ -80,4 +80,14 @@ return [
|
|||||||
'postmark' => [
|
'postmark' => [
|
||||||
'token' => env('POSTMARK_SECRET'),
|
'token' => env('POSTMARK_SECRET'),
|
||||||
],
|
],
|
||||||
|
'microsoft' => [
|
||||||
|
'client_id' => env('MICROSOFT_CLIENT_ID'),
|
||||||
|
'client_secret' => env('MICROSOFT_CLIENT_SECRET'),
|
||||||
|
'redirect' => env('MICROSOFT_REDIRECT_URI')
|
||||||
|
],
|
||||||
|
'apple' => [
|
||||||
|
'client_id' => env('APPLE_CLIENT_ID'),
|
||||||
|
'client_secret' => env('APPLE_CLIENT_SECRET'),
|
||||||
|
'redirect' => env('APPLE_REDIRECT_URI')
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
6
public/flutter_service_worker.js
vendored
6
public/flutter_service_worker.js
vendored
@ -5,9 +5,9 @@ const CACHE_NAME = 'flutter-app-cache';
|
|||||||
const RESOURCES = {
|
const RESOURCES = {
|
||||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||||
"/": "f4932ba24bfa72c97f7578b8951891c2",
|
"/": "94862dc60be2e82c49106de806115c42",
|
||||||
"main.dart.js": "68a04477f6ce39dcf894f583120e1c46",
|
"main.dart.js": "bb75daec9d3cdf8374011435e63376d2",
|
||||||
"version.json": "3afb81924daf4f751571755436069115",
|
"version.json": "d72bd323e3b8e22ce5acdc247f4e6f62",
|
||||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||||
"flutter.js": "0816e65a103ba8ba51b174eeeeb2cb67",
|
"flutter.js": "0816e65a103ba8ba51b174eeeeb2cb67",
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
|
53251
public/main.dart.js
vendored
53251
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
53409
public/main.foss.dart.js
vendored
53409
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
53523
public/main.next.dart.js
vendored
53523
public/main.next.dart.js
vendored
File diff suppressed because one or more lines are too long
499
public/main.profile.dart.js
vendored
499
public/main.profile.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"app_name":"invoiceninja_flutter","version":"5.0.84","build_number":"84","package_name":"invoiceninja_flutter"}
|
{"app_name":"invoiceninja_flutter","version":"5.0.85","build_number":"85","package_name":"invoiceninja_flutter"}
|
13
routes/vendor.php
Normal file
13
routes/vendor.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| API Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register API routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| is assigned the "api" middleware group. Enjoy building your API!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user