Handle record with preauthorize?
marlosirapuan opened this issue · 2 comments
Hi, @palkan. There is a way to get record or the ID of the record to handle before to execute an action without "preauthorize"?
I do something like this:
Mutation type:
field :update_user,
mutation: Mutations::Users::UpdateUserMutation,
authorize: { to: :update?, with: Mutations::UserPolicy }
Mutation:
class UpdateUserMutation < BaseMutation
argument :id, String, required: true
argument :data, Types::Inputs::User::UpdateUser, required: true
type Types::Data::User
def resolve(id:, data:)
UserService.new.save(id, data)
end
Policy:
module Mutations
class UserPolicy < ApplicationPolicy
def update?
user.admin? || own?
end
private
def own?
record.id == user.id
end
end
end
That way I get "not authorized", but it still performs the service action even if not authorized. If I put "preauthorize" i can't get the "record" to handle.. 🤔
I would need something to handle the record and stop the execution of resolve if it was not authorized. Is it possible?
I would need something to handle the record and stop the execution of resolve if it was not authorized
You can do this by calling authorize!
explicitly in your resolve
method:
def resolve(id:, data:)
user = User.find(id)
authorize! user, to: :update?
UserService.new.save(user, data)
end
That couldn't be achieved with neither authorize
nor preauthorize
because:
authorize
uses the resolved value (the return value ofresolve
method) as its authorization object, and, as you noticed, applies authorization after the mutation is executed- the idea of
preauthorize
is to perform authorization before field resolution (and without any object); you can only rely on the field name here.
We do not have authorize: ...
support for argument fields yet (see #24 for discussion), but that's what else you can do if you'd like to move authorization to schema definition, not resolving:
class UpdateUserMutation < BaseMutation
argument :id, String, required: true, as: :user, prepare: ->(id, ctx) {
User.find(id).tap do |user|
# context must be passed explicitly in this case
authorize! user, to: :update?, context: {user: ctx[:current_user]}
end
}
def resolve(user:, data:)
UserService.new.save(user, data)
end
end
hmm.. i got it. Thank you! 👍