Merge branch 'v5-develop' into v5-stable

This commit is contained in:
David Bomba 2023-01-24 07:26:01 +11:00
commit fb0c95b78b
27 changed files with 167320 additions and 167006 deletions

View file

@ -1 +1 @@
5.5.60
5.5.61

View file

@ -448,13 +448,24 @@ class CheckData extends Command
//check contact exists!
if($contact_class::where('company_id', $entity->company_id)->where($client_vendor_key,$entity->{$client_vendor_key})->exists())
{
$invitation = new $entity_obj();
$invitation->company_id = $entity->company_id;
$invitation->user_id = $entity->user_id;
$invitation->{$entity_key} = $entity->id;
$invitation->{$contact_id} = $contact_class::where('company_id', $entity->company_id)->where($client_vendor_key,$entity->{$client_vendor_key})->first()->id;
$invitation->key = Str::random(config('ninja.key_length'));
$this->logMessage("Add invitation for {$entity_key} - {$entity->id}");
$contact = $contact_class::where('company_id', $entity->company_id)->where($client_vendor_key,$entity->{$client_vendor_key})->first();
//double check if an archived invite exists
if($contact && $entity->invitations()->withTrashed()->where($contact_id, $contact->id)->count() != 0) {
$i = $entity->invitations()->withTrashed()->where($contact_id, $contact->id)->first();
$i->restore();
$this->logMessage("Found a valid contact and invitation restoring for {$entity_key} - {$entity->id}");
}
else {
$invitation = new $entity_obj();
$invitation->company_id = $entity->company_id;
$invitation->user_id = $entity->user_id;
$invitation->{$entity_key} = $entity->id;
$invitation->{$contact_id} = $contact->id;
$invitation->key = Str::random(config('ninja.key_length'));
$this->logMessage("Add invitation for {$entity_key} - {$entity->id}");
}
}
else
$this->logMessage("No contact present, so cannot add invitation for {$entity_key} - {$entity->id}");

View file

