Merge branch 'v5-develop' into billing_subscriptions

This commit is contained in:
David Bomba 2021-03-10 09:27:28 +11:00 committed by GitHub
commit b91fcf1b34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 66226 additions and 61669 deletions

View File

@ -1 +1 @@
5.1.14
5.1.17

View File

@ -35,6 +35,7 @@ class CompanyFactory
$company->custom_fields = (object) [];
$company->subdomain = '';
$company->enabled_modules = config('ninja.enabled_modules'); //32767;//8191; //4095
$company->default_password_timeout = 30;
return $company;
}

View File

@ -28,7 +28,7 @@ class UserFactory
$user->failed_logins = 0;
$user->signature = '';
$user->theme_id = 0;
return $user;
}
}

View File

@ -30,7 +30,7 @@ class TwoFactorController extends BaseController
$google2fa = new Google2FA();
$secret = $google2fa->generateSecretKey();
$qr_code = $google2fa->getQRCodeGoogleUrl(
$qr_code = $google2fa->getQRCodeUrl(
config('ninja.app_name'),
$user->email,
$secret

View File

@ -37,10 +37,17 @@ class PasswordProtection
'errors' => new stdClass,
];
$timeout = auth()->user()->company()->default_password_timeout;
if($timeout == 0)
$timeout = null;
else
$timeout = now()->addMinutes($timeout);
if (Cache::get(auth()->user()->hashed_id.'_logged_in')) {
Cache::pull(auth()->user()->hashed_id.'_logged_in');
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), now()->addMinutes(30));
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout);
return $next($request);
@ -62,12 +69,12 @@ class PasswordProtection
//If OAuth and user also has a password set - check both
if ($existing_user = MultiDB::hasUser($query) && auth()->user()->has_password && Hash::check(auth()->user()->password, $request->header('X-API-PASSWORD'))) {
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), now()->addMinutes(30));
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout);
return $next($request);
}
elseif($existing_user = MultiDB::hasUser($query) && !auth()->user()->has_password){
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), now()->addMinutes(30));
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout);
return $next($request);
}
}
@ -77,7 +84,7 @@ class PasswordProtection
}elseif ($request->header('X-API-PASSWORD') && Hash::check($request->header('X-API-PASSWORD'), auth()->user()->password)) {
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), now()->addMinutes(30));
Cache::add(auth()->user()->hashed_id.'_logged_in', Str::random(64), $timeout);
return $next($request);

View File

@ -51,8 +51,6 @@ class TokenAuth
*/
$user->setCompany($company_token->company);
config(['ninja.company_id' => $company_token->company->id]);
app('queue')->createPayloadUsing(function () use ($company_token) {
return ['db' => $company_token->company->db];
});
@ -71,6 +69,7 @@ class TokenAuth
auth()->login($user, false);
event(new UserLoggedIn($user, $company_token->company, Ninja::eventVars()));
} else {
$error = [
'message' => 'Invalid token',

View File

@ -23,6 +23,6 @@ class ReconfirmUserRequest extends Request
*/
public function authorize() : bool
{
return auth()->user()->Admin();
return auth()->user()->isAdmin();
}
}

View File

@ -86,6 +86,7 @@ class Company extends BaseModel
'session_timeout',
'oauth_password_required',
'invoice_task_datelog',
'default_password_timeout',
];
protected $hidden = [

View File

@ -36,7 +36,7 @@ class CompanyPresenter extends EntityPresenter
$settings = $this->entity->settings;
}
if(strlen($settings->company_logo) >= 1 && strpos($settings->company_logo, 'http'))
if(strlen($settings->company_logo) >= 1 && (strpos($settings->company_logo, 'http') !== false))
return $settings->company_logo;
else if(strlen($settings->company_logo) >= 1)
return url('') . $settings->company_logo;

View File

@ -154,6 +154,7 @@ class CompanyTransformer extends EntityTransformer
'expense_amount_is_pretax' =>(bool)true, //@deprecate 1-2-2021
'oauth_password_required' => (bool)$company->oauth_password_required,
'session_timeout' => (int)$company->session_timeout,
'default_password_timeout' => (int) $company->default_password_timeout,
];
}

View File

@ -13,7 +13,7 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.1.14',
'app_version' => '5.1.17',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),

View File

@ -0,0 +1,42 @@
<?php
use App\Models\Company;
use App\Models\Language;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddRussianLang extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$russian = ['id' => 29, 'name' => 'Russian (Russia)', 'locale' => 'ru_RU'];
Language::unguard();
Language::create($russian);
Schema::table('companies', function (Blueprint $table) {
$table->integer('default_password_timeout')->default(30);
});
Company::whereNotNull('id')->update(['default_password_timeout' => 30]);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -30,7 +30,7 @@ const RESOURCES = {
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "3e722fd57a6db80ee119f0e2c230ccff",
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
"/": "23224b5e03519aaa87594403d54412cf",
"main.dart.js": "53da6fecadfcc13e83a501a510a76f81",
"main.dart.js": "b47a232664791053223138fe8bf8322c",
"version.json": "b7c8971e1ab5b627fd2a4317c52b843e",
"favicon.png": "dca91c54388f52eded692718d5a98b8b"
};

123390
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

View File

@ -0,0 +1,13 @@
<?php
$lang = [
'client_dashboard' => 'Message to be displayed on clients dashboard',
'client_currency' => 'The client currency.',
'client_language' => 'The client language.',
'client_payment_terms' => 'The client payment terms.',
'client_paid_invoice' => 'Message to be displayed on a clients paid invoice screen',
'client_unpaid_invoice' => 'Message to be displayed on a clients unpaid invoice screen',
'client_unapproved_quote' => 'Message to be displayed on a clients unapproved quote screen',
];
return $lang;

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '« Previous',
'next' => 'Next »',
];

