ibrain-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +75 -0
  4. data/Rakefile +7 -0
  5. data/app/controllers/concerns/ibrain_errors.rb +23 -0
  6. data/app/controllers/concerns/ibrain_handler.rb +42 -0
  7. data/app/controllers/ibrain/base_controller.rb +28 -0
  8. data/app/controllers/ibrain/graphql_controller.rb +55 -0
  9. data/app/graphql/ibrain/base_schema.rb +52 -0
  10. data/app/graphql/ibrain/extentions/default_value.rb +15 -0
  11. data/app/graphql/ibrain/interfaces/base_interface.rb +5 -0
  12. data/app/graphql/ibrain/interfaces/person_interface.rb +15 -0
  13. data/app/graphql/ibrain/interfaces/record_interface.rb +10 -0
  14. data/app/graphql/ibrain/lazy/base.rb +8 -0
  15. data/app/graphql/ibrain/loaders/association_loader.rb +61 -0
  16. data/app/graphql/ibrain/mutations/base_mutation.rb +35 -0
  17. data/app/graphql/ibrain/policies/base_policy.rb +45 -0
  18. data/app/graphql/ibrain/policies/graphql_policy.rb +8 -0
  19. data/app/graphql/ibrain/resolvers/base_aggregate.rb +9 -0
  20. data/app/graphql/ibrain/resolvers/base_resolver.rb +15 -0
  21. data/app/graphql/ibrain/types/aggregate_type.rb +9 -0
  22. data/app/graphql/ibrain/types/base_argument.rb +11 -0
  23. data/app/graphql/ibrain/types/base_connection.rb +16 -0
  24. data/app/graphql/ibrain/types/base_edge.rb +10 -0
  25. data/app/graphql/ibrain/types/base_enum.rb +8 -0
  26. data/app/graphql/ibrain/types/base_field.rb +15 -0
  27. data/app/graphql/ibrain/types/base_input_object.rb +9 -0
  28. data/app/graphql/ibrain/types/base_interface.rb +14 -0
  29. data/app/graphql/ibrain/types/base_node.rb +13 -0
  30. data/app/graphql/ibrain/types/base_object.rb +14 -0
  31. data/app/graphql/ibrain/types/base_query_type.rb +14 -0
  32. data/app/graphql/ibrain/types/base_scalar.rb +8 -0
  33. data/app/graphql/ibrain/types/base_union.rb +10 -0
  34. data/app/graphql/ibrain/types/filter_type.rb +8 -0
  35. data/app/graphql/ibrain/types/node_type.rb +11 -0
  36. data/app/graphql/ibrain/util/field_combiner.rb +13 -0
  37. data/app/graphql/ibrain/util/query_combiner.rb +13 -0
  38. data/app/graphql/mutations/insert_user.rb +18 -0
  39. data/app/models/ibrain/ability.rb +51 -0
  40. data/app/models/ibrain/application_record.rb +7 -0
  41. data/app/models/ibrain/base.rb +47 -0
  42. data/app/models/ibrain/concerns/ransackable_attributes.rb +22 -0
  43. data/app/models/ibrain/concerns/soft_deletable.rb +16 -0
  44. data/app/models/ibrain/concerns/user_api_authentication.rb +23 -0
  45. data/app/models/ibrain/concerns/user_methods.rb +25 -0
  46. data/app/models/ibrain/legacy_user.rb +19 -0
  47. data/app/models/ibrain/role.rb +14 -0
  48. data/app/models/ibrain/role_user.rb +18 -0
  49. data/config/initializers/friendly_id.rb +87 -0
  50. data/config/locales/en.yml +10 -0
  51. data/config/locales/jp.yml +10 -0
  52. data/config/locales/vi.yml +10 -0
  53. data/config/routes.rb +9 -0
  54. data/lib/generators/ibrain/graphql/core.rb +75 -0
  55. data/lib/generators/ibrain/graphql/mutation_generator.rb +58 -0
  56. data/lib/generators/ibrain/graphql/object_generator.rb +80 -0
  57. data/lib/generators/ibrain/graphql/resolver_generator.rb +33 -0
  58. data/lib/generators/ibrain/graphql/resolvers_generator.rb +59 -0
  59. data/lib/generators/ibrain/graphql/templates/aggregate.erb +10 -0
  60. data/lib/generators/ibrain/graphql/templates/mutation.erb +16 -0
  61. data/lib/generators/ibrain/graphql/templates/object.erb +11 -0
  62. data/lib/generators/ibrain/graphql/templates/resolver.erb +15 -0
  63. data/lib/generators/ibrain/graphql/templates/resolvers.erb +13 -0
  64. data/lib/generators/ibrain/graphql/type_generator.rb +101 -0
  65. data/lib/generators/ibrain/install/install_generator.rb +189 -0
  66. data/lib/generators/ibrain/install/templates/config/database.tt +23 -0
  67. data/lib/generators/ibrain/install/templates/config/initializers/cors.tt +25 -0
  68. data/lib/generators/ibrain/install/templates/config/initializers/ibrain.rb.tt +55 -0
  69. data/lib/generators/ibrain/install/templates/config/puma.tt +43 -0
  70. data/lib/generators/ibrain/install/templates/graphql/app_schema.rb.tt +4 -0
  71. data/lib/generators/ibrain/install/templates/graphql/types/mutation_type.rb.tt +10 -0
  72. data/lib/generators/ibrain/install/templates/graphql/types/query_type.rb.tt +13 -0
  73. data/lib/ibrain/app_configuration.rb +66 -0
  74. data/lib/ibrain/config.rb +5 -0
  75. data/lib/ibrain/core/class_constantizer.rb +41 -0
  76. data/lib/ibrain/core/controller_helpers/auth.rb +64 -0
  77. data/lib/ibrain/core/controller_helpers/current_host.rb +17 -0
  78. data/lib/ibrain/core/controller_helpers/response.rb +52 -0
  79. data/lib/ibrain/core/controller_helpers/strong_parameters.rb +21 -0
  80. data/lib/ibrain/core/engine.rb +16 -0
  81. data/lib/ibrain/core/environment.rb +17 -0
  82. data/lib/ibrain/core/environment_extension.rb +27 -0
  83. data/lib/ibrain/core/role_configuration.rb +72 -0
  84. data/lib/ibrain/core/validators/email.rb +23 -0
  85. data/lib/ibrain/core/version.rb +17 -0
  86. data/lib/ibrain/core/versioned_value.rb +73 -0
  87. data/lib/ibrain/core.rb +86 -0
  88. data/lib/ibrain/encryptor.rb +27 -0
  89. data/lib/ibrain/i18n.rb +17 -0
  90. data/lib/ibrain/logger.rb +23 -0
  91. data/lib/ibrain/permission_sets/base.rb +33 -0
  92. data/lib/ibrain/permission_sets/super_user.rb +11 -0
  93. data/lib/ibrain/permission_sets.rb +4 -0
  94. data/lib/ibrain/permitted_attributes.rb +26 -0
  95. data/lib/ibrain/preferences/configuration.rb +170 -0
  96. data/lib/ibrain/preferences/preferable.rb +183 -0
  97. data/lib/ibrain/preferences/preferable_class_methods.rb +140 -0
  98. data/lib/ibrain/user_class_handle.rb +29 -0
  99. data/lib/ibrain_core.rb +3 -0
  100. data/lib/tasks/ibrain/auto_annotate_models.rake +61 -0
  101. data/lib/tasks/ibrain/core_tasks.rake +5 -0
  102. data/lib/tasks/ibrain/ridgepole.rake +37 -0
  103. metadata +293 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e306b2238fba539d079c52bbb0c6b6bb2ff1092e9f950c4c6fd85065b2325fa3
