prelands_rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +1456 -0
- data/LICENSE.txt +21 -0
- data/Makefile +4 -0
- data/README.md +4 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/prelands_rails/concerns/abstract_interactor.rb +48 -0
- data/lib/prelands_rails/concerns/base.rb +25 -0
- data/lib/prelands_rails/concerns/can_handle_errors.rb +31 -0
- data/lib/prelands_rails/concerns/hash.rb +11 -0
- data/lib/prelands_rails/concerns/my_aws_client.rb +123 -0
- data/lib/prelands_rails/create_simple_source/check_zip_files/detect_absent_files.rb +25 -0
- data/lib/prelands_rails/create_simple_source/check_zip_files/extract_files.rb +31 -0
- data/lib/prelands_rails/create_simple_source/check_zip_files.rb +79 -0
- data/lib/prelands_rails/create_simple_source/compile/html_compiler.rb +106 -0
- data/lib/prelands_rails/create_simple_source/compile.rb +44 -0
- data/lib/prelands_rails/create_simple_source/create_record.rb +44 -0
- data/lib/prelands_rails/create_simple_source/detect_incoming_locales.rb +35 -0
- data/lib/prelands_rails/create_simple_source/upload/uploader.rb +47 -0
- data/lib/prelands_rails/create_simple_source/upload.rb +83 -0
- data/lib/prelands_rails/create_simple_source/validate_zip_content/validate_html/html.rb +115 -0
- data/lib/prelands_rails/create_simple_source/validate_zip_content/validate_html.rb +40 -0
- data/lib/prelands_rails/create_simple_source/validate_zip_content/validate_js/js.rb +62 -0
- data/lib/prelands_rails/create_simple_source/validate_zip_content/validate_js.rb +32 -0
- data/lib/prelands_rails/create_simple_source/validate_zip_content.rb +26 -0
- data/lib/prelands_rails/create_simple_source.rb +48 -0
- data/lib/prelands_rails/update_simple_source/check_zip_files.rb +39 -0
- data/lib/prelands_rails/update_simple_source/compile.rb +38 -0
- data/lib/prelands_rails/update_simple_source/update_record.rb +41 -0
- data/lib/prelands_rails/update_simple_source/upload/delete_compiled_files.rb +30 -0
- data/lib/prelands_rails/update_simple_source/upload.rb +43 -0
- data/lib/prelands_rails/update_simple_source/validate_zip_content.rb +35 -0
- data/lib/prelands_rails/update_simple_source.rb +48 -0
- data/lib/prelands_rails/validate_simple_source.rb +26 -0
- data/lib/prelands_rails/version.rb +3 -0
- data/lib/prelands_rails.rb +41 -0
- data/prelands_rails.gemspec +48 -0
- metadata +314 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
class Upload
|
6
|
+
#
|
7
|
+
# Загрузчик файлов на AWS.
|
8
|
+
#
|
9
|
+
class Uploader
|
10
|
+
def initialize(creds, aws_prefix, client_class = ::PrelandsRails::MyAwsClient)
|
11
|
+
@folder = aws_prefix
|
12
|
+
@client = client_class.new creds[:access_key], creds[:secret_key], creds[:region]
|
13
|
+
end
|
14
|
+
|
15
|
+
# На вход подан путь к файлу на хосте, который грузим на aws с указанным именем.
|
16
|
+
#
|
17
|
+
# @param [String] file_path
|
18
|
+
# @param [String] s3_file_name
|
19
|
+
# @param [String] bucket_name
|
20
|
+
|
21
|
+
def upload_file(s3_file_name, file_path, bucket_name)
|
22
|
+
@client.upload_file file_path, path(s3_file_name), bucket_name
|
23
|
+
end
|
24
|
+
|
25
|
+
# На вход подана строка +file_content+. Сохраняем её, как файл с указанным именем.
|
26
|
+
#
|
27
|
+
# @param [String] s3_file_name
|
28
|
+
# @param [String] file_content
|
29
|
+
# @param [String] bucket_name
|
30
|
+
|
31
|
+
def upload_content(s3_file_name, file_content, bucket_name)
|
32
|
+
Tempfile.create(SecureRandom.uuid) do |file|
|
33
|
+
file.write file_content.force_encoding('utf-8')
|
34
|
+
file.close
|
35
|
+
@client.upload_file file.path, path(s3_file_name), bucket_name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def path(file)
|
42
|
+
[@folder, file].join('/')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
#
|
6
|
+
# Загрузит на aws скомпилированные html, icon.ico, index.js и содержимое директории images/
|
7
|
+
#
|
8
|
+
class Upload
|
9
|
+
include ::PrelandsRails::AbstractInteractor
|
10
|
+
include ::Interactor
|
11
|
+
include ::Interactor::Contracts
|
12
|
+
include ::PrelandsRails::Base
|
13
|
+
|
14
|
+
expects do
|
15
|
+
required(:archive).filled # Входящий архив с исходниками от фрилансера. Rack::Test::UploadedFile | ActionDispatch::Http::UploadedFile
|
16
|
+
required(:compiled_htmls).value(type?: Hash) # скомпилированные исходники { file_name[String] => compiled_content[String], ... }
|
17
|
+
required(:s3_credentials).schema do
|
18
|
+
required(:access_key).filled(:str?)
|
19
|
+
required(:secret_key).filled(:str?)
|
20
|
+
required(:region).filled(:str?)
|
21
|
+
end
|
22
|
+
required(:bucket_names).value(type?: Array)
|
23
|
+
required(:aws_prefix).value(type?: String)
|
24
|
+
required(:files_content).value(type?: Hash) # { file_name => file_content, ... }
|
25
|
+
end
|
26
|
+
|
27
|
+
assures do
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
@uploader = Uploader.new(context.s3_credentials, context.aws_prefix)
|
33
|
+
end
|
34
|
+
|
35
|
+
def act
|
36
|
+
context.bucket_names.each do |bucket_name|
|
37
|
+
images_files.map do |file_name, file_path|
|
38
|
+
@uploader.upload_file file_name, file_path, bucket_name
|
39
|
+
end
|
40
|
+
|
41
|
+
compiled_html_files.map do |file_name, content|
|
42
|
+
@uploader.upload_content file_name, content, bucket_name
|
43
|
+
end
|
44
|
+
|
45
|
+
@uploader.upload_content 'index.js', context.files_content['index.js'], bucket_name
|
46
|
+
end
|
47
|
+
|
48
|
+
del_tmp_files
|
49
|
+
context.uploaded_images = images_files
|
50
|
+
end
|
51
|
+
|
52
|
+
on_breach { |breaches| bad_expects breaches }
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
IMAGES = /\A(images\/.+|icon\.ico)\z/
|
57
|
+
|
58
|
+
def images_files
|
59
|
+
return @images_files if defined?(@images_files)
|
60
|
+
|
61
|
+
@tmp_paths = []
|
62
|
+
|
63
|
+
@images_files ||= Zip::File.open(context.archive.tempfile) do |zipfile|
|
64
|
+
zipfile.map do |entry|
|
65
|
+
next if entry.name.index(IMAGES) != 0
|
66
|
+
|
67
|
+
tmp_path = Rails.root.join make_tmp_path
|
68
|
+
entry.extract tmp_path
|
69
|
+
@tmp_paths << tmp_path
|
70
|
+
|
71
|
+
[entry.name, tmp_path]
|
72
|
+
end.compact.to_h
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def del_tmp_files
|
77
|
+
@tmp_paths.each do |path|
|
78
|
+
File.delete(path) if File.exists?(path)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
class ValidateZipContent
|
6
|
+
class ValidateHtml
|
7
|
+
#
|
8
|
+
# Принимает строку с html разметкой и валидирует её.
|
9
|
+
#
|
10
|
+
class Html
|
11
|
+
attr_reader :errors
|
12
|
+
|
13
|
+
# @param [String] string Содержимое html файла.
|
14
|
+
def initialize(string, continue_id)
|
15
|
+
@errors = []
|
16
|
+
@continue_id = continue_id
|
17
|
+
@string = string.gsub(/(\r\n?|\n)/, '') # убираем переносы, мешающие регуляркам
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
@errors = [
|
22
|
+
check_internal_scripts,
|
23
|
+
check_internal_styles,
|
24
|
+
check_continue_element,
|
25
|
+
check_js_plug,
|
26
|
+
check_css_plug,
|
27
|
+
check_title_presence,
|
28
|
+
check_a_hrefs,
|
29
|
+
check_favicon
|
30
|
+
].compact
|
31
|
+
|
32
|
+
!@errors.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# @return [nil] Если внутри html НЕ содержится JavaScript код в виде <script>...</script>
|
38
|
+
# @return [String] Иначе - вернёт сообщение об ошибке
|
39
|
+
def check_internal_scripts
|
40
|
+
rx = /<script[^>]*>([^<]+)<\/script>/
|
41
|
+
return unless any(rx)
|
42
|
+
|
43
|
+
'A JavaScript code is detected inside html-file. Please, move it to index.js.'
|
44
|
+
end
|
45
|
+
|
46
|
+
def check_internal_styles
|
47
|
+
rx = /<style[^>]*>([^<]+)<\/style>/
|
48
|
+
return unless any(rx)
|
49
|
+
|
50
|
+
'An internal CSS is detected inside html-file. Please, move it to index.css.'
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_continue_element
|
54
|
+
rx = Regexp.new('id="%s"' % @continue_id)
|
55
|
+
res = @string.scan(rx).flatten
|
56
|
+
return if res.size == 1
|
57
|
+
|
58
|
+
return 'The continue element with id="%s" must be uniq. Found %s matches.' % [@continue_id, res.size] if res.size > 1
|
59
|
+
|
60
|
+
'Not found continue element with id="%s"' % @continue_id
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_js_plug
|
64
|
+
body_rx = /<body[^>]*>(.+)<\/body>/
|
65
|
+
js_rx = '<script src="index.js"'
|
66
|
+
|
67
|
+
@string[body_rx]
|
68
|
+
res = $1&.[](js_rx)
|
69
|
+
return if res.present?
|
70
|
+
|
71
|
+
'Plug index.js script before closing tag of body.'
|
72
|
+
end
|
73
|
+
|
74
|
+
def check_css_plug
|
75
|
+
head_rx = /(?<=<head)(.+)(?=<\/head>)/
|
76
|
+
css_rx = 'href="index.css"'
|
77
|
+
|
78
|
+
@string[head_rx]
|
79
|
+
res = $1&.[](css_rx)
|
80
|
+
return if res.present?
|
81
|
+
|
82
|
+
'Plug index.css before closing tag of head.'
|
83
|
+
end
|
84
|
+
|
85
|
+
def check_title_presence
|
86
|
+
title_rx = /<title>[^<]+<\/title>/
|
87
|
+
return if @string[title_rx]
|
88
|
+
|
89
|
+
'Tag <title> not found.'
|
90
|
+
end
|
91
|
+
|
92
|
+
def check_a_hrefs
|
93
|
+
ahref_rx = /<a[^>]+href="[^"]+"/
|
94
|
+
return unless @string[ahref_rx]
|
95
|
+
|
96
|
+
'Links with href attribute found.'
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_favicon
|
100
|
+
favicon_rx = '<link rel="shortcut icon" href="icon.ico">'
|
101
|
+
return if @string[favicon_rx]
|
102
|
+
|
103
|
+
'<link rel="shortcut icon" href="icon.ico"> not found.'
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
def any(regex)
|
109
|
+
@string.scan(regex).flatten.map(&:strip).map(&:present?).any?
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
class ValidateZipContent
|
6
|
+
#
|
7
|
+
# Валидирует все html файлы.
|
8
|
+
#
|
9
|
+
class ValidateHtml
|
10
|
+
include ::PrelandsRails::AbstractInteractor
|
11
|
+
include ::Interactor
|
12
|
+
include ::Interactor::Contracts
|
13
|
+
include ::PrelandsRails::Base
|
14
|
+
|
15
|
+
CONTINUE_ID = 'continue'
|
16
|
+
|
17
|
+
expects do
|
18
|
+
required(:files_content).value(type?: Hash) # { file_name => file_content, ... }
|
19
|
+
end
|
20
|
+
|
21
|
+
assures do
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def act
|
26
|
+
errors =
|
27
|
+
incoming_html_files.map do |key, content|
|
28
|
+
content = Html.new(content, CONTINUE_ID)
|
29
|
+
next if content.valid?
|
30
|
+
[key, content.errors]
|
31
|
+
end.compact.to_h
|
32
|
+
|
33
|
+
fail! errors: errors if errors.any?
|
34
|
+
end
|
35
|
+
|
36
|
+
on_breach { |breaches| bad_expects breaches }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
class ValidateZipContent
|
6
|
+
class ValidateJs
|
7
|
+
#
|
8
|
+
# Принимает строку с JavaScript кодом разметкой и валидирует её.
|
9
|
+
#
|
10
|
+
class Js
|
11
|
+
attr_reader :errors
|
12
|
+
|
13
|
+
# @param [String] string Содержимое JavaScript файла.
|
14
|
+
def initialize(string)
|
15
|
+
@errors = []
|
16
|
+
@string = string.gsub(/(\r\n?|\n)/, '') # убираем переносы, мешающие регуляркам
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
@errors = [
|
21
|
+
check_location_changes,
|
22
|
+
check_framework_calls
|
23
|
+
].compact
|
24
|
+
|
25
|
+
!@errors.any?
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def check_location_changes
|
31
|
+
match_data = @string.match LOCATION_RX
|
32
|
+
is_loc_assign = ->(matched) { matched =~ /^('|")$/ || @string.match(/(;|\s*)#{matched}\s*=\s*('|")/) }
|
33
|
+
return unless match_data && is_loc_assign[match_data[3]]
|
34
|
+
|
35
|
+
'Location statement has found'
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_framework_calls
|
39
|
+
res = FUNCS_RX.map do |key, func|
|
40
|
+
[ key, !!@string[func] ]
|
41
|
+
end
|
42
|
+
|
43
|
+
return if res.map { |kf| kf[1] }.all?
|
44
|
+
|
45
|
+
res.to_h.map do |key, result|
|
46
|
+
'Call of %s() not found' % key if !result
|
47
|
+
end.compact.join('; ')
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
LOCATION_RX = /(;|\s*)location(\.href\s*=|\.replace\(|\.assign\(|\s*=)\s*(\w+|"|')/
|
53
|
+
FUNCS_RX = {
|
54
|
+
post_email: /post_email\([^)]+\)/,
|
55
|
+
post_gender: /post_gender\([^)]+\)/,
|
56
|
+
post_age: /post_age\([^)]+\)/
|
57
|
+
}.freeze
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
class ValidateZipContent
|
6
|
+
#
|
7
|
+
# Валидирует JavaScript код.
|
8
|
+
#
|
9
|
+
class ValidateJs
|
10
|
+
include ::PrelandsRails::AbstractInteractor
|
11
|
+
include ::Interactor
|
12
|
+
include ::Interactor::Contracts
|
13
|
+
|
14
|
+
expects do
|
15
|
+
required(:files_content).value(type?: Hash) # { file_name => file_content, ... }
|
16
|
+
end
|
17
|
+
|
18
|
+
assures do
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def act
|
23
|
+
content = context[:files_content]['index.js']
|
24
|
+
content = Js.new(content)
|
25
|
+
fail! errors: {'index.js' => content.errors} unless content.valid?
|
26
|
+
end
|
27
|
+
|
28
|
+
on_breach { |breaches| bad_expects breaches }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class CreateSimpleSource
|
5
|
+
#
|
6
|
+
# Примет содержимое файлов и валидирует их контент.
|
7
|
+
#
|
8
|
+
class ValidateZipContent
|
9
|
+
include ::PrelandsRails::AbstractInteractor
|
10
|
+
include ::Interactor::Organizer
|
11
|
+
include ::Interactor::Contracts
|
12
|
+
|
13
|
+
expects do
|
14
|
+
required(:files_content).value(type?: Hash) # { file_name[String] => file_content[String], ... }
|
15
|
+
end
|
16
|
+
|
17
|
+
assures do
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
organize ValidateHtml, ValidateJs#, ValidateCss
|
22
|
+
|
23
|
+
on_breach { |breaches| bad_expects breaches }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
#
|
5
|
+
# Примет zip-файл с исходниками преленда и опубликует этот преленд.
|
6
|
+
#
|
7
|
+
class CreateSimpleSource
|
8
|
+
include ::PrelandsRails::AbstractInteractor
|
9
|
+
include ::Interactor::Organizer
|
10
|
+
include ::Interactor::Contracts
|
11
|
+
|
12
|
+
expects do
|
13
|
+
required(:archive).filled # Входящий архив с исходниками от фрилансера. Rack::Test::UploadedFile | ActionDispatch::Http::UploadedFile
|
14
|
+
required(:preland_domain_ids).filled(type?: Array)
|
15
|
+
required(:expected_locales).filled(type?: Array) # Список локалей, для которых must were all index_<locale>.html files in the zip archive
|
16
|
+
required(:s3_credentials).schema do
|
17
|
+
required(:access_key).filled(:str?)
|
18
|
+
required(:secret_key).filled(:str?)
|
19
|
+
required(:region).filled(:str?)
|
20
|
+
end
|
21
|
+
required(:bucket_names).filled(type?: Array)
|
22
|
+
required(:aws_prefix).value(type?: String) # имя директории в букете
|
23
|
+
required(:preland_id).filled
|
24
|
+
required(:static_js_path).value(type?: String) # путь к размещённым в интернете нашим js скриптам
|
25
|
+
required(:model_preland_simple_source).filled
|
26
|
+
end
|
27
|
+
|
28
|
+
before do
|
29
|
+
fail!(errors: 'Preland domains missing') if context.preland_domain_ids.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
assures do
|
33
|
+
required(:incoming_locales).filled(type?: Array)
|
34
|
+
required(:files_content).value(type?: Hash) # распакованные файлы из архива { file_name[String] => file_content[String], ... }
|
35
|
+
required(:compiled_htmls).value(type?: Hash) # скомпилированные исходники { file_name[String] => compiled_content[String], ... }
|
36
|
+
required(:preland_simple_source).filled
|
37
|
+
end
|
38
|
+
|
39
|
+
organize DetectIncomingLocales,
|
40
|
+
CheckZipFiles,
|
41
|
+
ValidateZipContent,
|
42
|
+
Compile,
|
43
|
+
Upload,
|
44
|
+
CreateRecord
|
45
|
+
|
46
|
+
on_breach { |breaches| bad_expects breaches }
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class UpdateSimpleSource
|
5
|
+
|
6
|
+
class CheckZipFiles
|
7
|
+
include ::PrelandsRails::AbstractInteractor
|
8
|
+
include ::Interactor
|
9
|
+
include ::Interactor::Contracts
|
10
|
+
|
11
|
+
expects do
|
12
|
+
required(:archive) # Rack::Test::UploadedFile | ActionDispatch::Http::UploadedFile
|
13
|
+
required(:expected_locales).value(type?: Array)
|
14
|
+
required(:incoming_locales).filled(type?: Array)
|
15
|
+
end
|
16
|
+
|
17
|
+
assures do
|
18
|
+
optional(:files_content).maybe(type?: Hash) # js,html,css: { file_name => file_content, ... }
|
19
|
+
end
|
20
|
+
|
21
|
+
before do
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def act
|
26
|
+
if context.archive
|
27
|
+
result = ::PrelandsRails::CreateSimpleSource::CheckZipFiles.call context
|
28
|
+
if result.success?
|
29
|
+
context.files_content = result.files_content
|
30
|
+
else
|
31
|
+
fail!(errors: result.errors)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
on_breach { |breaches| bad_expects breaches }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class UpdateSimpleSource
|
5
|
+
|
6
|
+
class Compile
|
7
|
+
include ::PrelandsRails::AbstractInteractor
|
8
|
+
include ::Interactor
|
9
|
+
include ::Interactor::Contracts
|
10
|
+
|
11
|
+
expects do
|
12
|
+
optional(:files_content).maybe(type?: Hash) # js,html,css: { file_name => file_content, ... }
|
13
|
+
required(:static_js_path).value(type?: String)
|
14
|
+
end
|
15
|
+
|
16
|
+
assures do
|
17
|
+
optional(:compiled_htmls).value(type?: Hash) # { file_name[String] => compiled_content[String], ... }
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def act
|
25
|
+
if context.files_content
|
26
|
+
result = ::PrelandsRails::CreateSimpleSource::Compile.call context
|
27
|
+
if result.success?
|
28
|
+
context.compiled_htmls = result.compiled_htmls
|
29
|
+
else
|
30
|
+
fail!(errors: result.errors)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
on_breach { |breaches| bad_expects breaches }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module PrelandsRails
|
2
|
+
class UpdateSimpleSource
|
3
|
+
#
|
4
|
+
# обновит запись ::Preland::SimpleSource
|
5
|
+
#
|
6
|
+
class UpdateRecord
|
7
|
+
include ::PrelandsRails::AbstractInteractor
|
8
|
+
include ::Interactor
|
9
|
+
include ::Interactor::Contracts
|
10
|
+
include ::PrelandsRails::Base
|
11
|
+
|
12
|
+
expects do
|
13
|
+
required(:archive) # Входящий архив с исходниками от фрилансера. Rack::Test::UploadedFile | ActionDispatch::Http::UploadedFile
|
14
|
+
required(:aws_prefix).value(type?: String) # имя директории в букете
|
15
|
+
required(:preland_id).filled
|
16
|
+
required(:preland_domain_ids).value(type?: Array)
|
17
|
+
required(:incoming_locales).filled(type?: Array)
|
18
|
+
required(:model_preland_simple_source).filled
|
19
|
+
end
|
20
|
+
|
21
|
+
assures do
|
22
|
+
required(:preland_simple_source).filled
|
23
|
+
end
|
24
|
+
|
25
|
+
before do
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def act
|
30
|
+
source = context.model_preland_simple_source.find_by aws_prefix: context.aws_prefix
|
31
|
+
source.archive = context.archive if context.archive
|
32
|
+
source.preland_domain_ids = context.preland_domain_ids
|
33
|
+
source.locales = context.incoming_locales
|
34
|
+
source.save!
|
35
|
+
context.preland_simple_source = source
|
36
|
+
end
|
37
|
+
|
38
|
+
on_breach { |breaches| bad_expects breaches }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class UpdateSimpleSource
|
5
|
+
class Upload
|
6
|
+
#
|
7
|
+
# Удалить из +bucket_names+ файлы преленда из директории +aws_prefix+.
|
8
|
+
#
|
9
|
+
module DeleteCompiledFiles
|
10
|
+
def delete_compiled_files
|
11
|
+
creds = context.s3_credentials
|
12
|
+
client = ::PrelandsRails::MyAwsClient.new creds[:access_key], creds[:secret_key], creds[:region]
|
13
|
+
|
14
|
+
context.bucket_names.each do |bucket_name|
|
15
|
+
files = client.list_objects bucket_name
|
16
|
+
next unless files
|
17
|
+
|
18
|
+
files = files.map do |file_name|
|
19
|
+
{ key: file_name } if file_name.index(context.aws_prefix) == 0
|
20
|
+
end.compact
|
21
|
+
|
22
|
+
next if files.empty?
|
23
|
+
|
24
|
+
client.delete_objects bucket_name, files
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class UpdateSimpleSource
|
5
|
+
|
6
|
+
class Upload
|
7
|
+
include ::PrelandsRails::AbstractInteractor
|
8
|
+
include ::Interactor
|
9
|
+
include ::Interactor::Contracts
|
10
|
+
include DeleteCompiledFiles
|
11
|
+
|
12
|
+
expects do
|
13
|
+
required(:archive) # Входящий архив с исходниками от фрилансера. Rack::Test::UploadedFile | ActionDispatch::Http::UploadedFile
|
14
|
+
optional(:compiled_htmls).maybe(type?: Hash) # скомпилированные исходники { file_name[String] => compiled_content[String], ... }
|
15
|
+
required(:s3_credentials).schema do
|
16
|
+
required(:access_key).filled(:str?)
|
17
|
+
required(:secret_key).filled(:str?)
|
18
|
+
required(:region).filled(:str?)
|
19
|
+
end
|
20
|
+
required(:bucket_names).value(type?: Array)
|
21
|
+
required(:aws_prefix).value(type?: String)
|
22
|
+
optional(:files_content).maybe(type?: Hash) # js,html,css: { file_name => file_content, ... }
|
23
|
+
end
|
24
|
+
|
25
|
+
assures do
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
before do
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def act
|
34
|
+
if context.archive && context.compiled_htmls && context.files_content
|
35
|
+
delete_compiled_files
|
36
|
+
::PrelandsRails::CreateSimpleSource::Upload.call context
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
on_breach { |breaches| bad_expects breaches }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrelandsRails
|
4
|
+
class UpdateSimpleSource
|
5
|
+
|
6
|
+
class ValidateZipContent
|
7
|
+
include ::PrelandsRails::AbstractInteractor
|
8
|
+
include ::Interactor
|
9
|
+
include ::Interactor::Contracts
|
10
|
+
|
11
|
+
expects do
|
12
|
+
optional(:files_content).maybe(type?: Hash) # js,html,css: { file_name => file_content, ... }
|
13
|
+
end
|
14
|
+
|
15
|
+
assures do
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
before do
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def act
|
24
|
+
if context.files_content
|
25
|
+
result = ::PrelandsRails::CreateSimpleSource::ValidateZipContent.call context
|
26
|
+
unless result.success?
|
27
|
+
fail!(errors: result.errors)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
on_breach { |breaches| bad_expects breaches }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|