cmor_transports 0.0.56.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +19 -0
  5. data/app/assets/config/cmor/transports_manifest.js +1 -0
  6. data/app/assets/javascripts/cmor/transports/application.js +2 -0
  7. data/app/assets/javascripts/cmor/transports/application/keep.js +0 -0
  8. data/app/assets/javascripts/cmor_transports.js +2 -0
  9. data/app/assets/stylesheets/cmor/transports/application.css +3 -0
  10. data/app/assets/stylesheets/cmor/transports/application/keep.css +0 -0
  11. data/app/assets/stylesheets/cmor_transports.css +3 -0
  12. data/app/concerns/cmor/transports/models/uuid_concern.rb +20 -0
  13. data/app/concerns/cmor/transports/resources_controller/export_concern.rb +63 -0
  14. data/app/concerns/cmor/transports/routing/export_resources_concern.rb +30 -0
  15. data/app/controllers/cmor/transports/api/incoming/create_services_controller.rb +22 -0
  16. data/app/controllers/cmor/transports/api/incoming/show_services_controller.rb +22 -0
  17. data/app/controllers/cmor/transports/export_sidebars_controller.rb +11 -0
  18. data/app/controllers/cmor/transports/exports_controller.rb +24 -0
  19. data/app/controllers/cmor/transports/home_controller.rb +6 -0
  20. data/app/controllers/cmor/transports/incomings_controller.rb +16 -0
  21. data/app/controllers/cmor/transports/outgoings_controller.rb +16 -0
  22. data/app/controllers/cmor/transports/systems_controller.rb +14 -0
  23. data/app/models/cmor/transports/export.rb +61 -0
  24. data/app/models/cmor/transports/import.rb +37 -0
  25. data/app/models/cmor/transports/incoming.rb +40 -0
  26. data/app/models/cmor/transports/outgoing.rb +98 -0
  27. data/app/models/cmor/transports/outgoing_export.rb +8 -0
  28. data/app/models/cmor/transports/outgoing_target.rb +20 -0
  29. data/app/models/cmor/transports/system.rb +15 -0
  30. data/app/services/cmor/transports/api/incoming/create_service.rb +45 -0
  31. data/app/services/cmor/transports/api/incoming/show_service.rb +22 -0
  32. data/app/services/cmor/transports/exports/base.rb +74 -0
  33. data/app/services/cmor/transports/exports/csv_service.rb +32 -0
  34. data/app/services/cmor/transports/exports/json_service.rb +25 -0
  35. data/app/services/cmor/transports/exports/yaml_service.rb +25 -0
  36. data/app/services/cmor/transports/packs/base.rb +19 -0
  37. data/app/services/cmor/transports/packs/zip_service.rb +28 -0
  38. data/app/services/cmor/transports/transfers/api/incoming_state_service.rb +39 -0
  39. data/app/services/cmor/transports/transfers/api/push_service.rb +47 -0
  40. data/app/view_helpers/cmor/transports/application_view_helper.rb +6 -0
  41. data/app/view_helpers/cmor/transports/export_view_helper.rb +63 -0
  42. data/app/views/cmor/core/backend/resources_controller/base/_export_form.html.haml +3 -0
  43. data/app/views/cmor/core/backend/resources_controller/base/export.html.haml +6 -0
  44. data/app/views/cmor/transports/export_sidebars/show.html.haml +1 -0
  45. data/app/views/cmor/transports/exports/_after_show_table.html.haml +9 -0
  46. data/app/views/cmor/transports/exports/_form.html.haml +6 -0
  47. data/app/views/cmor/transports/exports/_index_table.html.haml +14 -0
  48. data/app/views/cmor/transports/exports/_show_table.html.haml +17 -0
  49. data/app/views/cmor/transports/incomings/_index_table.html.haml +12 -0
  50. data/app/views/cmor/transports/outgoings/_after_show_table.html.haml +26 -0
  51. data/app/views/cmor/transports/outgoings/_form.html.haml +2 -0
  52. data/app/views/cmor/transports/outgoings/_index_table.html.haml +8 -0
  53. data/app/views/cmor/transports/outgoings/_show_table.html.haml +11 -0
  54. data/config/initializers/assets.rb +2 -0
  55. data/config/initializers/cmor.rb +3 -0
  56. data/config/initializers/include_routing_concerns.rb +1 -0
  57. data/config/locales/de.yml +43 -0
  58. data/config/locales/en.yml +41 -0
  59. data/config/routes.rb +31 -0
  60. data/db/migrate/20200525095216_create_cmor_transports_exports.rb +20 -0
  61. data/db/migrate/20200607101713_create_cmor_transports_outgoings.rb +15 -0
  62. data/db/migrate/20200607102346_create_cmor_transports_outgoing_exports.rb +10 -0
  63. data/db/migrate/20200607105529_create_cmor_transports_systems.rb +11 -0
  64. data/db/migrate/20200607105839_create_cmor_transports_outgoing_targets.rb +10 -0
  65. data/db/migrate/20200607110930_create_cmor_transports_incomings.rb +16 -0
  66. data/db/migrate/20200607111046_create_cmor_transports_imports.rb +17 -0
  67. data/lib/cmor/transports/configuration.rb +41 -0
  68. data/lib/cmor/transports/engine.rb +19 -0
  69. data/lib/cmor/transports/version.rb +7 -0
  70. data/lib/cmor_transports.rb +18 -0
  71. data/lib/generators/cmor/transports/install/install_generator.rb +26 -0
  72. data/lib/generators/cmor/transports/install/templates/initializer.rb +45 -0
  73. data/lib/generators/cmor/transports/install/templates/routes.source +4 -0
  74. data/lib/tasks/cmor/transports_tasks.rake +5 -0
  75. data/spec/factories/cmor_transports_exports.rb +11 -0
  76. data/spec/factories/cmor_transports_imports.rb +7 -0
  77. data/spec/factories/cmor_transports_incomings.rb +7 -0
  78. data/spec/factories/cmor_transports_outgoing_exports.rb +8 -0
  79. data/spec/factories/cmor_transports_outgoing_targets.rb +8 -0
  80. data/spec/factories/cmor_transports_outgoings.rb +6 -0
  81. data/spec/factories/cmor_transports_systems.rb +9 -0
  82. data/spec/files/cmor/transports/outgoing/output/example.zip +0 -0
  83. metadata +601 -0
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Transports
4
+ class Incoming < ApplicationRecord
5
+ include Cmor::Transports::Models::UuidConcern
6
+ include AASM
7
+
8
+ belongs_to :creator, optional: true, polymorphic: true
9
+ # belongs_to :job, optional: true
10
+
11
+ has_one_attached :input
12
+ has_one_attached :payload
13
+
14
+ validates :outgoing_uuid, presence: true, uniqueness: true
15
+
16
+ aasm(:default, column: "state") do
17
+ state :created, initial: true
18
+ state :enqueued
19
+ state :processing
20
+ state :failed
21
+ state :succeeded
22
+
23
+ event :enqueue, after: :enqueue_service_call do
24
+ transitions from: :created, to: :enqueued
25
+ end
26
+
27
+ event :process do
28
+ transitions from: [:created, :enqueued], to: :processing
29
+ end
30
+
31
+ event :fail do
32
+ transitions from: :processing, to: :failed
33
+ end
34
+
35
+ event :succeed do
36
+ transitions from: :processing, to: :succeeded
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Transports
4
+ class Outgoing < ApplicationRecord
5
+ include Cmor::Transports::Models::UuidConcern
6
+ include AASM
7
+
8
+ belongs_to :creator, optional: true, polymorphic: true
9
+
10
+ has_many :outgoing_exports, dependent: :destroy
11
+ has_many :exports, through: :outgoing_exports
12
+
13
+ has_many :outgoing_targets, dependent: :destroy
14
+ has_many :systems, through: :outgoing_targets
15
+
16
+ has_one_attached :output
17
+
18
+ validates :state, presence: true
19
+
20
+ aasm(:default, column: "state") do
21
+ state :created, initial: true
22
+ state :enqueued_for_pack
23
+ state :packing
24
+ state :failed_packing
25
+ state :succeeded_packing
26
+ state :enqueued_for_transfer
27
+ state :transferring
28
+ state :failed_transferring
29
+ state :succeeded_transferring
30
+
31
+ event :enqueue_packing, after: :enqueue_packing_service_call do
32
+ transitions from: :created, to: :enqueued_for_pack
33
+ end
34
+
35
+ event :start_packing do
36
+ transitions from: :enqueued_for_pack, to: :packing
37
+ end
38
+
39
+ event :failed_packing do
40
+ transitions from: :packing, to: :failed_packing
41
+ end
42
+
43
+ event :succeed_packing do
44
+ transitions from: :packing, to: :succeeded_packing
45
+ end
46
+
47
+ event :reset_packing do
48
+ transitions from: [:enqueued_for_packing, :failed_packing], to: :created
49
+ end
50
+
51
+ event :enqueue_for_transfer, after: :enqueue_transferring_service_call do
52
+ transitions from: :succeeded_packing, to: :enqueued_for_transfer
53
+ end
54
+
55
+ event :start_transferring do
56
+ transitions from: :enqueued_for_transfer, to: :transferring
57
+ end
58
+
59
+ event :failed_transferring do
60
+ transitions from: :transferring, to: :failed_transferring
61
+ end
62
+
63
+ event :reset_transferring do
64
+ transitions from: [:enqueued_for_transfer, :failed_transferring], to: :succeeded_packing
65
+ end
66
+
67
+ event :succeed_transferring do
68
+ transitions from: :transferring, to: :succeeded_transferring
69
+ end
70
+ end
71
+
72
+ def enqueue_packing_service_call
73
+ result = pack_service_class_name.constantize.call_later!(outgoing: self)
74
+ self.job_id = result.job_id
75
+ end
76
+
77
+ def enqueue_transferring_service_call
78
+ result = transfer_service_class_name.constantize.call_later!(outgoing: self)
79
+ self.job_id = result.job_id
80
+ end
81
+
82
+ def pack_service_class_name
83
+ "Cmor::Transports::Packs::ZipService"
84
+ end
85
+
86
+ def transfer_service_class_name
87
+ "Cmor::Transports::Transfers::Api::PushService"
88
+ end
89
+
90
+ def output_base64
91
+ if output.attached?
92
+ Base64.encode64(output.attachment.blob.download)
93
+ else
94
+ nil
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Transports
4
+ class OutgoingExport < ApplicationRecord
5
+ belongs_to :outgoing
6
+ belongs_to :export
7
+ end
8
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Transports
4
+ class OutgoingTarget < ApplicationRecord
5
+ belongs_to :outgoing
6
+ belongs_to :system
7
+
8
+ delegate :identifier, :endpoint, :api_key, to: :system, prefix: true, allow_nil: true
9
+ delegate :uuid, to: :outgoing, prefix: true, allow_nil: true
10
+
11
+ def incoming_status
12
+ result = Cmor::Transports::Transfers::Api::IncomingStateService.call(system_identifier: system_identifier, endpoint: system_endpoint, api_key: system_api_key, outgoing_uuid: outgoing_uuid)
13
+ if result.ok?
14
+ result.incoming
15
+ else
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Transports
4
+ class System < ApplicationRecord
5
+ has_many :outgoing_targets
6
+
7
+ validates :identifier, presence: true, uniqueness: true
8
+ validates :endpoint, presence: true, uniqueness: true
9
+ validates :api_key, presence: true
10
+
11
+ def human
12
+ "#{identifier} | #{endpoint}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Api
6
+ module Incoming
7
+ class CreateService < Rao::Service::Base
8
+ class Result < Rao::Service::Result::Base
9
+ end
10
+
11
+ attr_accessor :outgoing, :incoming
12
+
13
+ validates :outgoing_output_base64, presence: true
14
+
15
+
16
+ def save
17
+ if @incoming.save
18
+ say "Saved incoming with id #{@incoming.id}"
19
+ else
20
+ add_error_and_say "Could not save incoming. Errors: #{@incoming.errors.full_messages.to_sentence}"
21
+ end
22
+ end
23
+
24
+ def outgoing_output_base64
25
+ outgoing["output_base64"] if outgoing.respond_to?(:[])
26
+ end
27
+
28
+ private
29
+ def _perform
30
+ build_incoming!
31
+ end
32
+
33
+ def build_incoming!
34
+ @incoming = Cmor::Transports::Incoming.new.tap do |i|
35
+ i.outgoing_uuid = outgoing["uuid"]
36
+ i.payload.attach(io: StringIO.new(Base64.decode64(outgoing["output_base64"])), filename: "payload.zip", content_type: "application/zip")
37
+ i.input.attach(io: StringIO.new(outgoing.to_json), filename: "outgoing.json", content_type: "application/json")
38
+ i
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Api
6
+ module Incoming
7
+ class ShowService < Rao::Service::Base
8
+ class Result < Rao::Service::Result::Base
9
+ attr_accessor :incoming
10
+ end
11
+
12
+ attr_accessor :outgoing_uuid
13
+
14
+ private
15
+ def _perform
16
+ @result.incoming = @incoming = Cmor::Transports::Incoming.where(outgoing_uuid: outgoing_uuid).first
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Exports
6
+ class Base < Rao::Service::Base
7
+ class Result < Rao::Service::Result::Base
8
+ attr_accessor :export
9
+ end
10
+
11
+ attr_accessor :export
12
+
13
+ private
14
+ def _perform
15
+ export.aasm.fire(:process)
16
+ generate_output!
17
+ if @errors.any?
18
+ export.aasm.fire(:fail)
19
+ return @result
20
+ end
21
+
22
+ attach_output_to_export!
23
+ if @errors.any?
24
+ export.aasm.fire(:fail)
25
+ return @result
26
+ end
27
+
28
+ export.aasm.fire(:succeed)
29
+ end
30
+
31
+ def after_perform
32
+ @export.service_errors = @errors.full_messages.to_sentence
33
+ @export.service_messages = @messages.map(&:to_s)
34
+ @result.export = @export
35
+ end
36
+
37
+ def save
38
+ export.save!
39
+ end
40
+
41
+ def generate_output!
42
+ raise "Child class responsibility"
43
+ end
44
+
45
+ def attach_output_to_export!
46
+ export.output.attach(attributes_for_attachment)
47
+ end
48
+
49
+ def attributes_for_attachment
50
+ raise "Child class responsibility"
51
+ end
52
+
53
+
54
+ def load_collection
55
+ resource_class.find_by_sql(export.query)
56
+ end
57
+
58
+ def resource_class
59
+ export.root_model.constantize
60
+ end
61
+
62
+ def resource_attributes
63
+ export.output_attributes || resource_class.attribute_names
64
+ end
65
+
66
+ def build_resource_hash(resource)
67
+ resource_attributes.each_with_object({}) do |attr, memo|
68
+ memo[attr] = resource.send(attr)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Cmor
6
+ module Transports
7
+ module Exports
8
+ class CsvService < Base
9
+ class Result < Base::Result
10
+ end
11
+
12
+ private
13
+ def generate_output!
14
+ @output = CSV.generate(headers: true) do |csv|
15
+ csv << resource_attributes
16
+ load_collection.each do |resource|
17
+ csv << build_resource_hash(resource).values
18
+ end
19
+ end
20
+ end
21
+
22
+ def attributes_for_attachment
23
+ {
24
+ io: StringIO.new(@output),
25
+ filename: "export_#{export.id}.csv",
26
+ content_type: "text/csv"
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Exports
6
+ class JsonService < Base
7
+ class Result < Base::Result
8
+ end
9
+
10
+ private
11
+ def generate_output!
12
+ @output = load_collection.collect { |r| build_resource_hash(r) }.to_json
13
+ end
14
+
15
+ def attributes_for_attachment
16
+ {
17
+ io: StringIO.new(@output),
18
+ filename: "export_#{export.id}.json",
19
+ content_type: "application/json"
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Exports
6
+ class YamlService < Base
7
+ class Result < Base::Result
8
+ end
9
+
10
+ private
11
+ def generate_output!
12
+ @output = load_collection.collect { |r| build_resource_hash(r) }.to_yaml
13
+ end
14
+
15
+ def attributes_for_attachment
16
+ {
17
+ io: StringIO.new(@output),
18
+ filename: "export_#{export.id}.yaml",
19
+ content_type: "application/x-yaml"
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Packs
6
+ class Base < Rao::Service::Base
7
+ class Result < Rao::Service::Result::Base
8
+ end
9
+
10
+ attr_accessor :outgoing
11
+
12
+ private
13
+ def _perform
14
+ pack_and_attach!
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Transports
5
+ module Packs
6
+ class ZipService < Base
7
+ private
8
+ def pack_and_attach!
9
+ outgoing.start_packing!
10
+ stringio = Zip::OutputStream.write_buffer do |zio|
11
+ outgoing.exports.map(&:output).each do |attachment|
12
+ zio.put_next_entry(attachment.filename)
13
+ zio.write attachment.blob.download
14
+ end
15
+ end
16
+
17
+ stringio.rewind
18
+
19
+ @outgoing.output.attach(io: stringio, filename: "output.zip", content_type: "application/zip")
20
+ outgoing.succeed_packing!
21
+ rescue => e
22
+ outgoing.failed_packing!
23
+ raise e
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end