Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@can with injectArgs: true doesn't inject args passed as variables #2456

Closed
SlyDave opened this issue Oct 6, 2023 · 3 comments
Closed

@can with injectArgs: true doesn't inject args passed as variables #2456

SlyDave opened this issue Oct 6, 2023 · 3 comments
Labels
needs reproduction Failing test case needed

Comments

@SlyDave
Copy link

SlyDave commented Oct 6, 2023

If you use injectArgs on @can, it doesn't pass in arguments that are populated via variables:

Model:

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Test extends Model {
    protected $table = 'test';
    protected $fillable = ['foo']
}

Policy:

class TestPolicy
{
    public function create(User $user, array $injectedArgs): bool
    {
        return $injectedArgs['input']['foo'] === "bar";
    }
}

graphQL schema:

Input TestInput {
    foo: String!
}

type LeaveMutations {
    test(input: TestInput): TestPayload! @can(ability: "create", model: "Test", injectArgs: true)
}

graphQL Query:

mutation test ($input: TestInput) {
   input: $input
}

{ "input": { foo: "bar" } }

Result:

Internal server error
"Undefined array key "input"", file: /var/app/current/app/Policies/TestPolicy.php

When dumping out $injectedArgs, it returns an empty array, when the expected is

["input" => ["foo": "bar"]]

From my understanding, this makes it impossible to use variables and @can with injectedArgs
Lighthouse Version 6.22.0

@SlyDave SlyDave changed the title @can injectArgs doesn't injected args passed as variables @can with injectArgs: true doesn't inject args passed as variables Oct 6, 2023
@spawnia spawnia added the needs reproduction Failing test case needed label Oct 6, 2023
@spawnia
Copy link
Collaborator

spawnia commented Oct 6, 2023

There is a test for this, perhaps you can add a failing test case for your scenario?

public function testInjectArgsPassesClientArgumentToPolicy(): void
{
$this->be(new User());
$this->mockResolver(fn (): User => $this->resolveUser());
$this->schema = /** @lang GraphQL */ '
type Query {
user(foo: String): User!
@can(ability: "injectArgs", injectArgs: true)
@mock
}
type User {
name: String
}
';
$this->graphQL(/** @lang GraphQL */ '
{
user(foo: "bar") {
name
}
}
')->assertJson([
'data' => [
'user' => [
'name' => 'foo',
],
],
]);
}

@SlyDave
Copy link
Author

SlyDave commented Oct 6, 2023

Thanks for the quick response, that test doesn't cover the case, as it doesn't use variables to pass in the arguments.

Once I am back in the office on Monday I'll attempt to put together something.

But generally speaking, it looks something like the following, for a query using Type rather than a mutation using Input:

     public function testInjectArgsPassesClientArgumentToPolicy(): void 
     { 
         $this->be(new User()); 
  
         $this->mockResolver(fn (): User => $this->resolveUser()); 
  
         $this->schema = /** @lang GraphQL */ ' 
         type Query { 
             user(foo: String): User! 
                 @can(ability: "injectArgs", injectArgs: true) 
                 @mock 
         } 
  
         type User { 
             name: String 
         } 

         type Foo { # Here we define the type to use as a variable.
             foo: String
         }
         '; 
  
         $this->graphQL(/** @lang GraphQL */ ' 
        query getUser($foo: Foo) {  # Here we set the query operation and tell it use to our Foo type as a variable.
             user(foo: $foo) { 
                 name 
             } 
         } 
         ', ['foo' => 'bar'] # Here we pass the variables into the graphQL helper
        )->assertJson([ 
             'data' => [ 
                 'user' => [ 
                     'name' => 'foo', 
                 ], 
             ], 
         ]); 
     } 

@SlyDave
Copy link
Author

SlyDave commented Oct 9, 2023

The actual test is:

    public function testInjectArgsPassesClientVariablesToPolicy(): void
    {
        $this->be(new User());

        $this->mockResolver(fn (): User => $this->resolveUser());

        $this->schema = /** @lang GraphQL */ '
         type Query {
             user(foo: String): User!
                 @can(ability: "injectArgs", injectArgs: true)
                 @mock
         }

         type User {
             name: String
         }
         ';

        $this->graphQL(/** @lang GraphQL */ '
        query getUser($foo: String) { 
             user(foo: $foo) {
                 name
             }
         }
         ', ['foo' => 'bar']
        )->assertJson([
            'data' => [
                'user' => [
                    'name' => 'foo',
                ],
            ],
        ]);
    }

and what would you know, it passes.

OK (1 test, 2 assertions)

Because I am an idiot. and I am using @spread on the Input so the outer associate key doesn't exist.

Sorry for wasting your time.

@SlyDave SlyDave closed this as completed Oct 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs reproduction Failing test case needed
Projects
None yet
Development

No branches or pull requests

2 participants