hasura_handler 0.1.0 → 0.1.5

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: 95be3b9811df02080b282112b53e0b0a6aacd4520cd98de9de851af3349028a8
4
- data.tar.gz: 41a54a270f42447b21ae308b79e23bd1ad24851cbc00d1c5101d8ca478342ef5
3
+ metadata.gz: d39e768059737605f096e2fb1ebc03b97a30ff3c05a55a580bc4f99b96e0e60e
4
+ data.tar.gz: 9322488f0d8cd4934509279e28b824926cb1f7a14a982700c323f5c11dab5d81
5
5
  SHA512:
6
- metadata.gz: f03c0e96d4c8f4e06de84c7ed087fb79a3c86d0fe8be6a29fd8d465d581c1a0735e81bf7cb3015eb1c7ac4bc2e25416ceef712716aa805a9163c6940d83aaa59
7
- data.tar.gz: b3c696453cd65e2c16b9d0e2888d0681456d7bba76d1e78d93b5cbcf510096c5618ecd58e5d81c5c7bdbfdffe8d68a651963e8737e293b93476fd9d6d7c8c720
6
+ metadata.gz: 021c7736f7148d728ea3b09562051e5b3679a6b9370a127304f988274a81cf2959b012dc2b2561fb257f43c10a2e396d753ce01101d19d1c1cc300337df9da69
7
+ data.tar.gz: ddda66c93f15b46b003f063b878fc00c59adba67bc0d6ec500d1b514ad1dfd0ecedf6f761db967a146678fb442060e8dbcb4cbea0306688ef0490ac31293118f
data/README.md CHANGED
@@ -1,28 +1,9 @@
1
- # HasuraHandler
2
- Short description and motivation.
1
+ # HasuraHandler ![Gem Version](https://badge.fury.io/rb/hasura_handler.svg) [![tests](https://github.com/KazW/HasuraHandler/workflows/tests/badge.svg)](https://github.com/KazW/HasuraHandler/actions?query=workflow%3Atests) [![Maintainability](https://api.codeclimate.com/v1/badges/38864d7565ab11729b6b/maintainability)](https://codeclimate.com/github/KazW/HasuraHandler/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/38864d7565ab11729b6b/test_coverage)](https://codeclimate.com/github/KazW/HasuraHandler/test_coverage)
2
+ HasuraHandler is a Rails framework that makes building microservices for Hasura easy.
3
+ HasuraHandler also simplifies adding Hasura to an existing Rails app.
3
4
 
4
5
  ## Usage
