Rajska.QueryScopeAuthorization (Rajska v1.3.2) View Source

Absinthe middleware to perform query scoping.

Usage

Create your Authorization module and add it and QueryAuthorization to your Absinthe.Schema. Since Scope Authorization middleware must be used with Query Authorization, it is automatically called when adding the former. Then set the scoped module and argument field:

  mutation do
    field :create_user, :user do
      arg :params, non_null(:user_params)

      # all does not require scoping, since it means anyone can execute this query, even without being logged in.
      middleware Rajska.QueryAuthorization, permit: :all
      resolve &AccountsResolver.create_user/2
    end

    field :update_user, :user do
      arg :id, non_null(:integer)
      arg :params, non_null(:user_params)

      middleware Rajska.QueryAuthorization, [permit: :user, scope: User] # same as [permit: :user, scope: User, args: :id]
      resolve &AccountsResolver.update_user/2
    end

    field :delete_user, :user do
      arg :user_id, non_null(:integer)

      # Providing a map for args is useful to map query argument to struct field.
      middleware Rajska.QueryAuthorization, [permit: [:user, :manager], scope: User, args: %{id: :user_id}]
      resolve &AccountsResolver.delete_user/2
    end

    input_object :user_params do
      field :id, non_null(:integer)
    end

    field :accept_user, :user do
      arg :params, non_null(:user_params)

      middleware Rajska.QueryAuthorization, [
        permit: :user,
        scope: User,
        args: %{id: [:params, :id]},
        rule: :accept_user
      ]
      resolve &AccountsResolver.invite_user/2
    end
  end

In the above example, :all and :admin permissions don't require the :scope keyword, as defined in the Rajska.Authorization.not_scoped_roles/0 function, but you can modify this behavior by overriding it.

Options

All the following options are sent to Rajska.Authorization.has_user_access?/3:

  • :scope
  • :args
    • %{user_id: [:params, :id]}: where user_id is the scoped field and id is an argument nested inside the params argument. This form also accepts a function in the array (the same way as described in the Kernel.get_in/2). This way, we can also use %{user_id: [:params, Access.all(), :id]} and for an input arg like params: [%{id: 1}, %{id: 2}], the builded struct will have the value %User{user_id: [1, 2]}.
    • :id: this is the same as %{id: :id}, where :id is both the query argument and the scoped field that will be passed to Rajska.Authorization.has_user_access?/3
    • [:code, :user_group_id]: this is the same as %{code: :code, user_group_id: :user_group_id}, where code and user_group_id are both query arguments and scoped fields.
  • :optional (optional) - when set to true the arguments are optional, so if no argument is provided, the query will be authorized. Defaults to false.
  • :rule (optional) - allows the same struct to have different rules. See Rajska.Authorization for rule default settings.

Link to this section Summary

Link to this section Functions

Callback implementation for Absinthe.Middleware.call/2.

Link to this function

get_scoped_struct_field(arguments_source, arg, optional, query_name)

View Source
Link to this function

scope_user!(resolution, config)

View Source