Merge pull request #4950 from turbo124/v5-develop

Update dependencies
This commit is contained in:
David Bomba 2021-02-20 23:13:53 +11:00 committed by GitHub
commit 1b19b3d0a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 785 additions and 562 deletions

View File

@ -1 +1 @@
5.1.6
5.1.7

View File

@ -0,0 +1,63 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Controllers;
use PragmaRX\Google2FA\Google2FA;
use Crypt;
class TwoFactorController extends BaseController
{
public function setupTwoFactor()
{
$user = auth()->user();
if ($user->google_2fa_secret)
return response()->json(['message' => '2FA already enabled'], 400);
elseif(! $user->phone)
return response()->json(['message' => ctrans('texts.set_phone_for_two_factor')], 400);
elseif(! $user->confirmed)
return response()->json(['message' => 'Please confirm your account first'], 400);
$google2fa = new Google2FA();
$secret = $google2fa->generateSecretKey();
$qr_code = $google2fa->getQRCodeGoogleUrl(
config('ninja.app_name')
$user->email,
$secret
);
$data = [
'secret' => $secret,
'qrCode' => $qrCode,
];
return response()->json(['data' => $data], 200);
}
public function enableTwoFactor()
{
$user = auth()->user();
$secret = request()->input('secret');
$oneTimePassword = request()->input('one_time_password');
if (! $secret || ! \Google2FA::verifyKey($secret, $oneTimePassword)) {
return response()->json('message' > ctrans('texts.invalid_one_time_password'));
} elseif (! $user->google_2fa_secret && $user->phone && $user->confirmed) {
$user->google_2fa_secret = encrypt($secret);
$user->save();
}
return response()->json(['message' => ctrans('texts.enabled_two_factor')], 200);
}
}

View File

@ -23,11 +23,16 @@ use App\Http\Requests\User\CreateUserRequest;
use App\Http\Requests\User\DestroyUserRequest;
use App\Http\Requests\User\DetachCompanyUserRequest;
use App\Http\Requests\User\EditUserRequest;
use App\Http\Requests\User\ReconfirmUserRequest;
use App\Http\Requests\User\ShowUserRequest;
use App\Http\Requests\User\StoreUserRequest;
use App\Http\Requests\User\UpdateUserRequest;
use App\Jobs\Company\CreateCompanyToken;
use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Jobs\User\UserEmailChanged;
use App\Mail\Admin\VerifyUserObject;
use App\Models\CompanyUser;
use App\Models\User;
use App\Repositories\UserRepository;
@ -378,11 +383,12 @@ class UserController extends BaseController
$new_user = $this->user_repo->save($request->all(), $user);
$new_user = $user->fresh();
nlog($old_user);
if ($old_user_email != $new_email)
/* When changing email address we store the former email in case we need to rollback */
if ($old_user_email != $new_email) {
$user->last_confirmed_email_address = $old_user_email;
$user->save();
UserEmailChanged::dispatch($new_user, json_decode($old_user), auth()->user()->company());
}
if(
@ -684,4 +690,70 @@ class UserController extends BaseController
return response()->json(['message' => ctrans('texts.user_detached')], 200);
}
/**
* Detach an existing user to a company.
*
* @OA\Post(
* path="/api/v1/users/{user}/reconfirm",
* operationId="reconfirmUser",
* tags={"users"},
* summary="Reconfirm an existing user to a company",
* description="Reconfirm an existing user from a company",
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="user",
* in="path",
* description="The user hashed_id",
* example="FD767dfd7",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Success response",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
* @param ReconfirmUserRequest $request
* @param User $user
* @return \Illuminate\Http\JsonResponse
*/
public function reconfirm(ReconfirmUserRequest $request, User $user)
{
$user->confirmation_code = $this->createDbHash($user->company()->db);
$user->save();
$nmo = new NinjaMailerObject;
$nmo->mailable = new NinjaMailer((new VerifyUserObject($user, $user->company()))->build());
$nmo->company = $user->company();
$nmo->to_user = $user;
$nmo->settings = $user->company->settings;
NinjaMailerJob::dispatch($nmo);
return response()->json(['message' => ctrans('texts.confirmation_resent')], 200);
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\User;
use App\Http\Requests\Request;
use App\Models\User;
class ReconfirmUserRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->Admin();
}
}

View File

@ -54,6 +54,7 @@ use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
class CSVImport implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, CleanLineItems;
public $invoice;

View File

@ -50,21 +50,5 @@ class BouncedEmail extends Mailable
->text()
->subject($subject);
//todo
/*
//todo determine WHO is notified!! In this instance the _user_ is notified
Mail::to($invitation->user->email)
//->cc('')
//->bcc('')
->queue(new BouncedEmail($invitation));
return $this->from('x@gmail.com') //todo
->subject(ctrans('texts.confirmation_subject'))
->markdown('email.auth.verify', ['user' => $this->user])
->text('email.auth.verify_text');
*/
}
}

View File

@ -1,32 +0,0 @@
<?php
namespace App\Mail\Invoices;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class InvoiceWasPaid extends Mailable
{
// use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from(config('mail.from.address'), config('mail.from.name'))->view('email.invoices.paid');
}
}

View File

@ -1,32 +0,0 @@
<?php
namespace App\Mail\Quote;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class QuoteWasApproved extends Mailable
{
// use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from(config('mail.from.address'), config('mail.from.name'))->view('email.quotes.approved');
}
}

View File

