123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398 |
- <?php
- namespace Illuminate\Tests\Auth;
- use Illuminate\Auth\Access\AuthorizationException;
- use Illuminate\Auth\Access\Gate;
- use Illuminate\Auth\Access\HandlesAuthorization;
- use Illuminate\Auth\Access\Response;
- use Illuminate\Container\Container;
- use InvalidArgumentException;
- use PHPUnit\Framework\TestCase;
- use stdClass;
- class AuthAccessGateTest extends TestCase
- {
- public function testBasicClosuresCanBeDefined()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', function ($user) {
- return true;
- });
- $gate->define('bar', function ($user) {
- return false;
- });
- $this->assertTrue($gate->check('foo'));
- $this->assertFalse($gate->check('bar'));
- }
- public function testBeforeCanTakeAnArrayCallbackAsObject()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->before([new AccessGateTestBeforeCallback, 'allowEverything']);
- $this->assertTrue($gate->check('anything'));
- }
- public function testBeforeCanTakeAnArrayCallbackAsObjectStatic()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->before([new AccessGateTestBeforeCallback, 'allowEverythingStatically']);
- $this->assertTrue($gate->check('anything'));
- }
- public function testBeforeCanTakeAnArrayCallbackWithStaticMethod()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->before([AccessGateTestBeforeCallback::class, 'allowEverythingStatically']);
- $this->assertTrue($gate->check('anything'));
- }
- public function testBeforeCanAllowGuests()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->before(function (?stdClass $user) {
- return true;
- });
- $this->assertTrue($gate->check('anything'));
- }
- public function testAfterCanAllowGuests()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->after(function (?stdClass $user) {
- return true;
- });
- $this->assertTrue($gate->check('anything'));
- }
- public function testClosuresCanAllowGuestUsers()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->define('foo', function (?stdClass $user) {
- return true;
- });
- $gate->define('bar', function (stdClass $user) {
- return false;
- });
- $this->assertTrue($gate->check('foo'));
- $this->assertFalse($gate->check('bar'));
- }
- public function testPoliciesCanAllowGuests()
- {
- unset($_SERVER['__laravel.testBefore']);
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyThatAllowsGuests::class);
- $this->assertTrue($gate->check('edit', new AccessGateTestDummy));
- $this->assertFalse($gate->check('update', new AccessGateTestDummy));
- $this->assertTrue($_SERVER['__laravel.testBefore']);
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyThatAllowsGuests::class);
- $this->assertTrue($gate->check('edit', new AccessGateTestDummy));
- $this->assertTrue($gate->check('update', new AccessGateTestDummy));
- unset($_SERVER['__laravel.testBefore']);
- }
- public function testPolicyBeforeNotCalledWithGuestsIfItDoesntAllowThem()
- {
- $_SERVER['__laravel.testBefore'] = false;
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithNonGuestBefore::class);
- $this->assertTrue($gate->check('edit', new AccessGateTestDummy));
- $this->assertFalse($gate->check('update', new AccessGateTestDummy));
- $this->assertFalse($_SERVER['__laravel.testBefore']);
- unset($_SERVER['__laravel.testBefore']);
- }
- public function testBeforeAndAfterCallbacksCanAllowGuests()
- {
- $_SERVER['__laravel.gateBefore'] = false;
- $_SERVER['__laravel.gateBefore2'] = false;
- $_SERVER['__laravel.gateAfter'] = false;
- $_SERVER['__laravel.gateAfter2'] = false;
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->before(function (?stdClass $user) {
- $_SERVER['__laravel.gateBefore'] = true;
- });
- $gate->after(function (?stdClass $user) {
- $_SERVER['__laravel.gateAfter'] = true;
- });
- $gate->before(function (stdClass $user) {
- $_SERVER['__laravel.gateBefore2'] = true;
- });
- $gate->after(function (stdClass $user) {
- $_SERVER['__laravel.gateAfter2'] = true;
- });
- $gate->define('foo', function ($user = null) {
- return true;
- });
- $this->assertTrue($gate->check('foo'));
- $this->assertTrue($_SERVER['__laravel.gateBefore']);
- $this->assertFalse($_SERVER['__laravel.gateBefore2']);
- $this->assertTrue($_SERVER['__laravel.gateAfter']);
- $this->assertFalse($_SERVER['__laravel.gateAfter2']);
- unset(
- $_SERVER['__laravel.gateBefore'],
- $_SERVER['__laravel.gateBefore2'],
- $_SERVER['__laravel.gateAfter'],
- $_SERVER['__laravel.gateAfter2']
- );
- }
- public function testResourceGatesCanBeDefined()
- {
- $gate = $this->getBasicGate();
- $gate->resource('test', AccessGateTestResource::class);
- $dummy = new AccessGateTestDummy;
- $this->assertTrue($gate->check('test.view'));
- $this->assertTrue($gate->check('test.create'));
- $this->assertTrue($gate->check('test.update', $dummy));
- $this->assertTrue($gate->check('test.delete', $dummy));
- }
- public function testCustomResourceGatesCanBeDefined()
- {
- $gate = $this->getBasicGate();
- $abilities = [
- 'ability1' => 'foo',
- 'ability2' => 'bar',
- ];
- $gate->resource('test', AccessGateTestCustomResource::class, $abilities);
- $this->assertTrue($gate->check('test.ability1'));
- $this->assertTrue($gate->check('test.ability2'));
- }
- public function testBeforeCallbacksCanOverrideResultIfNecessary()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', function ($user) {
- return true;
- });
- $gate->before(function ($user, $ability) {
- $this->assertSame('foo', $ability);
- return false;
- });
- $this->assertFalse($gate->check('foo'));
- }
- public function testBeforeCallbacksDontInterruptGateCheckIfNoValueIsReturned()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', function ($user) {
- return true;
- });
- $gate->before(function () {
- //
- });
- $this->assertTrue($gate->check('foo'));
- }
- public function testAfterCallbacksAreCalledWithResult()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', function ($user) {
- return true;
- });
- $gate->define('bar', function ($user) {
- return false;
- });
- $gate->after(function ($user, $ability, $result) {
- if ($ability === 'foo') {
- $this->assertTrue($result, 'After callback on `foo` should receive true as result');
- } elseif ($ability === 'bar') {
- $this->assertFalse($result, 'After callback on `bar` should receive false as result');
- } else {
- $this->assertNull($result, 'After callback on `missing` should receive null as result');
- }
- });
- $this->assertTrue($gate->check('foo'));
- $this->assertFalse($gate->check('bar'));
- $this->assertFalse($gate->check('missing'));
- }
- public function testAfterCallbacksCanAllowIfNull()
- {
- $gate = $this->getBasicGate();
- $gate->after(function ($user, $ability, $result) {
- return true;
- });
- $this->assertTrue($gate->allows('null'));
- }
- public function testAfterCallbacksDoNotOverridePreviousResult()
- {
- $gate = $this->getBasicGate();
- $gate->define('deny', function ($user) {
- return false;
- });
- $gate->define('allow', function ($user) {
- return true;
- });
- $gate->after(function ($user, $ability, $result) {
- return ! $result;
- });
- $this->assertTrue($gate->allows('allow'));
- $this->assertTrue($gate->denies('deny'));
- }
- public function testAfterCallbacksDoNotOverrideEachOther()
- {
- $gate = $this->getBasicGate();
- $gate->after(function ($user, $ability, $result) {
- return $ability === 'allow';
- });
- $gate->after(function ($user, $ability, $result) {
- return ! $result;
- });
- $this->assertTrue($gate->allows('allow'));
- $this->assertTrue($gate->denies('deny'));
- }
- public function testCurrentUserThatIsOnGateAlwaysInjectedIntoClosureCallbacks()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', function ($user) {
- $this->assertSame(1, $user->id);
- return true;
- });
- $this->assertTrue($gate->check('foo'));
- }
- public function testASingleArgumentCanBePassedWhenCheckingAbilities()
- {
- $gate = $this->getBasicGate();
- $dummy = new AccessGateTestDummy;
- $gate->before(function ($user, $ability, array $arguments) use ($dummy) {
- $this->assertCount(1, $arguments);
- $this->assertSame($dummy, $arguments[0]);
- });
- $gate->define('foo', function ($user, $x) use ($dummy) {
- $this->assertSame($dummy, $x);
- return true;
- });
- $gate->after(function ($user, $ability, $result, array $arguments) use ($dummy) {
- $this->assertCount(1, $arguments);
- $this->assertSame($dummy, $arguments[0]);
- });
- $this->assertTrue($gate->check('foo', $dummy));
- }
- public function testMultipleArgumentsCanBePassedWhenCheckingAbilities()
- {
- $gate = $this->getBasicGate();
- $dummy1 = new AccessGateTestDummy;
- $dummy2 = new AccessGateTestDummy;
- $gate->before(function ($user, $ability, array $arguments) use ($dummy1, $dummy2) {
- $this->assertCount(2, $arguments);
- $this->assertSame([$dummy1, $dummy2], $arguments);
- });
- $gate->define('foo', function ($user, $x, $y) use ($dummy1, $dummy2) {
- $this->assertSame($dummy1, $x);
- $this->assertSame($dummy2, $y);
- return true;
- });
- $gate->after(function ($user, $ability, $result, array $arguments) use ($dummy1, $dummy2) {
- $this->assertCount(2, $arguments);
- $this->assertSame([$dummy1, $dummy2], $arguments);
- });
- $this->assertTrue($gate->check('foo', [$dummy1, $dummy2]));
- }
- public function testClassesCanBeDefinedAsCallbacksUsingAtNotation()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', AccessGateTestClass::class.'@foo');
- $this->assertTrue($gate->check('foo'));
- }
- public function testInvokableClassesCanBeDefined()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', AccessGateTestInvokableClass::class);
- $this->assertTrue($gate->check('foo'));
- }
- public function testGatesCanBeDefinedUsingAnArrayCallback()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', [new AccessGateTestStaticClass, 'foo']);
- $this->assertTrue($gate->check('foo'));
- }
- public function testGatesCanBeDefinedUsingAnArrayCallbackWithStaticMethod()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', [AccessGateTestStaticClass::class, 'foo']);
- $this->assertTrue($gate->check('foo'));
- }
- public function testPolicyClassesCanBeDefinedToHandleChecksForGivenType()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('update', new AccessGateTestDummy));
- }
- public function testPolicyClassesHandleChecksForAllSubtypes()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('update', new AccessGateTestSubDummy));
- }
- public function testPolicyClassesHandleChecksForInterfaces()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummyInterface::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('update', new AccessGateTestSubDummy));
- }
- public function testPolicyConvertsDashToCamel()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('update-dash', new AccessGateTestDummy));
- }
- public function testPolicyDefaultToFalseIfMethodDoesNotExistAndGateDoesNotExist()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertFalse($gate->check('nonexistent_method', new AccessGateTestDummy));
- }
- public function testPolicyClassesCanBeDefinedToHandleChecksForGivenClassName()
- {
- $gate = $this->getBasicGate(true);
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('create', [AccessGateTestDummy::class, true]));
- }
- public function testPoliciesMayHaveBeforeMethodsToOverrideChecks()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithBefore::class);
- $this->assertTrue($gate->check('update', new AccessGateTestDummy));
- }
- public function testPoliciesAlwaysOverrideClosuresWithSameName()
- {
- $gate = $this->getBasicGate();
- $gate->define('update', function () {
- $this->fail();
- });
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('update', new AccessGateTestDummy));
- }
- public function testPoliciesDeferToGatesIfMethodDoesNotExist()
- {
- $gate = $this->getBasicGate();
- $gate->define('nonexistent_method', function ($user) {
- return true;
- });
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $this->assertTrue($gate->check('nonexistent_method', new AccessGateTestDummy));
- }
- public function testForUserMethodAttachesANewUserToANewGateInstance()
- {
- $gate = $this->getBasicGate();
- // Assert that the callback receives the new user with ID of 2 instead of ID of 1...
- $gate->define('foo', function ($user) {
- $this->assertSame(2, $user->id);
- return true;
- });
- $this->assertTrue($gate->forUser((object) ['id' => 2])->check('foo'));
- }
- public function testForUserMethodAttachesANewUserToANewGateInstanceWithGuessCallback()
- {
- $gate = $this->getBasicGate();
- $gate->define('foo', function () {
- return true;
- });
- $counter = 0;
- $guesserCallback = function () use (&$counter) {
- $counter++;
- };
- $gate->guessPolicyNamesUsing($guesserCallback);
- $gate->getPolicyFor('fooClass');
- $this->assertSame(1, $counter);
- // now the guesser callback should be present on the new gate as well
- $newGate = $gate->forUser((object) ['id' => 1]);
- $newGate->getPolicyFor('fooClass');
- $this->assertSame(2, $counter);
- $newGate->getPolicyFor('fooClass');
- $this->assertSame(3, $counter);
- }
- /**
- * @dataProvider notCallableDataProvider
- */
- public function testDefineSecondParameterShouldBeStringOrCallable($callback)
- {
- $this->expectException(InvalidArgumentException::class);
- $gate = $this->getBasicGate();
- $gate->define('foo', $callback);
- }
- /**
- * @return array
- */
- public function notCallableDataProvider()
- {
- return [
- [1],
- [new stdClass],
- [[]],
- [1.1],
- ];
- }
- public function testAuthorizeThrowsUnauthorizedException()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('You are not an admin.');
- $this->expectExceptionCode(null);
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $gate->authorize('create', new AccessGateTestDummy);
- }
- public function testAuthorizeThrowsUnauthorizedExceptionWithCustomStatusCode()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('Not allowed to view as it is not published.');
- $this->expectExceptionCode('unpublished');
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithCode::class);
- $gate->authorize('view', new AccessGateTestDummy);
- }
- public function testAuthorizeWithPolicyThatReturnsDeniedResponseObjectThrowsException()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('Not allowed.');
- $this->expectExceptionCode('some_code');
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithDeniedResponseObject::class);
- $gate->authorize('create', new AccessGateTestDummy);
- }
- public function testPolicyThatThrowsAuthorizationExceptionIsCaughtInInspect()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyThrowingAuthorizationException::class);
- $response = $gate->inspect('create', new AccessGateTestDummy);
- $this->assertTrue($response->denied());
- $this->assertFalse($response->allowed());
- $this->assertSame('Not allowed.', $response->message());
- $this->assertSame('some_code', $response->code());
- }
- public function testAuthorizeReturnsAllowedResponse()
- {
- $gate = $this->getBasicGate(true);
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $check = $gate->check('create', new AccessGateTestDummy);
- $response = $gate->authorize('create', new AccessGateTestDummy);
- $this->assertInstanceOf(Response::class, $response);
- $this->assertNull($response->message());
- $this->assertTrue($check);
- }
- public function testResponseReturnsResponseWhenAbilityGranted()
- {
- $gate = $this->getBasicGate(true);
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithCode::class);
- $response = $gate->inspect('view', new AccessGateTestDummy);
- $this->assertInstanceOf(Response::class, $response);
- $this->assertNull($response->message());
- $this->assertTrue($response->allowed());
- $this->assertFalse($response->denied());
- $this->assertNull($response->code());
- }
- public function testResponseReturnsResponseWhenAbilityDenied()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithCode::class);
- $response = $gate->inspect('view', new AccessGateTestDummy);
- $this->assertInstanceOf(Response::class, $response);
- $this->assertSame('Not allowed to view as it is not published.', $response->message());
- $this->assertFalse($response->allowed());
- $this->assertTrue($response->denied());
- $this->assertSame('unpublished', $response->code());
- }
- public function testAuthorizeReturnsAnAllowedResponseForATruthyReturn()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicy::class);
- $response = $gate->authorize('update', new AccessGateTestDummy);
- $this->assertInstanceOf(Response::class, $response);
- $this->assertNull($response->message());
- }
- public function testAllowIfAuthorizesTrue()
- {
- $response = $this->getBasicGate()->allowIf(true);
- $this->assertTrue($response->allowed());
- }
- public function testAllowIfAuthorizesTruthy()
- {
- $response = $this->getBasicGate()->allowIf('truthy');
- $this->assertTrue($response->allowed());
- }
- public function testAllowIfAuthorizesIfGuest()
- {
- $response = $this->getBasicGate()->forUser(null)->allowIf(true);
- $this->assertTrue($response->allowed());
- }
- public function testAllowIfAuthorizesCallbackTrue()
- {
- $response = $this->getBasicGate()->allowIf(function ($user) {
- $this->assertSame(1, $user->id);
- return true;
- }, 'foo', 'bar');
- $this->assertTrue($response->allowed());
- $this->assertSame('foo', $response->message());
- $this->assertSame('bar', $response->code());
- }
- public function testAllowIfAuthorizesResponseAllowed()
- {
- $response = $this->getBasicGate()->allowIf(Response::allow('foo', 'bar'));
- $this->assertTrue($response->allowed());
- $this->assertSame('foo', $response->message());
- $this->assertSame('bar', $response->code());
- }
- public function testAllowIfAuthorizesCallbackResponseAllowed()
- {
- $response = $this->getBasicGate()->allowIf(function () {
- return Response::allow('quz', 'qux');
- }, 'foo', 'bar');
- $this->assertTrue($response->allowed());
- $this->assertSame('quz', $response->message());
- $this->assertSame('qux', $response->code());
- }
- public function testAllowsIfCallbackAcceptsGuestsWhenAuthenticated()
- {
- $response = $this->getBasicGate()->allowIf(function (stdClass $user = null) {
- return $user !== null;
- });
- $this->assertTrue($response->allowed());
- }
- public function testAllowIfCallbackAcceptsGuestsWhenUnauthenticated()
- {
- $gate = $this->getBasicGate()->forUser(null);
- $response = $gate->allowIf(function (stdClass $user = null) {
- return $user === null;
- });
- $this->assertTrue($response->allowed());
- }
- public function testAllowIfThrowsExceptionWhenFalse()
- {
- $this->expectException(AuthorizationException::class);
- $this->getBasicGate()->allowIf(false);
- }
- public function testAllowIfThrowsExceptionWhenCallbackFalse()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $this->getBasicGate()->allowIf(function () {
- return false;
- }, 'foo', 'bar');
- }
- public function testAllowIfThrowsExceptionWhenResponseDenied()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $this->getBasicGate()->allowIf(Response::deny('foo', 'bar'));
- }
- public function testAllowIfThrowsExceptionWhenCallbackResponseDenied()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('quz');
- $this->expectExceptionCode('qux');
- $this->getBasicGate()->allowIf(function () {
- return Response::deny('quz', 'qux');
- }, 'foo', 'bar');
- }
- public function testAllowIfThrowsExceptionIfUnauthenticated()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $gate = $this->getBasicGate()->forUser(null);
- $gate->allowIf(function () {
- return true;
- }, 'foo', 'bar');
- }
- public function testAllowIfThrowsExceptionIfAuthUserExpectedWhenGuest()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $gate = $this->getBasicGate()->forUser(null);
- $gate->allowIf(function (stdClass $user) {
- return true;
- }, 'foo', 'bar');
- }
- public function testDenyIfAuthorizesFalse()
- {
- $response = $this->getBasicGate()->denyIf(false);
- $this->assertTrue($response->allowed());
- }
- public function testDenyIfAuthorizesFalsy()
- {
- $response = $this->getBasicGate()->denyIf(0);
- $this->assertTrue($response->allowed());
- }
- public function testDenyIfAuthorizesIfGuest()
- {
- $response = $this->getBasicGate()->forUser(null)->denyIf(false);
- $this->assertTrue($response->allowed());
- }
- public function testDenyIfAuthorizesCallbackFalse()
- {
- $response = $this->getBasicGate()->denyIf(function ($user) {
- $this->assertSame(1, $user->id);
- return false;
- }, 'foo', 'bar');
- $this->assertTrue($response->allowed());
- $this->assertSame('foo', $response->message());
- $this->assertSame('bar', $response->code());
- }
- public function testDenyIfAuthorizesResponseAllowed()
- {
- $response = $this->getBasicGate()->denyIf(Response::allow('foo', 'bar'));
- $this->assertTrue($response->allowed());
- $this->assertSame('foo', $response->message());
- $this->assertSame('bar', $response->code());
- }
- public function testDenyIfAuthorizesCallbackResponseAllowed()
- {
- $response = $this->getBasicGate()->denyIf(function () {
- return Response::allow('quz', 'qux');
- }, 'foo', 'bar');
- $this->assertTrue($response->allowed());
- $this->assertSame('quz', $response->message());
- $this->assertSame('qux', $response->code());
- }
- public function testDenyIfCallbackAcceptsGuestsWhenAuthenticated()
- {
- $response = $this->getBasicGate()->denyIf(function (stdClass $user = null) {
- return $user === null;
- });
- $this->assertTrue($response->allowed());
- }
- public function testDenyIfCallbackAcceptsGuestsWhenUnauthenticated()
- {
- $gate = $this->getBasicGate()->forUser(null);
- $response = $gate->denyIf(function (stdClass $user = null) {
- return $user !== null;
- });
- $this->assertTrue($response->allowed());
- }
- public function testDenyIfThrowsExceptionWhenTrue()
- {
- $this->expectException(AuthorizationException::class);
- $this->getBasicGate()->denyIf(true);
- }
- public function testDenyIfThrowsExceptionWhenCallbackTrue()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $this->getBasicGate()->denyIf(function () {
- return true;
- }, 'foo', 'bar');
- }
- public function testDenyIfThrowsExceptionWhenResponseDenied()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $this->getBasicGate()->denyIf(Response::deny('foo', 'bar'));
- }
- public function testDenyIfThrowsExceptionWhenCallbackResponseDenied()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('quz');
- $this->expectExceptionCode('qux');
- $this->getBasicGate()->denyIf(function () {
- return Response::deny('quz', 'qux');
- }, 'foo', 'bar');
- }
- public function testDenyIfThrowsExceptionIfUnauthenticated()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $gate = $this->getBasicGate()->forUser(null);
- $gate->denyIf(function () {
- return false;
- }, 'foo', 'bar');
- }
- public function testDenyIfThrowsExceptionIfAuthUserExpectedWhenGuest()
- {
- $this->expectException(AuthorizationException::class);
- $this->expectExceptionMessage('foo');
- $this->expectExceptionCode('bar');
- $gate = $this->getBasicGate()->forUser(null);
- $gate->denyIf(function (stdClass $user) {
- return false;
- }, 'foo', 'bar');
- }
- protected function getBasicGate($isAdmin = false)
- {
- return new Gate(new Container, function () use ($isAdmin) {
- return (object) ['id' => 1, 'isAdmin' => $isAdmin];
- });
- }
- public function testAnyAbilityCheckPassesIfAllPass()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithAllPermissions::class);
- $this->assertTrue($gate->any(['edit', 'update'], new AccessGateTestDummy));
- }
- public function testAnyAbilityCheckPassesIfAtLeastOnePasses()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithMixedPermissions::class);
- $this->assertTrue($gate->any(['edit', 'update'], new AccessGateTestDummy));
- }
- public function testAnyAbilityCheckFailsIfNonePass()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithNoPermissions::class);
- $this->assertFalse($gate->any(['edit', 'update'], new AccessGateTestDummy));
- }
- public function testNoneAbilityCheckPassesIfAllFail()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithNoPermissions::class);
- $this->assertTrue($gate->none(['edit', 'update'], new AccessGateTestDummy));
- }
- public function testEveryAbilityCheckPassesIfAllPass()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithAllPermissions::class);
- $this->assertTrue($gate->check(['edit', 'update'], new AccessGateTestDummy));
- }
- public function testEveryAbilityCheckFailsIfAtLeastOneFails()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithMixedPermissions::class);
- $this->assertFalse($gate->check(['edit', 'update'], new AccessGateTestDummy));
- }
- public function testEveryAbilityCheckFailsIfNonePass()
- {
- $gate = $this->getBasicGate();
- $gate->policy(AccessGateTestDummy::class, AccessGateTestPolicyWithNoPermissions::class);
- $this->assertFalse($gate->check(['edit', 'update'], new AccessGateTestDummy));
- }
- /**
- * @dataProvider hasAbilitiesTestDataProvider
- *
- * @param array $abilitiesToSet
- * @param array|string $abilitiesToCheck
- * @param bool $expectedHasValue
- */
- public function testHasAbilities($abilitiesToSet, $abilitiesToCheck, $expectedHasValue)
- {
- $gate = $this->getBasicGate();
- $gate->resource('test', AccessGateTestResource::class, $abilitiesToSet);
- $this->assertEquals($expectedHasValue, $gate->has($abilitiesToCheck));
- }
- public function hasAbilitiesTestDataProvider()
- {
- $abilities = ['foo' => 'foo', 'bar' => 'bar'];
- $noAbilities = [];
- return [
- [$abilities, ['test.foo', 'test.bar'], true],
- [$abilities, ['test.bar', 'test.foo'], true],
- [$abilities, ['test.bar', 'test.foo', 'test.baz'], false],
- [$abilities, ['test.bar'], true],
- [$abilities, ['baz'], false],
- [$abilities, [''], false],
- [$abilities, [], true],
- [$abilities, 'test.bar', true],
- [$abilities, 'test.foo', true],
- [$abilities, '', false],
- [$noAbilities, '', false],
- [$noAbilities, [], true],
- ];
- }
- public function testClassesCanBeDefinedAsCallbacksUsingAtNotationForGuests()
- {
- $gate = new Gate(new Container, function () {
- //
- });
- $gate->define('foo', AccessGateTestClassForGuest::class.'@foo');
- $gate->define('obj_foo', [new AccessGateTestClassForGuest, 'foo']);
- $gate->define('static_foo', [AccessGateTestClassForGuest::class, 'staticFoo']);
- $gate->define('static_@foo', AccessGateTestClassForGuest::class.'@staticFoo');
- $gate->define('bar', AccessGateTestClassForGuest::class.'@bar');
- $gate->define('invokable', AccessGateTestGuestInvokableClass::class);
- $gate->define('nullable_invokable', AccessGateTestGuestNullableInvokable::class);
- $gate->define('absent_invokable', 'someAbsentClass');
- AccessGateTestClassForGuest::$calledMethod = '';
- $this->assertTrue($gate->check('foo'));
- $this->assertSame('foo was called', AccessGateTestClassForGuest::$calledMethod);
- $this->assertTrue($gate->check('static_foo'));
- $this->assertSame('static foo was invoked', AccessGateTestClassForGuest::$calledMethod);
- $this->assertTrue($gate->check('bar'));
- $this->assertSame('bar got invoked', AccessGateTestClassForGuest::$calledMethod);
- $this->assertTrue($gate->check('static_@foo'));
- $this->assertSame('static foo was invoked', AccessGateTestClassForGuest::$calledMethod);
- $this->assertTrue($gate->check('invokable'));
- $this->assertSame('__invoke was called', AccessGateTestGuestInvokableClass::$calledMethod);
- $this->assertTrue($gate->check('nullable_invokable'));
- $this->assertSame('Nullable __invoke was called', AccessGateTestGuestNullableInvokable::$calledMethod);
- $this->assertFalse($gate->check('absent_invokable'));
- }
- }
- class AccessGateTestClassForGuest
- {
- public static $calledMethod = null;
- public function foo($user = null)
- {
- static::$calledMethod = 'foo was called';
- return true;
- }
- public static function staticFoo($user = null)
- {
- static::$calledMethod = 'static foo was invoked';
- return true;
- }
- public function bar(?stdClass $user)
- {
- static::$calledMethod = 'bar got invoked';
- return true;
- }
- }
- class AccessGateTestStaticClass
- {
- public static function foo($user)
- {
- return $user->id === 1;
- }
- }
- class AccessGateTestClass
- {
- public function foo($user)
- {
- return $user->id === 1;
- }
- }
- class AccessGateTestInvokableClass
- {
- public function __invoke($user)
- {
- return $user->id === 1;
- }
- }
- class AccessGateTestGuestInvokableClass
- {
- public static $calledMethod = null;
- public function __invoke($user = null)
- {
- static::$calledMethod = '__invoke was called';
- return true;
- }
- }
- class AccessGateTestGuestNullableInvokable
- {
- public static $calledMethod = null;
- public function __invoke(?stdClass $user)
- {
- static::$calledMethod = 'Nullable __invoke was called';
- return true;
- }
- }
- interface AccessGateTestDummyInterface
- {
- //
- }
- class AccessGateTestDummy implements AccessGateTestDummyInterface
- {
- //
- }
- class AccessGateTestSubDummy extends AccessGateTestDummy
- {
- //
- }
- class AccessGateTestPolicy
- {
- use HandlesAuthorization;
- public function createAny($user, $additional)
- {
- return $additional;
- }
- public function create($user)
- {
- return $user->isAdmin ? $this->allow() : $this->deny('You are not an admin.');
- }
- public function updateAny($user, AccessGateTestDummy $dummy)
- {
- return ! $user->isAdmin;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return ! $user->isAdmin;
- }
- public function updateDash($user, AccessGateTestDummy $dummy)
- {
- return $user instanceof stdClass;
- }
- }
- class AccessGateTestPolicyWithBefore
- {
- public function before($user, $ability)
- {
- return true;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return false;
- }
- }
- class AccessGateTestResource
- {
- public function view($user)
- {
- return true;
- }
- public function create($user)
- {
- return true;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- public function delete($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- }
- class AccessGateTestCustomResource
- {
- public function foo($user)
- {
- return true;
- }
- public function bar($user)
- {
- return true;
- }
- }
- class AccessGateTestPolicyWithMixedPermissions
- {
- public function edit($user, AccessGateTestDummy $dummy)
- {
- return false;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- }
- class AccessGateTestPolicyWithNoPermissions
- {
- public function edit($user, AccessGateTestDummy $dummy)
- {
- return false;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return false;
- }
- }
- class AccessGateTestPolicyWithAllPermissions
- {
- public function edit($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- }
- class AccessGateTestPolicyThatAllowsGuests
- {
- public function before(?stdClass $user)
- {
- $_SERVER['__laravel.testBefore'] = true;
- }
- public function edit(?stdClass $user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- }
- class AccessGateTestPolicyWithNonGuestBefore
- {
- public function before(stdClass $user)
- {
- $_SERVER['__laravel.testBefore'] = true;
- }
- public function edit(?stdClass $user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- public function update($user, AccessGateTestDummy $dummy)
- {
- return true;
- }
- }
- class AccessGateTestBeforeCallback
- {
- public function allowEverything($user = null)
- {
- return true;
- }
- public static function allowEverythingStatically($user = null)
- {
- return true;
- }
- }
- class AccessGateTestPolicyWithCode
- {
- use HandlesAuthorization;
- public function view($user)
- {
- if (! $user->isAdmin) {
- return $this->deny('Not allowed to view as it is not published.', 'unpublished');
- }
- return true;
- }
- }
- class AccessGateTestPolicyWithDeniedResponseObject
- {
- public function create()
- {
- return Response::deny('Not allowed.', 'some_code');
- }
- }
- class AccessGateTestPolicyThrowingAuthorizationException
- {
- public function create()
- {
- throw new AuthorizationException('Not allowed.', 'some_code');
- }
- }
|