Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2018-05-23 10:55:14 +0300
committerBob Van Landuyt <bob@vanlanduyt.co>2018-06-06 11:58:54 +0300
commit9b65d4bb417fb4939289eab94487c894f0a62db6 (patch)
tree1f97b9a1bd0d722a3c3ff4e89ec13bdb7a3aec00 /lib
parentc443133e779c4c508b9c6429dd4ba623d64f03f1 (diff)
Initial setup GraphQL using graphql-ruby 1.8
- All definitions have been replaced by classes: http://graphql-ruby.org/schema/class_based_api.html - Authorization & Presentation have been refactored to work in the class based system - Loaders have been replaced by resolvers - Times are now coersed as ISO 8601
Diffstat (limited to 'lib')
-rw-r--r--lib/constraints/feature_constrainer.rb13
-rw-r--r--lib/gitlab/graphql/authorize.rb52
-rw-r--r--lib/gitlab/graphql/authorize/instrumentation.rb45
-rw-r--r--lib/gitlab/graphql/present.rb36
-rw-r--r--lib/gitlab/graphql/present/instrumentation.rb25
5 files changed, 102 insertions, 69 deletions
diff --git a/lib/constraints/feature_constrainer.rb b/lib/constraints/feature_constrainer.rb
new file mode 100644
index 00000000000..05d48b0f25a
--- /dev/null
+++ b/lib/constraints/feature_constrainer.rb
@@ -0,0 +1,13 @@
+module Constraints
+ class FeatureConstrainer
+ attr_reader :feature
+
+ def initialize(feature)
+ @feature = feature
+ end
+
+ def matches?(_request)
+ Feature.enabled?(feature)
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb
index 6f9de8c38b7..04f25c53e49 100644
--- a/lib/gitlab/graphql/authorize.rb
+++ b/lib/gitlab/graphql/authorize.rb
@@ -2,55 +2,19 @@ module Gitlab
module Graphql
# Allow fields to declare permissions their objects must have. The field
# will be set to nil unless all required permissions are present.
- class Authorize
- SETUP_PROC = -> (type, *args) do
- type.metadata[:authorize] ||= []
- type.metadata[:authorize].concat(args)
- end
-
- INSTRUMENT_PROC = -> (schema) do
- schema.instrument(:field, new)
- end
+ module Authorize
+ extend ActiveSupport::Concern
- def self.register!
- GraphQL::Schema.accepts_definitions(enable_authorization: INSTRUMENT_PROC)
- GraphQL::Field.accepts_definitions(authorize: SETUP_PROC)
+ def self.use(schema_definition)
+ schema_definition.instrument(:field, Instrumentation.new)
end
- # Replace the resolver for the field with one that will only return the
- # resolved object if the permissions check is successful.
- #
- # Collections are not supported. Apply permissions checks for those at the
- # database level instead, to avoid loading superfluous data from the DB
- def instrument(_type, field)
- return field unless field.metadata.include?(:authorize)
-
- old_resolver = field.resolve_proc
-
- new_resolver = -> (obj, args, ctx) do
- resolved_obj = old_resolver.call(obj, args, ctx)
- checker = build_checker(ctx[:current_user], field.metadata[:authorize])
-
- if resolved_obj.respond_to?(:then)
- resolved_obj.then(&checker)
- else
- checker.call(resolved_obj)
- end
- end
-
- field.redefine do
- resolve(new_resolver)
- end
+ def required_permissions
+ @required_permissions ||= []
end
- private
-
- def build_checker(current_user, abilities)
- proc do |obj|
- # Load the elements if they weren't loaded by BatchLoader yet
- obj = obj.sync if obj.respond_to?(:sync)
- obj if abilities.all? { |ability| Ability.allowed?(current_user, ability, obj) }
- end
+ def authorize(*permissions)
+ required_permissions.concat(permissions)
end
end
end
diff --git a/lib/gitlab/graphql/authorize/instrumentation.rb b/lib/gitlab/graphql/authorize/instrumentation.rb
new file mode 100644
index 00000000000..6cb8e617f62
--- /dev/null
+++ b/lib/gitlab/graphql/authorize/instrumentation.rb
@@ -0,0 +1,45 @@
+module Gitlab
+ module Graphql
+ module Authorize
+ class Instrumentation
+ # Replace the resolver for the field with one that will only return the
+ # resolved object if the permissions check is successful.
+ #
+ # Collections are not supported. Apply permissions checks for those at the
+ # database level instead, to avoid loading superfluous data from the DB
+ def instrument(_type, field)
+ field_definition = field.metadata[:type_class]
+ return field unless field_definition.respond_to?(:required_permissions)
+ return field if field_definition.required_permissions.empty?
+
+ old_resolver = field.resolve_proc
+
+ new_resolver = -> (obj, args, ctx) do
+ resolved_obj = old_resolver.call(obj, args, ctx)
+ checker = build_checker(ctx[:current_user], field_definition.required_permissions)
+
+ if resolved_obj.respond_to?(:then)
+ resolved_obj.then(&checker)
+ else
+ checker.call(resolved_obj)
+ end
+ end
+
+ field.redefine do
+ resolve(new_resolver)
+ end
+ end
+
+ private
+
+ def build_checker(current_user, abilities)
+ proc do |obj|
+ # Load the elements if they weren't loaded by BatchLoader yet
+ obj = obj.sync if obj.respond_to?(:sync)
+ obj if abilities.all? { |ability| Ability.allowed?(current_user, ability, obj) }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/present.rb b/lib/gitlab/graphql/present.rb
index b060692b334..2c7b64f1be9 100644
--- a/lib/gitlab/graphql/present.rb
+++ b/lib/gitlab/graphql/present.rb
@@ -1,34 +1,20 @@
module Gitlab
module Graphql
- class Present
- PRESENT_USING = -> (type, presenter_class, *args) do
- type.metadata[:presenter_class] = presenter_class
- end
-
- INSTRUMENT_PROC = -> (schema) do
- schema.instrument(:field, new)
- end
-
- def self.register!
- GraphQL::Schema.accepts_definitions(enable_presenting: INSTRUMENT_PROC)
- GraphQL::ObjectType.accepts_definitions(present_using: PRESENT_USING)
- end
-
- def instrument(type, field)
- return field unless type.metadata[:presenter_class]
-
- old_resolver = field.resolve_proc
-
- resolve_with_presenter = -> (obj, args, context) do
- presenter = type.metadata[:presenter_class].new(obj, **context.to_h)
-
- old_resolver.call(presenter, args, context)
+ module Present
+ extend ActiveSupport::Concern
+ prepended do
+ def self.present_using(kls)
+ @presenter_class = kls
end
- field.redefine do
- resolve(resolve_with_presenter)
+ def self.presenter_class
+ @presenter_class
end
end
+
+ def self.use(schema_definition)
+ schema_definition.instrument(:field, Instrumentation.new)
+ end
end
end
end
diff --git a/lib/gitlab/graphql/present/instrumentation.rb b/lib/gitlab/graphql/present/instrumentation.rb
new file mode 100644
index 00000000000..1688262974b
--- /dev/null
+++ b/lib/gitlab/graphql/present/instrumentation.rb
@@ -0,0 +1,25 @@
+module Gitlab
+ module Graphql
+ module Present
+ class Instrumentation
+ def instrument(type, field)
+ presented_in = field.metadata[:type_class].owner
+ return field unless presented_in.respond_to?(:presenter_class)
+ return field unless presented_in.presenter_class
+
+ old_resolver = field.resolve_proc
+
+ resolve_with_presenter = -> (presented_type, args, context) do
+ object = presented_type.object
+ presenter = presented_in.presenter_class.new(object, **context.to_h)
+ old_resolver.call(presenter, args, context)
+ end
+
+ field.redefine do
+ resolve(resolve_with_presenter)
+ end
+ end
+ end
+ end
+ end
+end