@ -27,6 +27,8 @@ class TemplateEmail extends Mailable
private $contact;
private $company;
public function __construct($build_email, ClientContact $contact)
{
$this->build_email = $build_email;
@ -34,6 +36,8 @@ class TemplateEmail extends Mailable
$this->contact = $contact;
$this->client = $contact->client;
$this->company = $contact->company;
}
public function build()
@ -44,15 +48,13 @@ class TemplateEmail extends Mailable
$company = $this->client->company;
$this->from(config('mail.from.address'), config('mail.from.name'));
$this->from(config('mail.from.address'), $this->company->present()->name());
if (strlen($settings->reply_to_email) > 1) {
if (strlen($settings->reply_to_email) > 1)
$this->replyTo($settings->reply_to_email, $settings->reply_to_email);
}
if (strlen($settings->bcc_email) > 1) {
if (strlen($settings->bcc_email) > 1)
$this->bcc($settings->bcc_email, $settings->bcc_email);
}
$this->subject($this->build_email->getSubject())
->text('email.template.plain', [

View File

@ -58,6 +58,7 @@ class UserTransformer extends EntityTransformer
'custom_value3' => $user->custom_value3 ?: '',
'custom_value4' => $user->custom_value4 ?: '',
'oauth_provider_id' => (string) $user->oauth_provider_id,
'last_confirmed_email_address' => (string) $user->last_confirmed_email_address ?: '',
];
}

View File

@ -49,7 +49,7 @@ class Helpers
*
* @return null|string
*/
public function formatCustomFieldValue($custom_fields = null, $field, $value, Client $client = null): ?string
public function formatCustomFieldValue($custom_fields, $field, $value, Client $client = null): ?string
{
$custom_field = '';
@ -84,7 +84,7 @@ class Helpers
*
* @return string
*/
public function makeCustomField($custom_fields = null, $field): string
public function makeCustomField($custom_fields, $field): string
{
if ($custom_fields && property_exists($custom_fields, $field)) {
$custom_field = $custom_fields->{$field};

View File

@ -217,13 +217,17 @@ trait CompanySettingsSaver
switch ($key) {
case 'int':
case 'integer':
return ctype_digit(strval(abs($value)));
if(is_string($value))
return false;
return is_int($value) || ctype_digit(strval(abs($value)));
case 'real':
case 'float':
case 'double':
return is_float($value) || is_numeric(strval($value));
case 'string':
return method_exists($value, '__toString') || is_null($value) || is_string($value);
// return method_exists($value, '__toString') || is_null($value) || is_string($value);
return is_null($value) || is_string($value);
case 'bool':
case 'boolean':
return is_bool($value) || (int) filter_var($value, FILTER_VALIDATE_BOOLEAN);

View File

@ -30,8 +30,8 @@
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"asgrim/ofxparser": "^1.2",
"authorizenet/authorizenet": "^2.0",
"bacon/bacon-qr-code": "^2.0",
"beganovich/snappdf": "^1.0",
"checkout/checkout-sdk-php": "^1.0",
"cleverit/ubl_invoice": "^1.3",
@ -42,7 +42,7 @@
"fzaninotto/faker": "^1.4",
"google/apiclient": "^2.7",
"guzzlehttp/guzzle": "^7.0.1",
"hashids/hashids": "^3.0",
"hashids/hashids": "^4.0",
"intervention/image": "^2.5",
"laracasts/presenter": "^0.2.1",
"laravel/framework": "^8.0",
@ -59,11 +59,12 @@
"maennchen/zipstream-php": "^1.2",
"nwidart/laravel-modules": "^8.0",
"omnipay/paypal": "^3.0",
"pragmarx/google2fa": "^8.0",
"predis/predis": "^1.1",
"sentry/sentry-laravel": "^2",
"stripe/stripe-php": "^7.50",
"turbo124/beacon": "^1",
"turbo124/laravel-gmail": "^5.0",
"dacastro4/laravel-gmail": "dev-master",
"webpatser/laravel-countries": "dev-master#75992ad",
"wildbit/swiftmailer-postmark": "^3.3"
},
@ -89,7 +90,6 @@
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/Libraries/OFX.php"
]
},
"autoload-dev": {

1024
composer.lock generated

File diff suppressed because it is too large Load Diff

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.6',
'app_version' => '5.1.7',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class EmailLastConfirmedEmailAddressUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function(Blueprint $table){
$table->string('last_confirmed_email_address')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -146,6 +146,9 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
Route::resource('tokens', 'TokenController')->middleware('password_protected'); // name = (tokens. index / create / show / update / destroy / edit
Route::post('tokens/bulk', 'TokenController@bulk')->name('tokens.bulk')->middleware('password_protected');
Route::get('settings/enable_two_factor', 'TwoFactorController@setupTwoFactor');
Route::post('settings/enable_two_factor', 'TwoFactorController@enableTwoFactor');
Route::resource('vendors', 'VendorController'); // name = (vendors. index / create / show / update / destroy / edit
Route::post('vendors/bulk', 'VendorController@bulk')->name('vendors.bulk');
Route::put('vendors/{vendor}/upload', 'VendorController@upload');
@ -156,6 +159,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
Route::post('users/{user}/attach_to_company', 'UserController@attach')->middleware('password_protected');
Route::delete('users/{user}/detach_from_company', 'UserController@detach')->middleware('password_protected');
Route::post('users/bulk', 'UserController@bulk')->name('users.bulk')->middleware('password_protected');
Route::post('/user/{user}/reconfirm', 'UserController@reconfirm')->middleware('password_protected');
Route::resource('webhooks', 'WebhookController');
Route::post('webhooks/bulk', 'WebhookController@bulk')->name('webhooks.bulk');