5
- How to use my plugin.
6
-
7
- ## Installation
8
- Add this line to your application's Gemfile:
9
-
10
- ```ruby
11
- gem 'hasura_handler'
12
- ```
13
-
14
- And then execute:
15
- ```bash
16
- $ bundle
17
- ```
18
-
19
- Or install it yourself as:
20
- ```bash
21
- $ gem install hasura_handler
22
- ```
23
-
24
- ## Contributing
25
- Contribution directions go here.
6
+ Please see the [documentation site](https://kazw.github.io/HasuraHandler).
26
7
 
27
8
  ## License
28
9
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -2,16 +2,22 @@ require_dependency 'hasura_handler/application_controller'
2
2
 
3
3
  module HasuraHandler
4
4
  class ActionsController < ApplicationController
5
- def process
6
- unless HasuraHandler::Action.hasura_actions.keys.include?(action_params[:action][:name])
5
+ before_action :check_header
6
+
7
+ def index
8
+ unless HasuraHandler::Action.hasura_actions.keys.include?(action_params['action']['name'])
7
9
  render json: { error: true, message: 'action name not registered' }, status: 404
8
10
  return
9
11
  end
10
12
 
11
- klass = HasuraHandler::Action.hasura_actions[action_params[:action][:name]]
12
- action = klass.new(action_params[:session_variables], action_params[:input])
13
- action.run
13
+ klass = HasuraHandler::Action.hasura_actions[action_params['action']['name']]
14
+ action = klass.new(
15
+ clean_headers,
16
+ action_params['session_variables'].to_h,
17
+ action_params['input'].to_h
18
+ )
14
19
 
20
+ action.run
15
21
  if action.error_message.present?
16
22
  render json: { error: true, message: action.error_message }, status: 400
17
23
  else
@@ -20,7 +26,7 @@ module HasuraHandler
20
26
  end
21
27
 
22
28
  def action_params
23
- params.permit(
29
+ full_params.permit(
24
30
  action: [:name],
25
31
  input: {},
26
32
  session_variables: {}
@@ -1,7 +1,5 @@
1
1
  module HasuraHandler
2
2
  class ApplicationController < ActionController::API
3
- before_action :check_header
4
-
5
3
  private
6
4
 
7
5
  def check_header
@@ -9,5 +7,13 @@ module HasuraHandler
9
7
  render json: { error: true, message: 'unable to authenticate request' }, status: 401
10
8
  end
11
9
  end
10
+
11
+ def full_params
12
+ ActionController::Parameters.new(JSON.parse(request.raw_post))
13
+ end
14
+
15
+ def clean_headers
16
+ request.headers.reject{ |k,v| k.include?('.') }.to_h
17
+ end
12
18
  end
13
19
  end
@@ -0,0 +1,35 @@
1
+ require_dependency "hasura_handler/application_controller"
2
+
3
+ module HasuraHandler
4
+ class AuthHookController < ApplicationController
5
+ def get_mode
6
+ @headers = clean_headers.to_h.select{ |k,v| k =~ /\AHTTP_/ }.to_h
7
+ authenticate
8
+ end
9
+
10
+ def post_mode
11
+ @headers = post_params['auth_hook']['headers'].
12
+ to_h.
13
+ map{ |k,v| ['HTTP_' + k.to_s.gsub('-', '_').upcase, v] }.
14
+ to_h
15
+
16
+ authenticate
17
+ end
18
+
19
+ private
20
+
21
+ def post_params
22
+ params.permit(auth_hook: {}, headers: {})
23
+ end
24
+
25
+ def authenticate
26
+ @authenticator = HasuraHandler.authenticator.new(@headers)
27
+
28
+ if @authenticator.success?
29
+ render json: @authenticator.response, status: 200
30
+ else
31
+ render json: { error: true, message: @authenticator.error_message }, status: 401
32
+ end
33
+ end
34
+ end
35
+ end
@@ -2,8 +2,10 @@ require_dependency 'hasura_handler/application_controller'
2
2
 
3
3
  module HasuraHandler
4
4
  class EventsController < ApplicationController
5
- def process
6
- processor = HasuraHandler::EventHandler.new(event_params)
5
+ before_action :check_header
6
+
7
+ def index
8
+ processor = HasuraHandler::EventProcessor.new(event_params.to_h)
7
9
 
8
10
  unless processor.event.valid?
9
11
  error_response(processor.event.errors)
@@ -32,9 +34,10 @@ module HasuraHandler
32
34
  end
33
35
 
34
36
  def event_params
35
- params.permit(
37
+ full_params.permit(
36
38
  :id,
37
39
  :created_at,
40
+ delivery_info: {},
38
41
  table: [
39
42
  :schema,
40
43
  :name
@@ -46,10 +49,7 @@ module HasuraHandler
46
49
  :op,
47
50
  {
48
51
  session_variables: {},
49
- data: {
50
- new: {},
51
- old: {}
52
- }
52
+ data: {}
53
53
  }
54
54
  ]
55
55
  )
@@ -4,7 +4,7 @@ module HasuraHandler
4
4
 
5
5
  def perform(handler_class, event)
6
6
  klass = handler_class.constantize
7
- handler = klass.new(event)
7
+ handler = klass.new(HasuraHandler::Event.new(event))
8
8
  handler.run
9
9
  end
10
10
  end
@@ -3,7 +3,7 @@ module HasuraHandler
3
3
  queue_as HasuraHandler.event_job_queue
4
4
 
5
5
  def perform(event)
6
- HasuraHandler::EventHandler.new(event).process
6
+ HasuraHandler::EventProcessor.new(event).process
7
7
  end
8
8
  end
9
9
  end
@@ -1,9 +1,14 @@
1
1
  HasuraHandler::Engine.routes.draw do
2
+ if HasuraHandler.authentication_enabled
3
+ get '/auth', to: 'auth_hook#get_mode'
4
+ post '/auth', to: 'auth_hook#post_mode'
5
+ end
6
+
2
7
  if HasuraHandler.events_enabled
3
- post '/events', to: 'events#process'
8
+ post '/events', to: 'events#index'
4
9
  end
5
10
 
6
11
  if HasuraHandler.actions_enabled
7
- post '/actions', to: 'actions#process'
12
+ post '/actions', to: 'actions#index'
8
13
  end
9
14
  end
@@ -1,5 +1,7 @@
1
1
  require 'hasura_handler/engine'
2
+ require 'hasura_handler/authenticator'
2
3
  require 'hasura_handler/event_handler'
4
+ require 'hasura_handler/event_processor'
3
5
  require 'hasura_handler/event'
4
6
  require 'hasura_handler/action'
5
7
 
@@ -7,6 +9,8 @@ module HasuraHandler
7
9
  class << self
8
10
  mattr_accessor :auth_header,
9
11
  :auth_key,
12
+ :authentication_enabled,
13
+ :authenticator,
10
14
  :events_enabled,
11
15
  :actions_enabled,
12
16
  :event_job_queue,
@@ -15,7 +19,9 @@ module HasuraHandler
15
19
  :fanout_events,
16
20
  :retry_after
17
21
 
18
- self.auth_header = 'X-Hasura-Service-Key'
22
+ self.auth_header = 'HTTP_X_HASURA_SERVICE_KEY'
23
+ self.authentication_enabled = false
24
+ self.authenticator = nil
19
25
  self.events_enabled = true
20
26
  self.async_events = true
21
27
  self.fanout_events = true
@@ -27,8 +33,13 @@ module HasuraHandler
27
33
 
28
34
  def self.setup(&block)
29
35
  yield self
30
- [:auth_key].each do |key|
31
- raise "HasuraHandler requires the #{key} to be configured." if self.send(key).blank?
36
+
37
+ if (self.events_enabled || self.actions_enabled) && self.auth_key.blank?
38
+ raise "HasuraHandler requires the auth_key to be configured if actions or events are enabled."
39
+ end
40
+
41
+ if self.authentication_enabled && self.authenticator.blank?
42
+ raise "HasuraHandler requires the authenticator to be configured if authentication hook is enabled."
32
43
  end
33
44
  end
34
45
  end
@@ -5,9 +5,7 @@ module HasuraHandler
5
5
  attr_reader :hasura_action_name
6
6
 
7
7
  def action_name(action_name)
8
- raise 'run method not defined' unless new(nil, nil).respond_to?(:run)
9
8
  raise 'action_name must be a symbol or string' unless action_name.is_a?(Symbol) || action_name.is_a?(String)
10
- raise 'action_name already used' if @@hasura_actions.keys.include?(action_name.to_s)
11
9
 
12
10
  @@hasura_actions[action_name.to_s] = self
13
11
  @hasura_action_name = action_name.to_s
@@ -19,11 +17,13 @@ module HasuraHandler
19
17
  end
20
18
 
21
19
  attr_reader :session_variables,
20
+ :headers,
22
21
  :input,
23
22
  :output,
24
23
  :error_message
25
24
 
26
- def initialize(session_variables, input)
25
+ def initialize(headers, session_variables, input)
26
+ @headers = headers
27
27
  @session_variables = session_variables
28
28
  @input = input
29
29
  @output = {}
@@ -0,0 +1,21 @@
1
+ module HasuraHandler
2
+ class Authenticator
3
+ attr_accessor :response,
4
+ :error_message
5
+
6
+ def initialize(headers)
7
+ @headers = headers
8
+ @response = {}
9
+ end
10
+
11
+ def success?
12
+ begin
13
+ authenticate
14
+ ensure
15
+ return false if @response.blank?
16
+ end
17
+
18
+ @response.present? || @error_message.blank?
19
+ end
20
+ end
21
+ end
@@ -4,17 +4,19 @@ module HasuraHandler
4
4
  :table,
5
5
  :trigger,
6
6
  :event,
7
+ :op,
7
8
  :created_at,
8
9
  :raw_event,
9
10
  :errors,
10
11
  :valid
11
12
 
12
13
  def initialize(event)
13
- @id = event[:id]
14
- @table = event[:table]
15
- @trigger = event[:trigger]
16
- @event = event[:event]
17
- @created_at = event[:created_at]
14
+ @id = event['id']
15
+ @table = event['table']['name']
16
+ @trigger = event['trigger']['name']
17
+ @event = event['event']
18
+ @op = event['event']['op']
19
+ @created_at = event['created_at']
18
20
  @raw_event = event
19
21
  @errors = {}
20
22
 
@@ -42,21 +44,21 @@ module HasuraHandler
42
44
  end
43
45
 
44
46
  def validate_table
45
- unless @table.is_a?(Hash)
47
+ unless @raw_event['table'].is_a?(Hash)
46
48
  @errors['table'] = 'not a hash'
47
49
  return
48
50
  end
49
51
 
50
- string_fields?(@table, 'table', [:schema, :name])
52
+ string_fields?(@raw_event['table'], 'table', [:schema, :name])
51
53
  end
52
54
 
53
55
  def validate_trigger
54
- unless @trigger.is_a?(Hash)
56
+ unless @raw_event['trigger'].is_a?(Hash)
55
57
  @errors['trigger'] = 'not a hash'
56
58
  return
57
59
  end
58
60
 
59
- string_fields?(@trigger, 'trigger', [:name])
61
+ string_fields?(@raw_event['trigger'], 'trigger', [:name])
60
62
  end
61
63
 
62
64
  def validate_event
@@ -65,7 +67,7 @@ module HasuraHandler
65
67
  return
66
68
  end
67
69
 
68
- @errors['event.session_variables'] = 'not a hash' unless @event[:session_variables].is_a?(Hash)
70
+ @errors['event.session_variables'] = 'not a hash' unless @event['session_variables'].is_a?(Hash)
69
71
  string_fields?(@event, 'event', [:op])
70
72
 
71
73
  [:new, :old].each do |field|
@@ -12,12 +12,12 @@ module HasuraHandler
12
12
  raise 'invalid matcher value' unless matchers[matcher].is_a?(String)
13
13
  end
14
14
 
15
- raise 'run method not defined' unless new(nil).respond_to?(:run)
16
-
17
15
  @hasura_matchers = matchers
18
16
  end
19
17
  end
20
18
 
19
+ attr_reader :event
20
+
21
21
  def initialize(event)
22
22
  @event = event
23
23
  end
@@ -19,6 +19,10 @@ module HasuraHandler
19
19
  handler.run
20
20
  end
21
21
  end
22
+
23
+ if event_handlers.size == 0
24
+ Rails.logger.debug('[HasuraHandler] Received event with no matching handlers.')
25
+ end
22
26
  end
23
27
 
24
28
  private
@@ -28,6 +32,7 @@ module HasuraHandler
28
32
  descendants.
29
33
  map{ |klass| [klass, klass.hasura_matchers] }.
30
34
  to_h.
35
+ select{ |klass, matchers| matchers.present? }.
31
36
  map{ |klass,matchers| [klass, check_matchers(matchers)] }.
32
37
  to_h.
33
38
  select{ |klass,match| match }.
@@ -35,8 +40,8 @@ module HasuraHandler
35
40
  end
36
41
 
37
42
  def check_matchers(matchers)
38
- matchers.all? do |matcher|
39
- @event.send(matcher.first) == matcher.last
43
+ matchers.all? do |field,value|
44
+ @event.send(field) == value
40
45
  end
41
46
  end
42
47
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hasura_handler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaz Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-25 00:00:00.000000000 Z
11
+ date: 2020-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -30,21 +30,8 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 6.0.3.2
33
- - !ruby/object:Gem::Dependency
34
- name: graphql-client
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: 0.16.0
40
- type: :runtime
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: 0.16.0
47
- description: Provides an easy way to build custom backends for Hasura.
33
+ description: HasuraHandler is a Rails framework that makes building microservices
34
+ for Hasura easy.
48
35
  email:
49
36
  - me@kaz.codes
50
37
  executables: []
@@ -56,6 +43,7 @@ files:
56
43
  - Rakefile
57
44
  - app/controllers/hasura_handler/actions_controller.rb
58
45
  - app/controllers/hasura_handler/application_controller.rb
46
+ - app/controllers/hasura_handler/auth_hook_controller.rb
59
47
  - app/controllers/hasura_handler/events_controller.rb
60
48
  - app/jobs/hasura_handler/application_job.rb
61
49
  - app/jobs/hasura_handler/event_handler_job.rb
@@ -63,16 +51,20 @@ files:
63
51
  - config/routes.rb
64
52
  - lib/hasura_handler.rb
65
53
  - lib/hasura_handler/action.rb
54
+ - lib/hasura_handler/authenticator.rb
66
55
  - lib/hasura_handler/engine.rb
67
56
  - lib/hasura_handler/event.rb
68
57
  - lib/hasura_handler/event_handler.rb
69
58
  - lib/hasura_handler/event_processor.rb
70
- - lib/hasura_handler/version.rb
71
59
  - lib/tasks/hasura_handler_tasks.rake
72
- homepage: https://github.com/KazW/HasuraHandler
60
+ homepage: https://kazw.github.io/HasuraHandler
73
61
  licenses:
74
62
  - MIT
75
- metadata: {}
63
+ metadata:
64
+ bug_tracker_uri: https://github.com/KazW/HasuraHandler/issues
65
+ documentation_uri: https://kazw.github.io/HasuraHandler
66
+ homepage_uri: https://kazw.github.io/HasuraHandler
67
+ source_code_uri: https://github.com/KazW/HasuraHandler
76
68
  post_install_message:
77
69
  rdoc_options: []
78
70
  require_paths:
@@ -88,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
80
  - !ruby/object:Gem::Version
89
81
  version: '0'
90
82
  requirements: []
91
- rubygems_version: 3.1.4
83
+ rubygems_version: 3.1.2
92
84
  signing_key:
93
85
  specification_version: 4
94
86
  summary: Integrates Hasura with Rails
@@ -1,3 +0,0 @@
1
- module HasuraHandler
2
- VERSION = '0.1.0'
3
- end