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:
parent
808c6deb88
commit
0908893180
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,8 @@ class CreateAccountRequest extends Request
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return ! auth()->user();
|
||||
return true;
|
||||
//return ! auth()->user();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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 ?: '',
|
||||
|
@ -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');
|
||||
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user