ibrain-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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