diff options
Diffstat (limited to 'lib/gitlab/graphql')
-rw-r--r-- | lib/gitlab/graphql/authorize.rb | 9 | ||||
-rw-r--r-- | lib/gitlab/graphql/authorize/authorize_resource.rb | 46 | ||||
-rw-r--r-- | lib/gitlab/graphql/errors.rb | 1 | ||||
-rw-r--r-- | lib/gitlab/graphql/mount_mutation.rb | 18 |
4 files changed, 73 insertions, 1 deletions
diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb index 04f25c53e49..93a903915b0 100644 --- a/lib/gitlab/graphql/authorize.rb +++ b/lib/gitlab/graphql/authorize.rb @@ -10,7 +10,14 @@ module Gitlab end def required_permissions - @required_permissions ||= [] + # If the `#authorize` call is used on multiple classes, we add the + # permissions specified on a subclass, to the ones that were specified + # on it's superclass. + @required_permissions ||= if self.respond_to?(:superclass) && superclass.respond_to?(:required_permissions) + superclass.required_permissions.dup + else + [] + end end def authorize(*permissions) diff --git a/lib/gitlab/graphql/authorize/authorize_resource.rb b/lib/gitlab/graphql/authorize/authorize_resource.rb new file mode 100644 index 00000000000..40895686a8a --- /dev/null +++ b/lib/gitlab/graphql/authorize/authorize_resource.rb @@ -0,0 +1,46 @@ +module Gitlab + module Graphql + module Authorize + module AuthorizeResource + extend ActiveSupport::Concern + + included do + extend Gitlab::Graphql::Authorize + end + + def find_object(*args) + raise NotImplementedError, "Implement #find_object in #{self.class.name}" + end + + def authorized_find(*args) + object = find_object(*args) + + object if authorized?(object) + end + + def authorized_find!(*args) + object = find_object(*args) + authorize!(object) + + object + end + + def authorize!(object) + unless authorized?(object) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, + "The resource that you are attempting to access does not exist or you don't have permission to perform this action" + end + end + + def authorized?(object) + self.class.required_permissions.all? do |ability| + # The actions could be performed across multiple objects. In which + # case the current user is common, and we could benefit from the + # caching in `DeclarativePolicy`. + Ability.allowed?(current_user, ability, object, scope: :user) + end + end + end + end + end +end diff --git a/lib/gitlab/graphql/errors.rb b/lib/gitlab/graphql/errors.rb index 1d8e8307ab9..f8c7ec24be1 100644 --- a/lib/gitlab/graphql/errors.rb +++ b/lib/gitlab/graphql/errors.rb @@ -3,6 +3,7 @@ module Gitlab module Errors BaseError = Class.new(GraphQL::ExecutionError) ArgumentError = Class.new(BaseError) + ResourceNotAvailable = Class.new(BaseError) end end end diff --git a/lib/gitlab/graphql/mount_mutation.rb b/lib/gitlab/graphql/mount_mutation.rb new file mode 100644 index 00000000000..8cab84d7a5f --- /dev/null +++ b/lib/gitlab/graphql/mount_mutation.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Gitlab + module Graphql + module MountMutation + extend ActiveSupport::Concern + + module ClassMethods + def mount_mutation(mutation_class) + # Using an underscored field name symbol will make `graphql-ruby` + # standardize the field name + field mutation_class.graphql_name.underscore.to_sym, + mutation: mutation_class + end + end + end + end +end |