4
+ data.tar.gz: d9ae60e6b5769f14339bcdba97ed42538523c34aa9d382454496d0ac49f1d320
5
+ SHA512:
6
+ metadata.gz: 3ae2d1c79c5931769a432d6532f104c88245afb7df5dc3d0af557b3496b215548cbae686203f229c7d5bac7226000e39caad0ffe42fae0361fe19b1ca64f38df
7
+ data.tar.gz: 6b34268ff18f1eb0daafcd47d2b7a32f48360370ddc7367c18d5399048b69ca391758b4e0fdaa137a3a6f9d73d7cf02c84d828fe000a0ba7911d99d934dabe7e
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 TODO: Write your name
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Ibrain::Core
2
+ This is core plugin for rails api project
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'ibrain-core'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install ibrain-core
22
+ ```
23
+
24
+ Please install plugin after install this gem
25
+ ```bash
26
+ $ bundle exec rails generate ibrain:install
27
+ ```
28
+ # Migration
29
+ Default migration engine is [ridgepole](https://github.com/ridgepole/ridgepole), using this command line to migrate database:
30
+ ```bash
31
+ bundle exec rails ridgpole:apply
32
+ ```
33
+ To use default migration plugin, please disable ridgepole
34
+ ```bash
35
+ bundle exec rails generate ibrain::install --with-ridgepole=false
36
+ ```
37
+ # GraphQL API
38
+ If you use graphql for rails please add this option when install plugin
39
+ ```bash
40
+ $ bundle exec rails generate ibrain::install --with-graphql
41
+ ```
42
+ To generate graphql type
43
+ ```bash
44
+ bundle exec rails generate ibrain:graphql:object user
45
+ ```
46
+ To generate graphql resolver single query to get user data
47
+ ```bash
48
+ bundle exec rails generate ibrain:graphql:resolver user --model=User
49
+ ```
50
+ To generate graphql resolvers query to get users list
51
+ ```bash
52
+ bundle exec rails generate ibrain:graphql:resolvers users --model=User
53
+ ```
54
+ For pagination please using aggregate body query, something like
55
+ ```
56
+ query users($offset: Int, $limit: Int, $filter: Filter) {
57
+ users(offset: $offset, limit: $limit, filter: $filter) {
58
+ id
59
+ first_name
60
+ }
61
+
62
+ users_aggregate(filter: $filter) {
63
+ total_count
64
+ }
65
+ }
66
+ ```
67
+ To generate graphql mutation to insert, update, delete user
68
+ ```bash
69
+ bundle exec rails generate ibrain:graphql:mutation insert_user --model=User
70
+ ```
71
+ ## Contributing
72
+ Contribution directions go here.
73
+
74
+ ## License
75
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+
5
+ load "rails/tasks/statistics.rake"
6
+
7
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IbrainErrors
4
+ extend ActiveSupport::Concern
5
+
6
+ class PermissionError < StandardError; end
7
+
8
+ class UnknownError < StandardError
9
+ def initialize(message)
10
+ super
11
+
12
+ @message = message
13
+ end
14
+
15
+ def details
16
+ message
17
+ end
18
+
19
+ private
20
+
21
+ attr_accessor :message
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IbrainHandler
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ rescue_from StandardError, with: :standard_handler
8
+ rescue_from ActionController::ParameterMissing, with: :parameter_handler
9
+ rescue_from ActiveRecord::RecordNotFound, with: :not_found_handler
10
+ rescue_from ActiveRecord::RecordInvalid, with: :bad_request_handler
11
+ rescue_from IbrainErrors::PermissionError, with: :permission_denied_handler
12
+ rescue_from IbrainErrors::UnknownError, with: :bad_request_handler
13
+ rescue_from ActionController::InvalidAuthenticityToken, with: :unauthorized_handler
14
+ rescue_from ActiveSupport::MessageVerifier::InvalidSignature, with: :unauthorized_handler
15
+ end
16
+
17
+ private
18
+
19
+ def standard_handler(errors)
20
+ render_json_error(errors, 500)
21
+ end
22
+
23
+ def bad_request_handler(errors)
24
+ render_json_error(errors, 400)
25
+ end
26
+
27
+ def parameter_handler(errors)
28
+ render_json_error(errors, 400)
29
+ end
30
+
31
+ def not_found_handler(errors)
32
+ render_json_error(errors, 404)
33
+ end
34
+
35
+ def permission_denied_handler(errors)
36
+ render_json_error(errors, 405)
37
+ end
38
+
39
+ def unauthorized_handler(errors)
40
+ render_json_error(errors, 401)
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ class BaseController < ActionController::API
5
+ include ActionController::Helpers
6
+ include Ibrain::Core::ControllerHelpers::Response
7
+ include Ibrain::Core::ControllerHelpers::StrongParameters
8
+ include Ibrain::Core::ControllerHelpers::CurrentHost
9
+ include Ibrain::Core::ControllerHelpers::Auth
10
+
11
+ include IbrainErrors
12
+ include IbrainHandler
13
+
14
+ protected
15
+
16
+ def operation_name
17
+ params[:operationName]
18
+ end
19
+
20
+ def skip_operations
21
+ []
22
+ end
23
+
24
+ def cryptor
25
+ Ibrain::Encryptor.new
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ class GraphqlController < Ibrain::BaseController
5
+ def execute
6
+ query, variables, operation_name = normalize_entity
7
+
8
+ result = schema.execute(
9
+ query,
10
+ variables: variables,
11
+ context: {
12
+ session: session,
13
+ current_user: current_ibrain_user
14
+ },
15
+ operation_name: operation_name
16
+ )
17
+
18
+ render_json_ok(result['data'], nil, result['errors'])
19
+ end
20
+
21
+ protected
22
+
23
+ def normalize_entity
24
+ query = params[:query]
25
+ operation_name = params[:operationName]
26
+ variables = prepare_variables(params[:variables])
27
+
28
+ [query, variables, operation_name]
29
+ end
30
+
31
+ # Handle variables in form data, JSON body, or a blank value
32
+ def prepare_variables(variables_param)
33
+ case variables_param
34
+ when String
35
+ if variables_param.present?
36
+ JSON.parse(variables_param) || {}
37
+ else
38
+ {}
39
+ end
40
+ when Hash
41
+ variables_param
42
+ when ActionController::Parameters
43
+ variables_param.to_unsafe_hash # GraphQLRuby will validate name and type of incoming variables.
44
+ when nil
45
+ {}
46
+ else
47
+ raise ArgumentError, "Unexpected parameter: #{variables_param}"
48
+ end
49
+ end
50
+
51
+ def schema
52
+ Ibrain::Config.graphql_schema.safe_constantize
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ class BaseSchema < ::GraphQL::Schema
5
+ use GraphQL::Batch
6
+
7
+ use GraphQL::Guard.new(
8
+ policy_object: ::Ibrain::Config.graphql_policy.safe_constantize,
9
+ not_authorized: ->(type, field) { GraphQL::ExecutionError.new("Not authorized to access #{type}.#{field}") }
10
+ )
11
+
12
+ # Union and Interface Resolution
13
+ def self.resolve_type(_abstract_type, _obj, _ctx)
14
+ # TODO: Implement this function
15
+ # to return the correct object type for `obj`
16
+ raise(GraphQL::RequiredImplementationMissingError)
17
+ end
18
+
19
+ # Relay-style Object Identification:
20
+
21
+ # Return a string UUID for `object`
22
+ def self.id_from_object(object, type_definition, query_ctx)
23
+ # Here's a simple implementation which:
24
+ # - joins the type name & object.id
25
+ # - encodes it with base64:
26
+ # GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
27
+ end
28
+
29
+ # Given a string UUID, find the object
30
+ def self.object_from_id(id, query_ctx)
31
+ # For example, to decode the UUIDs generated above:
32
+ # type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
33
+ #
34
+ # Then, based on `type_name` and `id`
35
+ # find an object in your application
36
+ # ...
37
+ end
38
+
39
+ def self.field(*args, camelize: false, **kwargs, &block)
40
+ # if camelize == false
41
+ # # Also make a camelized field:
42
+ # field(*args, camelize: false, **kwargs, &block)
43
+ # end
44
+ super
45
+ end
46
+
47
+ rescue_from(ActiveRecord::RecordNotFound) do |_err, _obj, _args, _ctx, field|
48
+ # Raise a graphql-friendly error with a custom message
49
+ raise GraphQL::ExecutionError, "#{field.type.unwrap.graphql_name} not found"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Extentions
5
+ class DefaultValue < GraphQL::Schema::FieldExtension
6
+ def after_resolve(value:, **_rest)
7
+ if value.nil?
8
+ options[:default_value]
9
+ else
10
+ value
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain::Interfaces::BaseInterface
4
+ include ::GraphQL::Schema::Interface
5
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain::Interfaces::PersonInterface
4
+ include Ibrain::Types::BaseInterface
5
+
6
+ description 'Person Interface'
7
+
8
+ field :first_name, String, null: true
9
+ field :last_name, String, null: true
10
+ field :full_name, String, null: true
11
+
12
+ def full_name
13
+ [object.try(:first_name), object.try(:last_name)].compact.join(' ')
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain::Interfaces::RecordInterface
4
+ include Ibrain::Types::BaseInterface
5
+
6
+ description 'Common Interface'
7
+
8
+ field :created_at, ::GraphQL::Types::ISO8601DateTime, null: false
9
+ field :updated_at, ::GraphQL::Types::ISO8601DateTime, null: false
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Lazy
5
+ class Base < GraphQL::Function
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ref: https://zenn.dev/necocoa/articles/setup-graphql-batch
4
+
5
+ module Ibrain
6
+ module Loaders
7
+ class AssociationLoader < GraphQL::Batch::Loader
8
+ def self.validate(model, association_name)
9
+ new(model, association_name)
10
+ nil
11
+ end
12
+
13
+ def initialize(model, association_name)
14
+ super()
15
+ @model = model
16
+ @association_name = association_name
17
+ validate
18
+ end
19
+
20
+ def load(record)
21
+ unless record.is_a?(@model)
22
+ raise TypeError,
23
+ "#{@model} loader can't load association for #{record.class}"
24
+ end
25
+ return Promise.resolve(read_association(record)) if association_loaded?(record)
26
+
27
+ super
28
+ end
29
+
30
+ # We want to load the associations on all records, even if they have the same id
31
+ def cache_key(record)
32
+ record.object_id
33
+ end
34
+
35
+ def perform(records)
36
+ preload_association(records)
37
+ records.each { |record| fulfill(record, read_association(record)) }
38
+ end
39
+
40
+ private
41
+
42
+ def validate
43
+ return if @model.reflect_on_association(@association_name)
44
+
45
+ raise ArgumentError, "No association #{@association_name} on #{@model}"
46
+ end
47
+
48
+ def preload_association(records)
49
+ ::ActiveRecord::Associations::Preloader.new.preload(records, @association_name)
50
+ end
51
+
52
+ def read_association(record)
53
+ record.public_send(@association_name)
54
+ end
55
+
56
+ def association_loaded?(record)
57
+ record.association(@association_name).loaded?
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Mutations
5
+ class BaseMutation < GraphQL::Schema::RelayClassicMutation
6
+ argument_class Types::BaseArgument
7
+ field_class Types::BaseField
8
+ input_object_class Types::BaseInputObject
9
+ object_class Types::BaseObject
10
+
11
+ argument :attribute, Types::AttributeType, required: false
12
+ argument :attributes, [Types::AttributeType], required: false
13
+
14
+ def resolve(args)
15
+ @params = ::ActionController::Parameters.new(args)
16
+ end
17
+
18
+ protected
19
+
20
+ attr_reader :params
21
+
22
+ def upload_permitted
23
+ %i[content_type headers original_filename tempfile]
24
+ end
25
+
26
+ def cryptor
27
+ ::Ibrain::Encryptor.new
28
+ end
29
+
30
+ def current_user
31
+ context[:current_user]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Policies
5
+ class BasePolicy
6
+ IBRAIN_QUERY_RULES = {
7
+ '*': {
8
+ guard: ->(_obj, _args, _ctx) { true }
9
+ }
10
+ }
11
+
12
+ IBRAIN_MUTATION_RULES = {
13
+ '*': {
14
+ guard: ->(_obj, _args, ctx) { roles.include?(ctx[:current_user].try(:role)) }
15
+ }
16
+ }
17
+
18
+ RULES = {
19
+ 'Query' => IBRAIN_QUERY_RULES,
20
+ 'Mutation' => IBRAIN_MUTATION_RULES
21
+ }.freeze
22
+
23
+ class << self
24
+ def roles
25
+ Ibrain::Config.ibrain_roles
26
+ end
27
+
28
+ def has_permission?(current_user, resource)
29
+ return false if current_user.blank?
30
+ return true if current_user.super_admin?
31
+
32
+ current_user.try(:scope).to_s.split(',').include?(resource)
33
+ end
34
+
35
+ def guard(type, field)
36
+ RULES.dig(type.name, field, :guard)
37
+ end
38
+
39
+ def not_authorized_handler(type, field)
40
+ RULES.dig(type, field, :not_authorized) || RULES.dig(type, :*, :not_authorized)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Policies
5
+ class GraphqlPolicy < BasePolicy
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Resolvers
5
+ class BaseAggregate < BaseResolver
6
+ type Ibrain::Types::AggregateType.connection_type, null: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Resolvers
5
+ class BaseResolver < GraphQL::Schema::Resolver
6
+ argument :filter, Ibrain::Types::FilterType, required: false, default_value: nil
7
+ argument :offset, Int, required: false, default_value: 0
8
+ argument :limit, Int, required: false, default_value: 10
9
+
10
+ def current_user
11
+ context.fetch(:current_user)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class AggregateType < BaseObject
6
+ field :total_count, Int, null: false, default_value: 0
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class BaseArgument < GraphQL::Schema::Argument
6
+ def initialize(*args, **kwargs, &block)
7
+ super(*args, camelize: false, **kwargs, &block)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class BaseConnection < Types::BaseObject
6
+ # add `nodes` and `pageInfo` fields, as well as `edge_type(...)` and `node_nullable(...)` overrides
7
+ include GraphQL::Types::Relay::ConnectionBehaviors
8
+
9
+ field :total_count, Integer, null: false, camelize: false
10
+
11
+ def total_count
12
+ object.items.size
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class BaseEdge < Types::BaseObject
6
+ # add `node` and `cursor` fields, as well as `node_type(...)` override
7
+ include GraphQL::Types::Relay::EdgeBehaviors
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class BaseEnum < GraphQL::Schema::Enum
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class BaseField < GraphQL::Schema::Field
6
+ argument_class ::Ibrain::Types::BaseArgument
7
+
8
+ def initialize(*args, default_value: nil, **kwargs, &block)
9
+ super(*args, camelize: false, **kwargs, &block)
10
+
11
+ extension(::Ibrain::Extentions::DefaultValue, default_value: default_value) unless default_value.nil?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ class BaseInputObject < GraphQL::Schema::InputObject
6
+ argument_class Ibrain::Types::BaseArgument
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Types
5
+ module BaseInterface
6
+ include GraphQL::Schema::Interface
7
+
8
+ edge_type_class(Ibrain::Types::BaseEdge)
9
+ connection_type_class(Ibrain::Types::BaseConnection)
10
+
11
+ field_class Ibrain::Types::BaseField
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Ibrain::Types::BaseNode < Types::BaseObject
4
+ implements ::GraphQL::Relay::Node.interface
5
+ implements ::Ibrain::Interfaces::RecordInterface
6
+
7
+ global_id_field :id
8
+ field_class ::Ibrain::Types::BaseField
9
+
10
+ def self.field(*args, camelize: false, **kwargs, &block)
11
+ super
12
+ end
13
+ end