Merge pull request #7547 from turbo124/v5-stable

v5.3.100
This commit is contained in:
David Bomba 2022-06-13 08:18:28 +10:00 committed by GitHub
commit b4b823e481
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 81399 additions and 80656 deletions

View File

@ -61,3 +61,11 @@ SENTRY_LARAVEL_DSN=https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co
GOOGLE_PLAY_PACKAGE_NAME=
APPSTORE_PASSWORD=
MICROSOFT_CLIENT_ID=
MICROSOFT_CLIENT_SECRET=
MICROSOFT_REDIRECT_URI=
APPLE_CLIENT_ID=
APPLE_CLIENT_SECRET=
APPLE_REDIRECT_URI=

View File

@ -1 +1 @@
5.3.99
5.3.100

View File

@ -330,8 +330,7 @@ class LoginController extends BaseController
$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'));
}
});
@ -359,16 +358,126 @@ class LoginController extends BaseController
*/
public function oauthApiLogin()
{
$message = 'Provider not supported';
if (request()->input('provider') == 'google') {
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()
->json(['message' => 'Provider not supported'], 400)
->json(['message' => $message], 400)
->header('X-App-Version', config('ninja.app_version'))
->header('X-Api-Version', config('ninja.minimum_client_version'));
}
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
{
@ -392,8 +501,7 @@ class LoginController extends BaseController
if($cu->count() == 0)
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) {

View File

@ -39,6 +39,12 @@ class RedirectIfAuthenticated
// return redirect()->route('dashboard.index');
// }
break;
case 'vendor':
if (Auth::guard($guard)->check()) {
//TODO create routes for vendor
// return redirect()->route('vendor.dashboard');
}
break;
default:
Auth::logout();
// if (Auth::guard($guard)->check()) {

View File

@ -23,7 +23,7 @@ class ShowInvoiceRequest extends Request
*/
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;
}
}

View File

@ -27,9 +27,8 @@ class CreatePaymentMethodRequest extends FormRequest
$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 false;
}

View File

@ -29,6 +29,8 @@ class OAuth
const SOCIAL_LINKEDIN = 4;
const SOCIAL_TWITTER = 5;
const SOCIAL_BITBUCKET = 6;
const SOCIAL_MICROSOFT = 7;
const SOCIAL_APPLE = 8;
/**
* @param Socialite $user
@ -74,6 +76,10 @@ class OAuth
return 'twitter';
case SOCIAL_BITBUCKET:
return 'bitbucket';
case SOCIAL_MICROSOFT:
return 'microsoft';
case SOCIAL_APPLE:
return 'apple';
}
}
@ -92,6 +98,10 @@ class OAuth
return SOCIAL_TWITTER;
case '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;
return $this;
default:
return null;
break;

View File

@ -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){
@ -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'))) {
foreach ($pms as $pm) {
if ($pm['gateway_type_id'] == GatewayType::DIRECT_DEBIT) {

View File

@ -346,7 +346,7 @@ class Invoice extends BaseModel
return '<h5><span class="badge badge-danger">'.ctrans('texts.overdue').'</span></h5>';
break;
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;
case self::STATUS_REVERSED:
return '<h5><span class="badge badge-info">'.ctrans('texts.reversed').'</span></h5>';

View File

@ -212,7 +212,7 @@ class Payment extends BaseModel
return '<h6><span class="badge badge-secondary">'.ctrans('texts.payment_status_1').'</span></h6>';
break;
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;
case self::STATUS_FAILED:
return '<h6><span class="badge badge-danger">'.ctrans('texts.payment_status_3').'</span></h6>';

View File

@ -593,7 +593,12 @@ class EventServiceProvider extends ServiceProvider
],
VendorWasUpdated::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',
],
];

View File

@ -121,4 +121,12 @@ class RouteServiceProvider extends ServiceProvider
->namespace($this->namespace)
->group(base_path('routes/shop.php'));
}
protected function mapVendorsApiRoutes()
{
Route::prefix('')
->middleware('vendor')
->namespace($this->namespace)
->group(base_path('routes/vendor.php'));
}
}

View File

@ -77,6 +77,8 @@
"sentry/sentry-laravel": "^2",
"setasign/fpdf": "^1.8",
"setasign/fpdi": "^2.3",
"socialiteproviders/apple": "^5.2",
"socialiteproviders/microsoft": "^4.1",
"square/square": "13.0.0.20210721",
"stripe/stripe-php": "^7.50",
"symfony/http-client": "^5.2",

949
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,10 @@ return [
'driver' => 'session',
'provider' => 'contacts',
],
'vendor' => [
'driver' => 'session',
'provider' => 'vendors',
],
],
/*
@ -85,6 +89,11 @@ return [
'driver' => 'eloquent',
'model' => App\Models\ClientContact::class,
],
'vendors' => [
'driver' => 'eloquent',
'model' => App\Models\VendorContact::class,
],
// 'users' => [
// 'driver' => 'database',
@ -120,6 +129,11 @@ return [
'table' => 'password_resets',
'expire' => 60,
],
'vendors' => [
'provider' => 'vendors',
'table' => 'password_resets',
'expire' => 60,
],
],
/*

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.3.99',
'app_tag' => '5.3.99',
'app_version' => '5.3.100',
'app_tag' => '5.3.100',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -80,4 +80,14 @@ return [
'postmark' => [
'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')
],
];

View File

@ -5,9 +5,9 @@ const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"/": "f4932ba24bfa72c97f7578b8951891c2",
"main.dart.js": "68a04477f6ce39dcf894f583120e1c46",
"version.json": "3afb81924daf4f751571755436069115",
"/": "94862dc60be2e82c49106de806115c42",
"main.dart.js": "bb75daec9d3cdf8374011435e63376d2",
"version.json": "d72bd323e3b8e22ce5acdc247f4e6f62",
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
"flutter.js": "0816e65a103ba8ba51b174eeeeb2cb67",
"favicon.ico": "51636d3a390451561744c42188ccd628",

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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
View 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!
|
*/