View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Passwords must be at least six characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that e-mail address.",
];

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'The :attribute must be a valid email address.',
'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'numeric' => 'The :attribute must be greater than :value.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'string' => 'The :attribute must be greater than :value characters.',
'array' => 'The :attribute must have more than :value items.',
],
'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'string' => 'The :attribute must be greater than or equal :value characters.',
'array' => 'The :attribute must have :value items or more.',
],
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'ipv4' => 'The :attribute must be a valid IPv4 address.',
'ipv6' => 'The :attribute must be a valid IPv6 address.',
'json' => 'The :attribute must be a valid JSON string.',
'lt' => [
'numeric' => 'The :attribute must be less than :value.',
'file' => 'The :attribute must be less than :value kilobytes.',
'string' => 'The :attribute must be less than :value characters.',
'array' => 'The :attribute must have less than :value items.',
],
'lte' => [
'numeric' => 'The :attribute must be less than or equal :value.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'string' => 'The :attribute must be less than or equal :value characters.',
'array' => 'The :attribute must not have more than :value items.',
],
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute format is invalid.',
'numeric' => 'The :attribute must be a number.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'url' => 'The :attribute format is invalid.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

View File

@ -11,73 +11,70 @@
<p><img src="{{ $company->present()->logo() }}"></p>
@if(isset($company) && $company->clients->count() >=1)
<p><b>Clients Imported:</b> {{ $company->clients->count() }} </p>
<p><b>{{ ctrans('texts.clients') }}:</b> {{ $company->clients->count() }} </p>
@endif
@if(isset($company) && count($company->products) >=1)
<p><b>Products Imported:</b> {{ count($company->products) }} </p>
<p><b>{{ ctrans('texts.products') }}:</b> {{ count($company->products) }} </p>
@endif
@if(isset($company) && count($company->invoices) >=1)
<p><b>Invoices Imported:</b> {{ count($company->invoices) }} </p>
<p>To test your PDF generation is working correctly, click <a href="{{$company->invoices->first()->invitations->first()->getLink() }}">here</a>. We've also attempted to attach the PDF to this email.
<p><b>{{ ctrans('texts.invoices') }}:</b> {{ count($company->invoices) }} </p>
@endif
@if(isset($company) && count($company->payments) >=1)
<p><b>Payments Imported:</b> {{ count($company->payments) }} </p>
<p><b>{{ ctrans('texts.payments') }}:</b> {{ count($company->payments) }} </p>
@endif
@if(isset($company) && count($company->recurring_invoices) >=1)
<p><b>Recurring Invoices Imported:</b> {{ count($company->recurring_invoices) }} </p>
<p><b>{{ ctrans('texts.recurring_invoices') }}:</b> {{ count($company->recurring_invoices) }} </p>
@endif
@if(isset($company) && count($company->quotes) >=1)
<p><b>Quotes Imported:</b> {{ count($company->quotes) }} </p>
<p><b>{{ ctrans('texts.quotes') }}:</b> {{ count($company->quotes) }} </p>
@endif
@if(isset($company) && count($company->credits) >=1)
<p><b>Credits Imported:</b> {{ count($company->credits) }} </p>
<p><b>{{ ctrans('texts.credits') }}:</b> {{ count($company->credits) }} </p>
@endif
@if(isset($company) && count($company->projects) >=1)
<p><b>Projects Imported:</b> {{ count($company->projects) }} </p>
<p><b>{{ ctrans('texts.projects') }}:</b> {{ count($company->projects) }} </p>
@endif
@if(isset($company) && count($company->tasks) >=1)
<p><b>Tasks Imported:</b> {{ count($company->tasks) }} </p>
<p><b>{{ ctrans('texts.tasks') }}:</b> {{ count($company->tasks) }} </p>
@endif
@if(isset($company) && count($company->vendors) >=1)
<p><b>Vendors Imported:</b> {{ count($company->vendors) }} </p>
<p><b>{{ ctrans('texts.vendors') }}:</b> {{ count($company->vendors) }} </p>
@endif
@if(isset($company) && count($company->expenses) >=1)
<p><b>Expenses Imported:</b> {{ count($company->expenses) }} </p>
<p><b>{{ ctrans('texts.expenses') }}:</b> {{ count($company->expenses) }} </p>
@endif
@if(isset($company) && count($company->company_gateways) >=1)
<p><b>Gateways Imported:</b> {{ count($company->company_gateways) }} </p>
<p><b>{{ ctrans('texts.gateways') }}:</b> {{ count($company->company_gateways) }} </p>
@endif
@if(isset($company) && count($company->client_gateway_tokens) >=1)
<p><b>Client Gateway Tokens Imported:</b> {{ count($company->client_gateway_tokens) }} </p>
<p><b>{{ ctrans('texts.tokens') }}:</b> {{ count($company->client_gateway_tokens) }} </p>
@endif
@if(isset($company) && count($company->tax_rates) >=1)
<p><b>Tax Rates Imported:</b> {{ count($company->tax_rates) }} </p>
<p><b>{{ ctrans('texts.tax_rates') }}:</b> {{ count($company->tax_rates) }} </p>
@endif
@if(isset($company) && count($company->documents) >=1)
<p><b>Documents Imported:</b> {{ count($company->documents) }} </p>
<p><b>{{ ctrans('texts.documents') }}:</b> {{ count($company->documents) }} </p>
@endif
<p><b>Data Quality:</b></p>
<p> {!! $check_data !!} </p>
@if(!empty($errors) )
<p>The following import errors occurred:</p>
<p>{{ ctrans('texts.errors') }}:</p>
<table>
<thead>
<tr>