Skip to content

Instantly share code, notes, and snippets.

@vickeryj
Created March 6, 2018 20:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vickeryj/7ae49e9093a4ce74e02616eea67659a1 to your computer and use it in GitHub Desktop.
Save vickeryj/7ae49e9093a4ce74e02616eea67659a1 to your computer and use it in GitHub Desktop.
role based field authorization
GraphQL::Field.accepts_definitions(
required_role: GraphQL::Define.assign_metadata_key(:required_role),
unauthorized_value: GraphQL::Define.assign_metadata_key(:unauthorized_value)
)
class RoleBasedAuthorization
def instrument(_type, field)
if field.metadata[:required_role]
old_resolve_proc = field.resolve_proc
new_resolve_proc = ->(obj, args, ctx) do
if user_authorized?(ctx[:current_user], field)
# TODO: Re-add this when Apollo Client version 2 is released and implemented
# which supports receiving both data and errors simultaneously
# ctx.add_error GraphQL::ExecutionError.new("Required role not found: #{required_roles.join(', ')}")
field.metadata[:unauthorized_value]
else
old_resolve_proc.call(obj, args, ctx)
end
end
field.redefine { resolve(new_resolve_proc) }
else
field
end
end
private
def user_authorized?(user, field)
current_roles = user&.roles&.map(&:title)
required_roles = field.metadata[:required_role].is_a?(Array) ? field.metadata[:required_role] : [field.metadata[:required_role]]
!current_roles || (current_roles & required_roles).empty?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment