bima-shark-sdk 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +56 -0
  5. data/.travis.yml +10 -0
  6. data/CHANGELOG.md +131 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +53 -0
  10. data/Rakefile +8 -0
  11. data/bima-shark-sdk.gemspec +36 -0
  12. data/bin/console +24 -0
  13. data/bin/setup +8 -0
  14. data/lib/bima-shark-sdk/rspec.rb +38 -0
  15. data/lib/bima-shark-sdk.rb +3 -0
  16. data/lib/shark/account.rb +7 -0
  17. data/lib/shark/activity.rb +11 -0
  18. data/lib/shark/asset.rb +13 -0
  19. data/lib/shark/base.rb +36 -0
  20. data/lib/shark/client/connection.rb +67 -0
  21. data/lib/shark/concerns/connected.rb +44 -0
  22. data/lib/shark/concerns/normalized_email.rb +13 -0
  23. data/lib/shark/configuration.rb +90 -0
  24. data/lib/shark/consent.rb +31 -0
  25. data/lib/shark/contact.rb +40 -0
  26. data/lib/shark/contact_log.rb +7 -0
  27. data/lib/shark/double_opt_in/execution.rb +50 -0
  28. data/lib/shark/double_opt_in/request.rb +45 -0
  29. data/lib/shark/error.rb +69 -0
  30. data/lib/shark/form_service/base.rb +11 -0
  31. data/lib/shark/form_service/form/container.rb +10 -0
  32. data/lib/shark/form_service/form/element.rb +83 -0
  33. data/lib/shark/form_service/form/multiple_choice.rb +21 -0
  34. data/lib/shark/form_service/form/rating_scale.rb +20 -0
  35. data/lib/shark/form_service/form/rating_star.rb +13 -0
  36. data/lib/shark/form_service/form/structure.rb +13 -0
  37. data/lib/shark/form_service/form/text_area.rb +10 -0
  38. data/lib/shark/form_service/form/text_field.rb +17 -0
  39. data/lib/shark/form_service/v2/base.rb +13 -0
  40. data/lib/shark/form_service/v2/form.rb +18 -0
  41. data/lib/shark/form_service/v2/form_input.rb +15 -0
  42. data/lib/shark/form_service/v2/form_version.rb +19 -0
  43. data/lib/shark/form_service.rb +21 -0
  44. data/lib/shark/group.rb +18 -0
  45. data/lib/shark/mailing_service/base.rb +11 -0
  46. data/lib/shark/mailing_service/configuration.rb +9 -0
  47. data/lib/shark/mailing_service/mail.rb +8 -0
  48. data/lib/shark/mailing_service/mailers/base_mailer.rb +96 -0
  49. data/lib/shark/mailing_service/renderers/context.rb +40 -0
  50. data/lib/shark/mailing_service/renderers/erb_renderer.rb +46 -0
  51. data/lib/shark/mailing_service.rb +23 -0
  52. data/lib/shark/membership.rb +16 -0
  53. data/lib/shark/middleware/compose_request.rb +41 -0
  54. data/lib/shark/middleware/status.rb +36 -0
  55. data/lib/shark/notification.rb +21 -0
  56. data/lib/shark/package.rb +7 -0
  57. data/lib/shark/permission.rb +7 -0
  58. data/lib/shark/rails.rb +13 -0
  59. data/lib/shark/rspec/fake_asset_service/object_cache.rb +76 -0
  60. data/lib/shark/rspec/fake_asset_service/public_id.rb +21 -0
  61. data/lib/shark/rspec/fake_asset_service/request.rb +154 -0
  62. data/lib/shark/rspec/fake_asset_service.rb +20 -0
  63. data/lib/shark/rspec/fake_consent_service/object_cache.rb +44 -0
  64. data/lib/shark/rspec/fake_consent_service/request.rb +53 -0
  65. data/lib/shark/rspec/fake_consent_service.rb +19 -0
  66. data/lib/shark/rspec/fake_contact_service/object_cache.rb +88 -0
  67. data/lib/shark/rspec/fake_contact_service/request.rb +170 -0
  68. data/lib/shark/rspec/fake_contact_service.rb +19 -0
  69. data/lib/shark/rspec/fake_double_opt_in/object_cache.rb +59 -0
  70. data/lib/shark/rspec/fake_double_opt_in/request.rb +133 -0
  71. data/lib/shark/rspec/fake_double_opt_in.rb +19 -0
  72. data/lib/shark/rspec/fake_mailing_service/request.rb +41 -0
  73. data/lib/shark/rspec/fake_mailing_service.rb +13 -0
  74. data/lib/shark/rspec/fake_notification_service/request.rb +53 -0
  75. data/lib/shark/rspec/fake_notification_service.rb +13 -0
  76. data/lib/shark/rspec/fake_subscription_service/object_cache.rb +54 -0
  77. data/lib/shark/rspec/fake_subscription_service/request.rb +100 -0
  78. data/lib/shark/rspec/fake_subscription_service.rb +19 -0
  79. data/lib/shark/rspec/fake_survey_service/object_cache.rb +36 -0
  80. data/lib/shark/rspec/fake_survey_service/request.rb +66 -0
  81. data/lib/shark/rspec/fake_survey_service.rb +19 -0
  82. data/lib/shark/rspec/fixtures/form_inputs.json +26 -0
  83. data/lib/shark/rspec/fixtures/form_structure.json +175 -0
  84. data/lib/shark/rspec/helpers/cache_helper.rb +44 -0
  85. data/lib/shark/rspec/helpers/fixtures.rb +26 -0
  86. data/lib/shark/rspec/helpers/form_service_helper.rb +27 -0
  87. data/lib/shark/rspec/helpers/response.rb +25 -0
  88. data/lib/shark/rspec/helpers.rb +26 -0
  89. data/lib/shark/subscription.rb +43 -0
  90. data/lib/shark/survey.rb +29 -0
  91. data/lib/shark/survey_participant.rb +37 -0
  92. data/lib/shark/version.rb +5 -0
  93. data/lib/shark.rb +91 -0
  94. metadata +291 -0
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module AssetService
5
+ module Resource
6
+ mattr_accessor :site
7
+ end
8
+ end
9
+
10
+ module ContactService
11
+ module Resource
12
+ mattr_accessor :site
13
+ end
14
+ end
15
+
16
+ module ConsentService
17
+ module Resource
18
+ mattr_accessor :site
19
+ end
20
+ end
21
+
22
+ module DoubleOptIn
23
+ class ExceededNumberOfVerificationRequestsError < Error; end
24
+ class RequestedUnverifiedExecutionError < Error; end
25
+ class VerificationExpiredError < Error; end
26
+
27
+ module Resource
28
+ mattr_accessor :site
29
+ end
30
+ end
31
+
32
+ module NotificationService
33
+ module Resource
34
+ mattr_accessor :site
35
+ end
36
+ end
37
+
38
+ module SubscriptionService
39
+ module Resource
40
+ mattr_accessor :site
41
+ end
42
+ end
43
+
44
+ module SurveyService
45
+ module Resource
46
+ mattr_accessor :site
47
+ end
48
+ end
49
+
50
+ class Configuration
51
+ class Service
52
+ attr_accessor :site
53
+ attr_reader :headers
54
+
55
+ def initialize
56
+ @headers = {}
57
+ end
58
+
59
+ def headers=(value)
60
+ @headers.merge!(value)
61
+ end
62
+ end
63
+
64
+ #
65
+ # Shark Configuration
66
+ #
67
+ attr_accessor :cache, :logger
68
+ attr_reader :contact_service
69
+ attr_reader :consent_service
70
+ attr_reader :double_opt_in
71
+ attr_reader :form_service
72
+ attr_reader :survey_service
73
+ attr_reader :notification_service
74
+ attr_reader :subscription_service
75
+ attr_reader :asset_service
76
+ attr_reader :mailing_service
77
+
78
+ def initialize
79
+ @asset_service = AssetService::Resource
80
+ @contact_service = ContactService::Resource
81
+ @consent_service = ConsentService::Resource
82
+ @double_opt_in = DoubleOptIn::Resource
83
+ @form_service = Service.new
84
+ @mailing_service = Service.new
85
+ @notification_service = NotificationService::Resource
86
+ @subscription_service = SubscriptionService::Resource
87
+ @survey_service = SurveyService::Resource
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ class Consent < Base
5
+ extend ConsentService::Resource
6
+
7
+ def self.all
8
+ raise Shark::ActionNotSupportedError,
9
+ 'Shark::ConsentService::Consent.all is not supported'
10
+ end
11
+
12
+ def update_attributes(_attributes = {})
13
+ raise Shark::ActionNotSupportedError,
14
+ 'Shark::ConsentService::Consent#update_attributes is not supported'
15
+ end
16
+
17
+ def destroy
18
+ raise Shark::ActionNotSupportedError,
19
+ 'Shark::ConsentService::Consent#destroy is not supported'
20
+ end
21
+
22
+ def save
23
+ if self['id'].present?
24
+ raise Shark::ActionNotSupportedError,
25
+ 'Shark::ConsentService::Consent#save is not supported for persisted consents'
26
+ else
27
+ super
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ class Contact < Base
5
+ extend ContactService::Resource
6
+ include Shark::NormalizedEmail
7
+
8
+ custom_endpoint :avatar, on: :collection, request_method: :get
9
+
10
+ property :account_id
11
+
12
+ has_many :memberships
13
+ has_many :groups
14
+ has_one :permission
15
+
16
+ def self.find_by_email(email)
17
+ normalized_email = normalize_email(email)
18
+ options = { filter: { equals: { email: normalized_email } } }
19
+ where(options).first
20
+ end
21
+
22
+ # @example
23
+ # contacts = Shark::ContactService::Contact.find_by_permissions([
24
+ # { resource: 'paragraph::contract', privilege: 'admin' },
25
+ # { resource: 'datenraum', privilege: 'admin'}
26
+ # ])
27
+ #
28
+ # @param permissions_filter [Array] the filter of resources and privileges.
29
+ # @api public
30
+ def self.find_by_permissions(permissions_filter)
31
+ includes('permission').where(permissions: permissions_filter)
32
+ end
33
+
34
+ def account
35
+ return nil if account_id.blank?
36
+
37
+ Shark::Account.find(account_id).first
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ class ContactLog < Base
5
+ extend ContactService::Resource
6
+ end
7
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module DoubleOptIn
5
+ class Execution < Base
6
+ extend DoubleOptIn::Resource
7
+
8
+ attr_accessor :payload, :request_type
9
+
10
+ def self.verify(verification_token)
11
+ response = connection.run(:post, "/executions/#{verification_token}/verify")
12
+ new(response.body['data'])
13
+ rescue UnprocessableEntity => e
14
+ if caused_by_error_code?(e.errors, 'exceeded_number_of_verification_requests')
15
+ raise ExceededNumberOfVerificationRequestsError
16
+ end
17
+
18
+ raise VerificationExpiredError if caused_by_error_code?(e.errors, 'verification_expired')
19
+
20
+ raise e
21
+ end
22
+
23
+ def self.find(verification_token)
24
+ response = connection.run(:get, "/executions/#{verification_token}")
25
+ new(response.body['data'])
26
+ rescue UnprocessableEntity => e
27
+ if caused_by_error_code?(e.errors, 'requested_unverified_execution')
28
+ raise RequestedUnverifiedExecutionError
29
+ end
30
+
31
+ raise e
32
+ end
33
+
34
+ def self.terminate(verification_token)
35
+ response = connection.run(:delete, "/executions/#{verification_token}")
36
+ new(response.body['data'])
37
+ end
38
+
39
+ def initialize(data)
40
+ %w[payload request_type].each do |key|
41
+ public_send("#{key}=", data['attributes'][key])
42
+ end
43
+ end
44
+
45
+ def self.caused_by_error_code?(errors, error_code)
46
+ errors.detect { |error| error['code'] == error_code }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module DoubleOptIn
5
+ class Request < Base
6
+ extend DoubleOptIn::Resource
7
+
8
+ ATTRIBUTES = %w[
9
+ payload
10
+ request_type
11
+ recipient
12
+ subject
13
+ header
14
+ sub_header
15
+ message
16
+ verification_url
17
+ verification_link_text
18
+ message_footer_html
19
+ timeout
20
+ leeway_to_terminate
21
+ max_verifications
22
+ ].freeze
23
+
24
+ attr_accessor(*ATTRIBUTES)
25
+
26
+ def self.create(attributes)
27
+ body = {
28
+ data: {
29
+ type: 'requests',
30
+ attributes: attributes
31
+ }
32
+ }
33
+
34
+ response = connection.request(:post, '/requests/', body: body)
35
+ new(response.body['data'])
36
+ end
37
+
38
+ def initialize(data)
39
+ ATTRIBUTES.each do |key|
40
+ public_send("#{key}=", data['attributes'][key])
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ class Error < StandardError; end
5
+
6
+ class ApiError < Error
7
+ attr_reader :code, :env
8
+
9
+ def initialize(code, env)
10
+ @code = code
11
+ @env = env
12
+ end
13
+
14
+ def body
15
+ env[:body]
16
+ end
17
+
18
+ def url
19
+ env[:url]
20
+ end
21
+
22
+ def message
23
+ body.to_s
24
+ end
25
+ end
26
+
27
+ class ConnectionError < ApiError
28
+ def initialize(env)
29
+ @env = env
30
+ end
31
+ end
32
+
33
+ class ClientError < ApiError; end
34
+
35
+ class AccessDenied < ClientError; end
36
+
37
+ class NotAuthorized < ClientError; end
38
+
39
+ class ResourceConflict < ClientError; end
40
+
41
+ class ResourceNotFound < ClientError
42
+ def message
43
+ "Couldn't find resource at: #{url}"
44
+ end
45
+ end
46
+
47
+ class UnprocessableEntity < ClientError
48
+ def errors
49
+ body['errors'] || {}
50
+ end
51
+
52
+ def message
53
+ errors.to_json
54
+ end
55
+ end
56
+
57
+ class ServerError < ApiError; end
58
+
59
+ class UnexpectedStatus < ServerError
60
+ def message
61
+ "Unexpected response status: #{code} from: #{url}"
62
+ end
63
+ end
64
+
65
+ #
66
+ # Other errors
67
+ #
68
+ class ActionNotSupportedError < Error; end
69
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ class Base < ::Shark::Base
6
+ def self.site
7
+ File.join(::Shark.configuration.form_service.site, '/api')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class Container < Element
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class Element
7
+ attr_reader :parent, :children
8
+
9
+ def initialize(element, parent = nil)
10
+ @element = element.except('elements') || {}
11
+ @parent = parent
12
+ @children = parse_children(element['elements'] || [])
13
+ end
14
+
15
+ def id
16
+ @element['id']
17
+ end
18
+
19
+ def label
20
+ %w[label legend].each do |attr|
21
+ next unless attribute_defined?(attr)
22
+
23
+ return attribute_definition(attr)['value']
24
+ end
25
+ ''
26
+ end
27
+
28
+ def type
29
+ @element['type']
30
+ end
31
+
32
+ def text
33
+ return '' unless attribute_defined?('text')
34
+
35
+ attribute_definition('text')['value']
36
+ end
37
+
38
+ def attribute_definitions
39
+ @element['attribute_definitions'] || []
40
+ end
41
+
42
+ def attribute_definition(name)
43
+ attribute_definitions.detect { |a| a['name'] == name }
44
+ end
45
+
46
+ def attribute_defined?(name)
47
+ attribute_definition(name).present?
48
+ end
49
+
50
+ def ancestors
51
+ return parent.ancestors << self if parent.present?
52
+
53
+ [self]
54
+ end
55
+
56
+ protected
57
+
58
+ attr_reader :element
59
+
60
+ def parse_children(elements)
61
+ elements.map do |e|
62
+ case e['type']
63
+ when 'form_container'
64
+ Container.new(e, self)
65
+ when 'form_multiple_choice'
66
+ MultipleChoice.new(e, self)
67
+ when 'form_rating_scale'
68
+ RatingScale.new(e, self)
69
+ when 'form_rating_star'
70
+ RatingStar.new(e, self)
71
+ when 'form_text_field'
72
+ TextField.new(e, self)
73
+ when 'form_textarea'
74
+ TextArea.new(e, self)
75
+ else
76
+ raise ArgumentError, "Unknown form element type: #{e['type']}"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class MultipleChoice < Element
7
+ def values
8
+ element['valid_values']
9
+ end
10
+
11
+ def more_on_choice?
12
+ more_on_choice = attribute('more_on_choice')
13
+
14
+ return values.include?(more_on_choice['value']) if more_on_choice.present?
15
+
16
+ false
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class RatingScale < Element
7
+ def values
8
+ scale_start = element['scale_start'].to_i
9
+ scale_end = element['scale_end'].to_i
10
+ allow_no_information = element['allow_no_information']
11
+
12
+ scale_values = (scale_start..scale_end).to_a
13
+ scale_values << -1 if allow_no_information == true
14
+
15
+ scale_values
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class RatingStar < Element
7
+ def values
8
+ element['valid_values']
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class Structure < Element
7
+ def initialize(structure)
8
+ super(structure)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class TextArea < Element
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module Form
6
+ class TextField < Element
7
+ def pre_text
8
+ attribute_definition('pre_text')['value']
9
+ end
10
+
11
+ def post_text
12
+ attribute_definition('post_text')['value']
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module V2
6
+ class Base < FormService::Base
7
+ def self.site
8
+ File.join(::Shark.configuration.form_service.site, '/api/v2')
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module V2
6
+ class Form < V2::Base
7
+ # @example
8
+ # form = Shark::FormService::V2::Form.find(id)
9
+ # form.activate
10
+ #
11
+ # @api public
12
+ def activate
13
+ update(state: 'active')
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module V2
6
+ class FormInput < V2::Base
7
+ belongs_to :form
8
+
9
+ def self.table_name
10
+ 'inputs'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module FormService
5
+ module V2
6
+ class FormVersion < V2::Base
7
+ belongs_to :form
8
+
9
+ def self.table_name
10
+ 'versions'
11
+ end
12
+
13
+ def form_structure
14
+ @form_structure ||= FormService::Form::Structure.new(structure)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shark/form_service/base'
4
+ require 'shark/form_service/form/element'
5
+ require 'shark/form_service/form/container'
6
+ require 'shark/form_service/form/multiple_choice'
7
+ require 'shark/form_service/form/rating_scale'
8
+ require 'shark/form_service/form/rating_star'
9
+ require 'shark/form_service/form/text_area'
10
+ require 'shark/form_service/form/text_field'
11
+ require 'shark/form_service/form/structure'
12
+
13
+ require 'shark/form_service/v2/base'
14
+ require 'shark/form_service/v2/form'
15
+ require 'shark/form_service/v2/form_input'
16
+ require 'shark/form_service/v2/form_version'
17
+
18
+ module Shark
19
+ module FormService
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ class Group < Base
5
+ extend ContactService::Resource
6
+
7
+ has_many :contacts
8
+
9
+ def contact?(contact_id)
10
+ contacts = relationships['contacts']
11
+ return false if contacts.blank? || contacts['data'].blank?
12
+
13
+ contacts['data'].any? { |c| c['type'] == 'contacts' && c['id'].to_s == contact_id.to_s }
14
+ end
15
+
16
+ alias has_contact? contact?
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module MailingService
5
+ class Base < ::Shark::Base
6
+ def self.site
7
+ ::Shark.configuration.mailing_service.site
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module MailingService
5
+ class Configuration
6
+ attr_accessor :context_helpers, :default_layout, :default_template_root
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shark
4
+ module MailingService
5
+ class Mail < Base
6
+ end
7
+ end
8
+ end