ibrain-core 0.1.7 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57017a63ef4f94fba49be6f78fa18d5754bd81109f144995c44d8ff38a7c8bc0
4
- data.tar.gz: 7204281494ec365f7528714301bf1fd7b2b40eff3f9e29e874207f8592c8fe33
3
+ metadata.gz: 5c262993dec17ae9595461851704d63d2db7c281c131e54694f804d935a2554e
4
+ data.tar.gz: 8a1500b6a3dc0e6ab6411335f85c7f5e197fb4f4166e87bf301c3c50a48611d8
5
5
  SHA512:
6
- metadata.gz: 948449257443e847916a2281a7acd9c346579a800d98af65e2bad7e32cf3812b8b69ff768dc760b0d4fcf098c1eba412e674ec5b34b87fa6e3a75415d69df1c7
7
- data.tar.gz: 33f5104110a2912405452c65829076ffb92b217835c2a1e9d0b4f7991c3577d35a739342a8e4e99215115f4af0dfcae73b6b3b32c491706432a00a68eee8a207
6
+ metadata.gz: e26db7af8481c6910d5a77a65c0c199da2464302ce412cbf13d682c25cfeac8d9fe15e27eb11def778b4ead1cd40cdb2060d76a9967f9a21f39c44711ce5acb4
7
+ data.tar.gz: 7b7681cc908112ae19e63e3abbec85824f86331ea91f966953b744f15564cac62f087a31b234dd4b4888cd62a2b5b8300b93546cf7d9ad9dae2ca75b55475ae6
data/README.md CHANGED
@@ -54,20 +54,34 @@ bundle exec rails generate ibrain:graphql:resolvers users --model=User
54
54
  For pagination please using aggregate body query, something like
55
55
  ```
56
56
  query users($offset: Int, $limit: Int, $filter: Filter) {
57
- users(offset: $offset, limit: $limit, filter: $filter) {
58
- id
59
- first_name
60
- }
57
+ users(offset: $offset, limit: $limit, filter: $filter) {
58
+ id
59
+ first_name
60
+ }
61
61
 
62
- users_aggregate(filter: $filter) {
63
- total_count
64
- }
62
+ users_aggregate(filter: $filter) {
63
+ total_count
64
+ }
65
65
  }
66
66
  ```
67
67
  To generate graphql mutation to insert, update, delete user
68
68
  ```bash
69
69
  bundle exec rails generate ibrain:graphql:mutation insert_user --model=User
70
70
  ```
71
+
72
+ Default all operation will be rejected if you not have Authorization Token at request header, so to skip authenticate please change `parent_controller` at `ibrain.rb`
73
+ ```
74
+ config.parent_controller = "<Your parent controller>"
75
+ ```
76
+ then create method skip_operations at this parent_controller
77
+ ```
78
+ class ApplicationController < BaseController::API
79
+ def skip_operations
80
+ %w[sign_in].include?(operation_name)
81
+ end
82
+ end
83
+ ```
84
+
71
85
  ## Contributing
72
86
  Contribution directions go here.
73
87
 
@@ -12,6 +12,7 @@ module IbrainHandler
12
12
  rescue_from IbrainErrors::UnknownError, with: :bad_request_handler
13
13
  rescue_from ActionController::InvalidAuthenticityToken, with: :unauthorized_handler
14
14
  rescue_from ActiveSupport::MessageVerifier::InvalidSignature, with: :unauthorized_handler
15
+ rescue_from GraphQL::ExecutionError, with: :bad_request_handler
15
16
  end
16
17
 
17
18
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ibrain
4
- class BaseController < ActionController::API
4
+ class BaseController < Ibrain::Config.parent_controller.constantize
5
5
  include ActionController::Helpers
6
6
  include Ibrain::Core::ControllerHelpers::Response
7
7
  include Ibrain::Core::ControllerHelpers::StrongParameters
@@ -18,7 +18,7 @@ module Ibrain
18
18
  end
19
19
 
20
20
  def skip_operations
21
- []
21
+ super || ['IntrospectionQuery'].include?(operation_name)
22
22
  end
23
23
 
