1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 05:02:36 +01:00

Fixes for client currency id (#3092)

* Fix for CORs error where file download were being prevented by headers

* Fixes for CORs and File downloads

* give contextual error messages for invalid route actions

* Clean up LoginController for OAuth Testing

* Quote Actions

* Invoice and Quote Actions

* Fix for client currency
This commit is contained in:
David Bomba 2019-11-25 20:38:55 +11:00 committed by GitHub
parent 808c6deb88
commit 0908893180
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 113 additions and 158 deletions

View File

@ -393,43 +393,4 @@ class LoginController extends BaseController
}
/**
* Received the returning object from the provider
* which we will use to resolve the user, we return the response in JSON format
*
* @return json
public function handleProviderCallbackApiUser(string $provider)
{
$socialite_user = Socialite::driver($provider)->stateless()->user();
if($user = OAuth::handleAuth($socialite_user, $provider))
{
return $this->itemResponse($user);
}
else if(MultiDB::checkUserEmailExists($socialite_user->getEmail()))
{
return $this->errorResponse(['message'=>'User exists in system, but not with this authentication method'], 400);
}
else {
//todo
$name = OAuth::splitName($socialite_user->getName());
$new_account = [
'first_name' => $name[0],
'last_name' => $name[1],
'password' => '',
'email' => $socialite_user->getEmail(),
];
$account = CreateAccount::dispatchNow($new_account);
return $this->itemResponse($account->default_company->owner());
}
}
*/
}

View File

@ -137,9 +137,6 @@ class BaseController extends Controller
protected function listResponse($query)
{
\DB::connection()->enableQueryLog();
$queries = \DB::getQueryLog();
\Log::error(print_r($queries,1));
$this->buildManager();

View File

@ -604,7 +604,7 @@ class InvoiceController extends BaseController
switch ($action) {
case 'clone_to_invoice':
$invoice = CloneInvoiceFactory::create($invoice, auth()->user()->id);
$invoice = CloneInvoiceFactory::create($invocie, auth()->user()->id);
return $this->itemResponse($invoice);
break;
case 'clone_to_quote':
@ -629,20 +629,22 @@ class InvoiceController extends BaseController
return $this->itemResponse($invoice);
break;
case 'download':
# code...
return response()->download(public_path($invoice->pdf_file_path()));
break;
case 'archive':
# code...
$this->invoice_repo->archive($invoice);
return $this->listResponse($invoice);
break;
case 'delete':
# code...
$this->invoice_repo->delete($invoice);
return $this->listResponse($invoice);
break;
case 'email':
//dispatch email to queue
return response()->json(['message'=>'email sent'],200);
break;
default:
# code...
return response()->json(['message' => "The requested action `{$action}` is not available."],400);
break;
}
}

View File

@ -512,7 +512,7 @@ class QuoteController extends BaseController
$quotes->each(function ($quote, $key) use($action){
if(auth()->user()->can('edit', $quote))
$this->product_repo->{$action}($quote);
$this->quote_repo->{$action}($quote);
});
@ -611,18 +611,22 @@ class QuoteController extends BaseController
case 'mark_paid':
# code...
break;
case 'download':
return response()->download(public_path($quote->pdf_file_path()));
break;
case 'archive':
# code...
$this->invoice_repo->archive($quote);
return $this->listResponse($quote);
break;
case 'delete':
# code...
$this->quote_repo->delete($quote);
return $this->listResponse($quote);
break;
case 'email':
//dispatch email to queue
return response()->json(['message'=>'email sent'],200);
break;
default:
# code...
return response()->json(['message' => "The requested action `{$action}` is not available."],400);
break;
}
}

View File

@ -4,7 +4,7 @@ namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class Cors
{
@ -26,11 +26,22 @@ class Cors
}
/* Work around for file downloads where the response cannot contain have headers set */
// if($request instanceOf BinaryFileResponse)
// return $next($request);
// else
// return $next($request)
// ->header('Access-Control-Allow-Origin', '*')
// ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
// ->header('Access-Control-Allow-Headers', 'X-API-SECRET,X-API-TOKEN,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'X-API-SECRET,X-API-TOKEN,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
$response = $next($request);
$response->headers->set('Access-Control-Allow-Origin' , '*');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
$response->headers->set('Access-Control-Allow-Headers', 'X-API-SECRET,X-API-TOKEN,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
return $response;
}

View File

@ -24,7 +24,8 @@ class CreateAccountRequest extends Request
*/
public function authorize()
{
return ! auth()->user();
return true;
//return ! auth()->user();
}
/**

View File

@ -67,7 +67,7 @@ class Account extends BaseModel
*/
public function payment()
{
return $this->belongsTo(Payment::class);
return $this->belongsTo(Payment::class)->withTrashed();
}
public function companies()

