bima-shark-sdk 2.3.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 (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