24
24
  def cryptor
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ibrain
4
+ module Core
5
+ class GraphqlController < ::Ibrain::BaseController
6
+ include Devise::Controllers::ScopedViews
7
+
8
+ before_action :authenticate_user!, unless: :skip_operations
9
+ before_action :map_user_class_to_request
10
+
11
+ helpers = %w(resource scope_name resource_name signed_in_resource
12
+ resource_class resource_params devise_mapping)
13
+ helper_method(*helpers)
14
+
15
+ def execute
16
+ query, variables, operation_name = normalize_entity
17
+
18
+ result = schema.execute(
19
+ query,
20
+ variables: variables,
21
+ context: {
22
+ session: session,
23
+ current_user: try_ibrain_current_user,
24
+ controller: self,
25
+ request: request
26
+ },
27
+ operation_name: operation_name
28
+ )
29
+
30
+ render_json_ok(result['data'], nil, result['errors'])
31
+ end
32
+
33
+ protected
34
+
35
+ def normalize_entity
36
+ query = params[:query]
37
+ operation_name = params[:operationName]
38
+ variables = prepare_variables(params[:variables])
39
+
40
+ [query, variables, operation_name]
41
+ end
42
+
43
+ # Handle variables in form data, JSON body, or a blank value
44
+ def prepare_variables(variables_param)
45
+ case variables_param
46
+ when String
47
+ if variables_param.present?
48
+ JSON.parse(variables_param) || {}
49
+ else
50
+ {}
51
+ end
52
+ when Hash
53
+ variables_param
54
+ when ActionController::Parameters
55
+ variables_param.to_unsafe_hash # GraphQLRuby will validate name and type of incoming variables.
56
+ when nil
57
+ {}
58
+ else
59
+ raise ArgumentError, "Unexpected parameter: #{variables_param}"
60
+ end
61
+ end
62
+
63
+ def schema
64
+ Ibrain::Config.graphql_schema.safe_constantize
65
+ end
66
+
67
+ def map_user_class_to_request
68
+ return if request.env['devise.mapping'].present?
69
+
70
+ request.env['devise.mapping'] = Ibrain.user_class
71
+ end
72
+ end
73
+ end
74
+ end
@@ -6,7 +6,7 @@ module Ibrain
6
6
 
7
7
  use GraphQL::Guard.new(
8
8
  policy_object: ::Ibrain::Config.graphql_policy.safe_constantize,
9
- not_authorized: ->(type, field) { GraphQL::ExecutionError.new("Not authorized to access #{type}.#{field}") }
9
+ not_authorized: ->(type, field) { raise IbrainErrors::UnknownError.new("Not authorized to access #{type}.#{field}") }
10
10
  )
11
11
 
12
12
  # Union and Interface Resolution
@@ -30,6 +30,18 @@ module Ibrain
30
30
  def current_user
31
31
  context[:current_user]
32
32
  end
33
+
34
+ def controller
35
+ context[:controller]
36
+ end
37
+
38
+ def session
39
+ context[:session]
40
+ end
41
+
42
+ def request
43
+ context[:request]
44
+ end
33
45
  end
34
46
  end
35
47
  end
@@ -3,26 +3,32 @@
3
3
  module Ibrain
4
4
  module Policies
5
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
6
  class << self
7
+ def query_rules
8
+ {
9
+ '*': {
10
+ guard: ->(_obj, _args, _ctx) { false }
11
+ }
12
+ }
13
+ end
14
+
15
+ def mutation_rules
16
+ {
17
+ '*': {
18
+ guard: ->(_obj, _args, _ctx) { false }
19
+ }
20
+ }
21
+ end
22
+
23
+ def rules
24
+ {
25
+ 'Types::QueryType' => query_rules,
26
+ 'Types::MutationType' => mutation_rules
27
+ }.freeze
28
+ end
29
+
24
30
  def roles
25
- Ibrain::Config.ibrain_roles
31
+ Ibrain.user_class.roles.keys
26
32
  end
27
33
 
28
34
  def has_permission?(current_user, resource)
@@ -33,11 +39,11 @@ module Ibrain
33
39
  end
34
40
 
35
41
  def guard(type, field)
36
- RULES.dig(type.name, field, :guard)
42
+ rules.dig(type.name, field, :guard)
37
43
  end
38
44
 
39
45
  def not_authorized_handler(type, field)
40
- RULES.dig(type, field, :not_authorized) || RULES.dig(type, :*, :not_authorized)
46
+ rules.dig(type, field, :not_authorized) || rules.dig(type, :*, :not_authorized)
41
47
  end
42
48
  end
43
49
  end
@@ -10,6 +10,10 @@ module Ibrain
10
10
  def current_user
11
11
  context.fetch(:current_user)
12
12
  end
13
+
14
+ def controller
15
+ context[:controller]
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- IGNORE_ATTRIBUTES = %w(id created_at updated_at)
4
-
5
3
  class Ibrain::Base < Ibrain::ApplicationRecord