View File

@ -194,8 +194,6 @@ class Client extends BaseModel
return $item->id == $this->getSetting('currency_id');
})->first();
//return Currency::find($this->getSetting('currency_id'));
//return $this->belongsTo(Currency::class);
}
/**

View File

@ -114,7 +114,7 @@ class ClientContact extends Authenticatable implements HasLocalePreference
public function client()
{
return $this->belongsTo(Client::class);
return $this->belongsTo(Client::class)->withTrashed();
}
public function primary_contact()
@ -129,7 +129,7 @@ class ClientContact extends Authenticatable implements HasLocalePreference
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function sendPasswordResetNotification($token)

View File

@ -29,7 +29,7 @@ class ClientGatewayToken extends BaseModel
public function client()
{
return $this->hasOne(Client::class);
return $this->hasOne(Client::class)->withTrashed();
}
public function gateway()
@ -49,7 +49,7 @@ class ClientGatewayToken extends BaseModel
public function user()
{
return $this->hasOne(User::class);
return $this->hasOne(User::class)->withTrashed();
}
}

View File

@ -33,6 +33,7 @@ use App\Models\User;
use App\Utils\Ninja;
use App\Utils\Traits\CompanySettingsSaver;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\ThrottlesEmail;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
use Laracasts\Presenter\PresentableTrait;
@ -42,7 +43,8 @@ class Company extends BaseModel
use PresentableTrait;
use MakesHash;
use CompanySettingsSaver;
use ThrottlesEmail;
protected $presenter = 'App\Models\Presenters\CompanyPresenter';
protected $fillable = [
@ -109,7 +111,7 @@ class Company extends BaseModel
*/
public function clients()
{
return $this->hasMany(Client::class);
return $this->hasMany(Client::class)->withTrashed();
}
/**
@ -130,7 +132,7 @@ class Company extends BaseModel
*/
public function invoices()
{
return $this->hasMany(Invoice::class);
return $this->hasMany(Invoice::class)->withTrashed();
}
/**
@ -261,47 +263,4 @@ class Company extends BaseModel
}
private function isThrottled()
{
if (Ninja::isSelfHost()) {
return false;
}
$key = $this->id;
// http://stackoverflow.com/questions/1375501/how-do-i-throttle-my-sites-api-users
$day = 60 * 60 * 24;
$day_limit = $account->getDailyEmailLimit();
$day_throttle = Cache::get("email_day_throttle:{$key}", null);
$last_api_request = Cache::get("last_email_request:{$key}", 0);
$last_api_diff = time() - $last_api_request;
if (is_null($day_throttle)) {
$new_day_throttle = 0;
} else {
$new_day_throttle = $day_throttle - $last_api_diff;
$new_day_throttle = $new_day_throttle < 0 ? 0 : $new_day_throttle;
$new_day_throttle += $day / $day_limit;
$day_hits_remaining = floor(($day - $new_day_throttle) * $day_limit / $day);
$day_hits_remaining = $day_hits_remaining >= 0 ? $day_hits_remaining : 0;
}
Cache::put("email_day_throttle:{$key}", $new_day_throttle, 60);
Cache::put("last_email_request:{$key}", time(), 60);
if ($new_day_throttle > $day) {
$errorEmail = env('ERROR_EMAIL');
if ($errorEmail && ! Cache::get("throttle_notified:{$key}")) {
Mail::raw('Account Throttle: ' . $account->account_key, function ($message) use ($errorEmail, $account) {
$message->to($errorEmail)
->from(CONTACT_EMAIL)
->subject("Email throttle triggered for account " . $account->id);
});
}
Cache::put("throttle_notified:{$key}", true, 60 * 24);
return true;
}
return false;
}
}

View File

@ -133,12 +133,12 @@ class Invoice extends BaseModel
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function invitations()
@ -148,7 +148,7 @@ class Invoice extends BaseModel
public function client()
{
return $this->belongsTo(Client::class);
return $this->belongsTo(Client::class)->withTrashed();
}
public function documents()

View File

@ -67,7 +67,7 @@ class Payment extends BaseModel
public function client()
{
return $this->belongsTo(Client::class);
return $this->belongsTo(Client::class)->withTrashed();
}
public function company()
@ -77,12 +77,12 @@ class Payment extends BaseModel
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function documents()

View File

@ -47,12 +47,12 @@ class Product extends BaseModel
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function documents()

View File

@ -70,18 +70,18 @@ class Quote extends BaseModel
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function client()
{
return $this->belongsTo(Client::class);
return $this->belongsTo(Client::class)->withTrashed();
}
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function invitations()

View File

@ -104,22 +104,22 @@ class RecurringInvoice extends BaseModel
public function client()
{
return $this->belongsTo(Client::class);
return $this->belongsTo(Client::class)->withTrashed();
}
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function invoices()
{
return $this->hasMany(Invoice::class, "id", "recurring_invoice_id");
return $this->hasMany(Invoice::class, "id", "recurring_invoice_id")->withTrashed();
}
public function invitations()

View File

@ -99,17 +99,17 @@ class RecurringQuote extends BaseModel
public function client()
{
return $this->belongsTo(Client::class);
return $this->belongsTo(Client::class)->withTrashed();
}
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class)->withTrashed();
}
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function invitations()

View File

@ -47,7 +47,18 @@ class Task extends BaseModel
public function assigned_user()
{
return $this->belongsTo(User::class ,'assigned_user_id', 'id');
return $this->belongsTo(User::class ,'assigned_user_id', 'id')->withTrashed();
}
public function user()
{
return $this->belongsTo(User::class);
}
public function client()
{
return $this->belongsTo(Client::class);
}
}

View File

@ -87,6 +87,7 @@ class ClientTransformer extends EntityTransformer
'group_settings_id' => isset($client->group_settings_id) ? (string)$this->encodePrimaryKey($client->group_settings_id) : '',
'paid_to_date' => (float) $client->paid_to_date,
'last_login' => (int)$client->last_login,
'currency_id' => (int)$client->currency_id,
'address1' => $client->address1 ?: '',
'address2' => $client->address2 ?: '',
'phone' => $client->phone ?: '',

View File

@ -299,7 +299,7 @@ class CreateUsersTable extends Migration
$table->timestamp('last_login')->nullable();
$table->unsignedInteger('industry_id')->nullable();
$table->unsignedInteger('size_id')->nullable();
// $table->unsignedInteger('currency_id')->nullable();
$table->unsignedInteger('currency_id')->nullable();
$table->string('address1')->nullable();
$table->string('address2')->nullable();
@ -331,7 +331,7 @@ class CreateUsersTable extends Migration
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->foreign('industry_id')->references('id')->on('industries');
$table->foreign('size_id')->references('id')->on('sizes');
// $table->foreign('currency_id')->references('id')->on('currencies');
$table->foreign('currency_id')->references('id')->on('currencies');
});

View File

@ -23,7 +23,7 @@ use Tests\TestCase;
class AccountTest extends TestCase
{
use DatabaseTransactions;
//use DatabaseTransactions;
public function setUp() :void
{
@ -36,29 +36,41 @@ class AccountTest extends TestCase
Model::reguard();
}
public function testAccountCreation()
{
$data = [
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'name' => $this->faker->company,
'email' => $this->faker->unique()->safeEmail,
'password' => 'ALongAndBrilliantPassword123',
'_token' => csrf_token(),
'privacy_policy' => 1,
'terms_of_service' => 1
];
// public function testAccountCreation()
// {
// $data = [
// 'first_name' => $this->faker->firstName,
// 'last_name' => $this->faker->lastName,
// 'name' => $this->faker->company,
// 'email' => $this->faker->unique()->safeEmail,
// 'password' => 'ALongAndBrilliantPassword123',
// '_token' => csrf_token(),
// 'privacy_policy' => 1,
// 'terms_of_service' => 1
// ];
$response = $this->post('/signup', $data, ['X-API-SECRET' => 'password']);
// try {
$response->assertStatus(200);
// $response = $this->post('/signup', $data, ['X-API-SECRET' => 'password']);
// }
// catch(ValidationException $e) {
// $message = json_decode($e->validator->getMessageBag(),1);
// \Log::error($message);
// }
// finally {
// $response->assertStatus(200);
// }
// $response->assertStatus(200);
}
// }
public function testApiAccountCreation()
{
$data = [
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
@ -75,7 +87,8 @@ class AccountTest extends TestCase
])->post('/api/v1/signup?include=account', $data);
$response->assertStatus(200);
}

View File

@ -188,15 +188,15 @@ class PaymentTest extends TestCase
}
catch(ValidationException $e) {
\Log::error('in the validator');
// \Log::error('in the validator');
$message = json_decode($e->validator->getMessageBag(),1);
\Log::error($message);
// \Log::error($message);
$this->assertNotNull($message);
}
$arr = $response->json();
\Log::error($arr);
// \Log::error($arr);
$response->assertStatus(200);

View File

@ -210,13 +210,10 @@ class GroupSettingsTest extends TestCase
$this->settings = $this->company->settings;
\Log::error(print_r($this->settings,1));
$this->assertTrue($this->validateSettings($this->settings));
$new_settings = $this->saveSettings($this->settings, $this->client);
\Log::error(print_r($new_settings,1));
}
}