@ -87,13 +87,15 @@ class ActivityController extends BaseController
{
$default_activities = $request->has('rows') ? $request->input('rows') : 50;
$activities = Activity::orderBy('created_at', 'DESC')->company()
$activities = Activity::orderBy('created_at', 'DESC')
->company()
->take($default_activities);
if ($request->has('react')) {
if(!auth()->user()->isAdmin())
return response()->json(['data' => []], 200);
$activities->where('user_id', auth()->user()->id);
// return response()->json(['data' => []], 200);
$system = ctrans('texts.system');

View file

@ -450,7 +450,7 @@ class BaseController extends Controller
'company.bank_transactions'=> function ($query) use ($updated_at, $user) {
$query->where('updated_at', '>=', $updated_at);
if (! $user->isAdmin()) {
if (! $user->hasPermission('view_bank_transaction')) {
$query->where('bank_transactions.user_id', $user->id);
}
},
@ -796,7 +796,7 @@ class BaseController extends Controller
'company.bank_transactions'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at);
if (! $user->isAdmin()) {
if (! $user->hasPermission('bank_transactions')) {
$query->where('bank_transactions.user_id', $user->id);
}
},
@ -861,7 +861,7 @@ class BaseController extends Controller
/**/
// 10-01-2022 need to ensure we snake case properly here to ensure permissions work as expected
// 28-03-2022 this is definitely correct here, do not append _ to the view, it resolved correctly when snake cased
if (auth()->user() && ! auth()->user()->hasPermission('view'.lcfirst(class_basename(Str::snake($this->entity_type))))) {
if (auth()->user() && ! auth()->user()->hasPermission('view_'.Str::snake(class_basename($this->entity_type)))) {
//06-10-2022 - some entities do not have assigned_user_id - this becomes an issue when we have a large company and low permission users
if(in_array($this->entity_type, [User::class])){
$query->where('id', auth()->user()->id);

View file

@ -16,7 +16,7 @@ class Cors
// ALLOW OPTIONS METHOD
$headers = [
'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers'=> 'X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-CLIENT-VERSION,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE',
'Access-Control-Allow-Headers'=> 'X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-CLIENT-VERSION,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Disposition,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE',
];
return Response::make('OK', 200, $headers);
@ -26,8 +26,8 @@ class Cors
$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-PASSWORD-BASE64,X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE');
$response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION,X-MINIMUM-CLIENT-VERSION');
$response->headers->set('Access-Control-Allow-Headers', 'X-API-PASSWORD-BASE64,X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Disposition,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE');
$response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION,X-MINIMUM-CLIENT-VERSION,Content-Disposition');
$response->headers->set('X-APP-VERSION', config('ninja.app_version'));
$response->headers->set('X-MINIMUM-CLIENT-VERSION', config('ninja.minimum_client_version'));

View file

@ -42,6 +42,23 @@ class TaskScheduler implements ShouldQueue
*/
public function handle()
{
if (! config('ninja.db.multi_db_enabled')) {
Scheduler::with('company')
->where('is_paused', false)
->where('is_deleted', false)
->whereNotNull('next_run')
->where('next_run', '<=', now())
->cursor()
->each(function ($scheduler) {
$this->doJob($scheduler);
});
return;
}
foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db);

View file

@ -174,7 +174,7 @@ class BaseModel extends Model
return $this
->withTrashed()
->company()
// ->company()
->where('id', $this->decodePrimaryKey($value))->firstOrFail();
}

View file

@ -240,7 +240,7 @@ class ClientContact extends Authenticatable implements HasLocalePreference
{
return $this
->withTrashed()
->company()
// ->company()
->where('id', $this->decodePrimaryKey($value))->firstOrFail();
}

View file

@ -358,18 +358,21 @@ class User extends Authenticatable implements MustVerifyEmail
public function hasPermission($permission) : bool
{
$parts = explode('_', $permission);
$all_permission = '';
$all_permission = false;
if (count($parts) > 1) {
$all_permission = $parts[0].'_all';
}
//empty $all_permissions leads to stripos returning true;
return $this->isOwner() ||
$this->isAdmin() ||
(is_int(stripos($this->token()->cu->permissions, $all_permission))) ||
(is_int(stripos($this->token()->cu->permissions, $permission)));
(stripos($all_permission, $this->token()->cu->permissions) !== false) ||
(stripos($permission, $this->token()->cu->permissions) !== false);
// return $this->isOwner() ||
// $this->isAdmin() ||
// (is_int(stripos($this->token()->cu->permissions, $all_permission))) ||
// (is_int(stripos($this->token()->cu->permissions, $permission)));
}

View file

@ -26,6 +26,6 @@ class BankTransactionPolicy extends EntityPolicy
*/
public function create(User $user) : bool
{
return $user->isAdmin();
return $user->isAdmin() || $user->hasPermission('create_invoice') || $user->hasPermission('create_all');
}
}

View file

@ -47,7 +47,7 @@ class EntityPolicy
public function edit(User $user, $entity) : bool
{
return ($user->isAdmin() && $entity->company_id == $user->companyId())
|| ($user->hasPermission('edit_'.strtolower(\Illuminate\Support\Str::snake(class_basename($entity)))) && $entity->company_id == $user->companyId())
|| ($user->hasPermission('edit_'.\Illuminate\Support\Str::snake(class_basename($entity))) && $entity->company_id == $user->companyId())
|| ($user->hasPermission('edit_all') && $entity->company_id == $user->companyId())
|| ($user->owns($entity) && $entity->company_id == $user->companyId())
|| ($user->assigned($entity) && $entity->company_id == $user->companyId());
@ -64,7 +64,7 @@ class EntityPolicy
public function view(User $user, $entity) : bool
{
return ($user->isAdmin() && $entity->company_id == $user->companyId())
|| ($user->hasPermission('view_'.strtolower(\Illuminate\Support\Str::snake(class_basename($entity)))) && $entity->company_id == $user->companyId())
|| ($user->hasPermission('view_'.\Illuminate\Support\Str::snake(class_basename($entity))) && $entity->company_id == $user->companyId())
|| ($user->hasPermission('view_all') && $entity->company_id == $user->companyId())
|| ($user->owns($entity) && $entity->company_id == $user->companyId())
|| ($user->assigned($entity) && $entity->company_id == $user->companyId());

View file

@ -98,7 +98,7 @@ class SubscriptionService
->save();
//update the invoice and attach to the recurring invoice!!!!!
$invoice = Invoice::find($payment_hash->fee_invoice_id);
$invoice = Invoice::withTrashed()->find($payment_hash->fee_invoice_id);
$invoice->recurring_id = $recurring_invoice->id;
$invoice->is_proforma = false;
$invoice->save();

View file

@ -23,7 +23,7 @@ return [
'allowed_origins_patterns' => [],
'allowed_headers' => ['X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE'],
'allowed_headers' => ['X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Disposition,Content-Type,Range,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE'],
'exposed_headers' => ['X-APP-VERSION,X-MINIMUM-CLIENT-VERSION,X-CSRF-TOKEN,X-XSRF-TOKEN,X-LIVEWIRE'],

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.5.60',
'app_tag' => '5.5.60',
'app_version' => '5.5.61',
'app_tag' => '5.5.61',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View file

@ -476,10 +476,10 @@ return new class extends Migration {
$t->string('custom_value4')->nullable();
$t->datetime('next_send_date')->nullable();
$t->string('custom_surcharge1')->nullable();
$t->string('custom_surcharge2')->nullable();
$t->string('custom_surcharge3')->nullable();
$t->string('custom_surcharge4')->nullable();
$t->decimal('custom_surcharge1', 20, 6)->nullable();
$t->decimal('custom_surcharge2', 20, 6)->nullable();
$t->decimal('custom_surcharge3', 20, 6)->nullable();
$t->decimal('custom_surcharge4', 20, 6)->nullable();
$t->boolean('custom_surcharge_tax1')->default(false);
$t->boolean('custom_surcharge_tax2')->default(false);
$t->boolean('custom_surcharge_tax3')->default(false);
@ -554,10 +554,10 @@ return new class extends Migration {
$t->string('custom_value4')->nullable();
$t->datetime('next_send_date')->nullable();
$t->string('custom_surcharge1')->nullable();
$t->string('custom_surcharge2')->nullable();
$t->string('custom_surcharge3')->nullable();
$t->string('custom_surcharge4')->nullable();
$t->decimal('custom_surcharge1', 20, 6)->nullable();
$t->decimal('custom_surcharge2', 20, 6)->nullable();
$t->decimal('custom_surcharge3', 20, 6)->nullable();
$t->decimal('custom_surcharge4', 20, 6)->nullable();
$t->boolean('custom_surcharge_tax1')->default(false);
$t->boolean('custom_surcharge_tax2')->default(false);
$t->boolean('custom_surcharge_tax3')->default(false);
@ -791,10 +791,10 @@ return new class extends Migration {
$t->string('custom_value3')->nullable();
$t->string('custom_value4')->nullable();
$t->string('custom_surcharge1')->nullable();
$t->string('custom_surcharge2')->nullable();
$t->string('custom_surcharge3')->nullable();
$t->string('custom_surcharge4')->nullable();
$t->decimal('custom_surcharge1', 20, 6)->nullable();
$t->decimal('custom_surcharge2', 20, 6)->nullable();
$t->decimal('custom_surcharge3', 20, 6)->nullable();
$t->decimal('custom_surcharge4', 20, 6)->nullable();
$t->boolean('custom_surcharge_tax1')->default(false);
$t->boolean('custom_surcharge_tax2')->default(false);
$t->boolean('custom_surcharge_tax3')->default(false);

View file

@ -59,10 +59,10 @@ return new class extends Migration {
$table->boolean('auto_bill_enabled')->default(0);
$table->unsignedInteger('design_id')->nullable();
$table->boolean('uses_inclusive_taxes')->default(0);
$table->string('custom_surcharge1')->nullable();
$table->string('custom_surcharge2')->nullable();
$table->string('custom_surcharge3')->nullable();
$table->string('custom_surcharge4')->nullable();
$table->decimal('custom_surcharge1', 20, 6)->nullable();
$table->decimal('custom_surcharge2', 20, 6)->nullable();
$table->decimal('custom_surcharge3', 20, 6)->nullable();
$table->decimal('custom_surcharge4', 20, 6)->nullable();
$table->boolean('custom_surcharge_tax1')->default(false);
$table->boolean('custom_surcharge_tax2')->default(false);
$table->boolean('custom_surcharge_tax3')->default(false);

View file

@ -12,33 +12,33 @@ return new class extends Migration {
*/
public function up()
{
Schema::table('invoices', function (Blueprint $table) {
$table->decimal('custom_surcharge1', 20, 6)->change();
$table->decimal('custom_surcharge2', 20, 6)->change();
$table->decimal('custom_surcharge3', 20, 6)->change();
$table->decimal('custom_surcharge4', 20, 6)->change();
});
// Schema::table('invoices', function (Blueprint $table) {
// $table->decimal('custom_surcharge1', 20, 6)->change();
// $table->decimal('custom_surcharge2', 20, 6)->change();
// $table->decimal('custom_surcharge3', 20, 6)->change();
// $table->decimal('custom_surcharge4', 20, 6)->change();
// });
Schema::table('recurring_invoices', function (Blueprint $table) {
$table->decimal('custom_surcharge1', 20, 6)->change();
$table->decimal('custom_surcharge2', 20, 6)->change();
$table->decimal('custom_surcharge3', 20, 6)->change();
$table->decimal('custom_surcharge4', 20, 6)->change();
});
// Schema::table('recurring_invoices', function (Blueprint $table) {
// $table->decimal('custom_surcharge1', 20, 6)->change();
// $table->decimal('custom_surcharge2', 20, 6)->change();
// $table->decimal('custom_surcharge3', 20, 6)->change();
// $table->decimal('custom_surcharge4', 20, 6)->change();
// });
Schema::table('quotes', function (Blueprint $table) {
$table->decimal('custom_surcharge1', 20, 6)->change();
$table->decimal('custom_surcharge2', 20, 6)->change();
$table->decimal('custom_surcharge3', 20, 6)->change();
$table->decimal('custom_surcharge4', 20, 6)->change();
});
// Schema::table('quotes', function (Blueprint $table) {
// $table->decimal('custom_surcharge1', 20, 6)->change();
// $table->decimal('custom_surcharge2', 20, 6)->change();
// $table->decimal('custom_surcharge3', 20, 6)->change();
// $table->decimal('custom_surcharge4', 20, 6)->change();
// });
Schema::table('credits', function (Blueprint $table) {
$table->decimal('custom_surcharge1', 20, 6)->change();
$table->decimal('custom_surcharge2', 20, 6)->change();
$table->decimal('custom_surcharge3', 20, 6)->change();
$table->decimal('custom_surcharge4', 20, 6)->change();
});
// Schema::table('credits', function (Blueprint $table) {
// $table->decimal('custom_surcharge1', 20, 6)->change();
// $table->decimal('custom_surcharge2', 20, 6)->change();
// $table->decimal('custom_surcharge3', 20, 6)->change();
// $table->decimal('custom_surcharge4', 20, 6)->change();
// });
}
/**

View file

@ -4,8 +4,8 @@ const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
"flutter.js": "f85e6fb278b0fd20c349186fb46ae36d",
"/": "911f541b7841f1489526cac9db913e3f",
"main.dart.js": "6e6f82717bb27feb8e7bced23b43125e",
"/": "81db08b231c2ca12a2c6c27abc6546dc",
"main.dart.js": "80df879ac94d14fd27d03749428a2ccc",
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
"favicon.ico": "51636d3a390451561744c42188ccd628",
"favicon.png": "dca91c54388f52eded692718d5a98b8b",

160907
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

161173
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

File diff suppressed because one or more lines are too long

View file

@ -2,6 +2,15 @@
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
@if(App\Utils\Ninja::isHosted())
<!-- G Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-WMJ5W23');</script>
<!-- End G Tag Manager -->
@endif
<!-- Error: {{ session('error') }} -->
@if (isset($company) && $company->matomo_url && $company->matomo_id)
<script>

View file

@ -18,6 +18,7 @@ use App\Models\BankIntegration;
use App\Models\BankTransaction;
use App\Models\BankTransactionRule;
use App\Models\Invoice;
use App\Services\Bank\ProcessBankRules;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Validation\ValidationException;
use Tests\MockAccountData;
@ -41,6 +42,19 @@ class BankTransactionRuleTest extends TestCase
$this->withoutExceptionHandling();
}
public function testMatchingWithStripos()
{
$bt_value = strtolower(str_replace(" ", "", 'hello soldier'));
$rule_value = strtolower(str_replace(" ", "", 'solider'));
$rule_length = iconv_strlen($rule_value);
$this->assertFalse(stripos($rule_value, $bt_value) !== false);
$this->assertFalse(stripos($bt_value, $rule_value) !== false);
}
public function testBankRuleBulkActions()
{
$data = [

View file

@ -31,7 +31,7 @@ class ExampleIntegrationTest extends TestCase
public function testExample()
{
$this->markTestIncomplete();
// $this->markTestIncomplete();
$invoice = $this->invoice;
$invitation = $invoice->invitations()->first();
@ -57,10 +57,6 @@ class ExampleIntegrationTest extends TestCase
->design($design)
->build();
// exec('echo "" > storage/logs/laravel.log');
// nlog($maker->getCompiledHTML(true));
$this->assertTrue(true);
$this->assertNotNull($maker->getCompiledHTML(true));
}
}

View file

@ -13,10 +13,12 @@ namespace Tests\Unit;
use App\Factory\CompanyUserFactory;
use App\Models\Account;
use App\Models\Client;
use App\Models\Company;
use App\Models\CompanyToken;
use App\Models\CompanyUser;
use App\Models\Invoice;
use App\Models\RecurringInvoice;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\MockAccountData;
@ -77,6 +79,54 @@ class PermissionsTest extends TestCase
}
public function testPermissionResolution()
{
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(Invoice::class)));
$this->assertEquals('view_invoice', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(Client::class)));
$this->assertEquals('view_client', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(RecurringInvoice::class)));
$this->assertEquals('view_recurring_invoice', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Product::class)));
$this->assertEquals('view_product', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Payment::class)));
$this->assertEquals('view_payment', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Quote::class)));
$this->assertEquals('view_quote', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Credit::class)));
$this->assertEquals('view_credit', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Project::class)));
$this->assertEquals('view_project', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Task::class)));
$this->assertEquals('view_task', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Vendor::class)));
$this->assertEquals('view_vendor', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\PurchaseOrder::class)));
$this->assertEquals('view_purchase_order', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\Expense::class)));
$this->assertEquals('view_expense', $class);
$class = 'view'.lcfirst(class_basename(\Illuminate\Support\Str::snake(App\Models\BankTransaction::class)));
$this->assertEquals('view_bank_transaction', $class);
$this->assertEquals('invoice', \Illuminate\Support\Str::snake(class_basename(Invoice::class)));
$this->assertEquals('recurring_invoice', \Illuminate\Support\Str::snake(class_basename(RecurringInvoice::class)));
}
public function testExactPermissions()
{
@ -109,6 +159,40 @@ class PermissionsTest extends TestCase
}
public function testReturnTypesOfStripos()
{
$this->assertEquals(0, stripos("view_client", ''));
$all_permission = '[]';
$this->assertFalse(stripos($all_permission, "view_client") !== false);
$this->assertTrue(stripos($all_permission, "view_client") == 0);
$this->assertFalse(is_int(stripos($all_permission, "view_client")));
$all_permission = ' ';
$this->assertFalse(stripos($all_permission, "view_client") !== false);
$this->assertFalse(is_int(stripos($all_permission, "view_client")));
$all_permission = "";//problems are empty strings
$this->assertTrue(empty($all_permission));
$this->assertFalse( stripos($all_permission, "view_client") !== false);
$this->assertFalse( is_int(stripos($all_permission, "view_client")));
$all_permission = 'view';//will always pass currently
$this->assertFalse( stripos($all_permission, "view_client") !== false);
$this->assertFalse(is_int(stripos($all_permission, "view_client")));
$all_permission = "view_client";
$this->assertTrue(stripos($all_permission, "view_client") !== false);
$this->assertTrue(is_int(stripos($all_permission, "view_client")) !== false);
$this->assertTrue(is_int(stripos($all_permission, "view_client")));
}
public function testViewClientPermission()
{
@ -116,8 +200,8 @@ class PermissionsTest extends TestCase
$low_cu->permissions = '["view_client"]';
$low_cu->save();
//this is aberrant
$this->assertTrue($this->user->hasPermission("viewclient"));
// this is aberrant
$this->assertFalse($this->user->hasPermission("view____client"));
}