6
4
  include ActionView::Helpers::DateHelper
7
5
 
6
+ IGNORE_ATTRIBUTES = %w(id created_at updated_at)
7
+
8
8
  self.abstract_class = true
9
9
 
10
10
  def string_id
data/config/routes.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Ibrain::Core::Engine.routes.draw do
4
- if ::Ibrain::Config.api_version.blank?
5
- post '/api/graphql', to: 'graphql#execute'
6
- else
7
- post "/api/#{::Ibrain::Config.api_version.downcase}/graphql", controller: 'graphql', action: 'execute'
8
- end
4
+ match "/", controller: 'graphql', action: 'execute', via: [:options, :post]
9
5
  end
@@ -7,7 +7,7 @@ module Resolvers
7
7
  # description
8
8
 
9
9
  # TODO: define return fields
10
- type Types::Objects::<%= model_name.capitalize %>Type, null: false, description: 'Define data type will be response to client'
10
+ type Types::Objects::<%= model_name.capitalize %>Type, null: false
11
11
 
12
12
  argument :id, ID, required: false, description: 'TODO: describe about this argument'
13
13
 
@@ -7,7 +7,7 @@ module Resolvers
7
7
  # description
8
8
 
9
9
  # TODO: define return fields
10
- type [Types::Objects::<%= model_name.capitalize %>Type], null: false, description: 'Define data type will be response to client'
10
+ type [Types::Objects::<%= model_name.capitalize %>Type], null: false
11
11
 
12
12
  # TODO: define resolve method
13
13
  def resolve(args)
@@ -41,6 +41,9 @@ Ibrain.config do |config|
41
41
 
42
42
  # Graphql Encryptor key
43
43
  # config.ibrain_encryptor_key = Rails.application.secrets.secret_key_base.byteslice(0..31)
44
+
45
+ # Parent controller
46
+ # config.parent_controller = 'ActionController::API'
44
47
  end
45
48
 
46
49
  <% if defined?(Ibrain::Api::Engine) -%>
@@ -48,6 +48,9 @@ module Ibrain
48
48
  # Graphql Encryptor key
49
49
  preference :ibrain_encryptor_key, :string, default: nil
50
50
 
51
+ # Parent controller
52
+ preference :parent_controller, :string, default: 'ActionController::API'
53
+
51
54
  def static_model_preferences
52
55
  @static_model_preferences ||= Ibrain::Preferences::StaticModelPreferences.new
53
56
  end
@@ -16,6 +16,7 @@ module Ibrain
16
16
  def render_json_error(error, status)
17
17
  e_message = error.try(:record).try(:errors).try(:full_messages).try(:first)
18
18
  e_message = error.try(:message) if e_message.blank?
19
+ e_message = error.try(:details) if e_message.blank?
19
20
 
20
21
  backtrace = error.try(:backtrace).try(:join, "\n")
21
22
 
@@ -5,7 +5,7 @@ require 'ibrain/config'
5
5
  module Ibrain
6
6
  module Core
7
7
  class Engine < ::Rails::Engine
8
- isolate_namespace Ibrain
8
+ isolate_namespace Ibrain::Core
9
9
  config.generators.api_only = true
10
10
 
11
11
  initializer "ibrain.environment", before: :load_config_initializers do |app|
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ibrain
4
- VERSION = "0.1.7"
4
+ VERSION = "0.2.1"
5
5
 
6
6
  def self.ibrain_version
7
7
  VERSION
8
8
  end
9
9
 
10
10
  def self.previous_ibrain_minor_version
11
- '0.1.6'
11
+ '0.2.0'
12
12
  end
13
13
 
14
14
  def self.ibrain_gem_version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ibrain-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tai Nguyen Van
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-30 00:00:00.000000000 Z
11
+ date: 2022-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord-session_store
@@ -183,7 +183,7 @@ files:
183
183
  - app/controllers/concerns/ibrain_errors.rb
184
184
  - app/controllers/concerns/ibrain_handler.rb
185
185
  - app/controllers/ibrain/base_controller.rb
186
- - app/controllers/ibrain/graphql_controller.rb
186
+ - app/controllers/ibrain/core/graphql_controller.rb
187
187
  - app/graphql/ibrain/base_schema.rb
188
188
  - app/graphql/ibrain/extentions/default_value.rb
189
189
  - app/graphql/ibrain/interfaces/base_interface.rb
@@ -1,55 +0,0 @@
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: try_ibrain_current_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