motor-admin 0.1.34 → 0.1.40
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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb +70 -0
- data/app/controllers/motor/alerts_controller.rb +12 -6
- data/app/controllers/motor/audits_controller.rb +16 -0
- data/app/controllers/motor/configs_controller.rb +1 -0
- data/app/controllers/motor/dashboards_controller.rb +4 -0
- data/app/controllers/motor/data_controller.rb +2 -57
- data/app/controllers/motor/forms_controller.rb +4 -0
- data/app/controllers/motor/queries_controller.rb +4 -0
- data/app/controllers/motor/resources_controller.rb +1 -0
- data/app/controllers/motor/ui_controller.rb +4 -0
- data/app/models/motor/alert.rb +4 -2
- data/app/models/motor/application_record.rb +10 -0
- data/app/models/motor/audit.rb +9 -0
- data/app/models/motor/config.rb +2 -0
- data/app/models/motor/dashboard.rb +3 -1
- data/app/models/motor/form.rb +3 -1
- data/app/models/motor/query.rb +4 -1
- data/app/models/motor/resource.rb +2 -0
- data/app/views/motor/ui/show.html.erb +1 -1
- data/config/routes.rb +1 -0
- data/lib/generators/motor/templates/install.rb +40 -16
- data/lib/motor.rb +11 -2
- data/lib/motor/admin.rb +8 -0
- data/lib/motor/alerts/persistance.rb +17 -3
- data/lib/motor/alerts/scheduler.rb +1 -1
- data/lib/motor/api_query/sort.rb +1 -1
- data/lib/motor/build_schema.rb +3 -3
- data/lib/motor/build_schema/load_from_rails.rb +2 -1
- data/lib/motor/build_schema/merge_schema_configs.rb +8 -4
- data/lib/motor/build_schema/reorder_schema.rb +10 -4
- data/lib/motor/configs.rb +17 -0
- data/lib/motor/configs/build_configs_hash.rb +83 -0
- data/lib/motor/configs/build_ui_app_tag.rb +71 -0
- data/lib/motor/configs/load_from_cache.rb +81 -0
- data/lib/motor/configs/sync_from_file.rb +36 -0
- data/lib/motor/configs/sync_from_hash.rb +124 -0
- data/lib/motor/configs/sync_middleware.rb +72 -0
- data/lib/motor/configs/sync_with_remote.rb +47 -0
- data/lib/motor/configs/write_to_file.rb +36 -0
- data/lib/motor/dashboards/persistance.rb +15 -5
- data/lib/motor/forms/persistance.rb +15 -5
- data/lib/motor/net_http_utils.rb +38 -0
- data/lib/motor/queries/persistance.rb +13 -3
- data/lib/motor/railtie.rb +11 -0
- data/lib/motor/tasks/motor.rake +37 -0
- data/lib/motor/version.rb +1 -1
- data/ui/dist/{main-052729fa924c6434623f.css.gz → main-57d82791202293600221.css.gz} +0 -0
- data/ui/dist/main-57d82791202293600221.js.gz +0 -0
- data/ui/dist/manifest.json +5 -5
- metadata +33 -5
- data/lib/motor/ui_configs.rb +0 -82
- data/ui/dist/main-052729fa924c6434623f.js.gz +0 -0
@@ -29,16 +29,20 @@ module Motor
|
|
29
29
|
retry
|
30
30
|
end
|
31
31
|
|
32
|
-
def update_from_params!(form, params)
|
32
|
+
def update_from_params!(form, params, force_replace: false)
|
33
|
+
tag_ids = form.tags.ids
|
34
|
+
|
33
35
|
form = assign_attributes(form, params)
|
34
36
|
|
35
|
-
raise NameAlreadyExists if name_already_exists?(form)
|
37
|
+
raise NameAlreadyExists if !force_replace && name_already_exists?(form)
|
36
38
|
|
37
39
|
ApplicationRecord.transaction do
|
40
|
+
archive_with_existing_name(form) if force_replace
|
41
|
+
|
38
42
|
form.save!
|
39
43
|
end
|
40
44
|
|
41
|
-
form.tags.reload
|
45
|
+
form.touch if tag_ids.sort != form.tags.reload.ids.sort && params[:updated_at].blank?
|
42
46
|
|
43
47
|
form
|
44
48
|
rescue ActiveRecord::RecordNotUnique
|
@@ -47,15 +51,21 @@ module Motor
|
|
47
51
|
|
48
52
|
def assign_attributes(form, params)
|
49
53
|
form.assign_attributes(params.slice(:name, :description, :api_path, :http_method, :preferences))
|
54
|
+
form.updated_at = [params[:updated_at], Time.current].min if params[:updated_at].present?
|
50
55
|
|
51
56
|
Motor::Tags.assign_tags(form, params[:tags])
|
52
57
|
end
|
53
58
|
|
59
|
+
def archive_with_existing_name(form)
|
60
|
+
Motor::Form.where(['lower(name) = ? AND id != ?', form.name.to_s.downcase, form.id])
|
61
|
+
.update_all(deleted_at: Time.current)
|
62
|
+
end
|
63
|
+
|
54
64
|
def name_already_exists?(form)
|
55
65
|
if form.new_record?
|
56
|
-
Form.exists?(['lower(name) = ?', form.name.to_s.downcase])
|
66
|
+
Motor::Form.exists?(['lower(name) = ?', form.name.to_s.downcase])
|
57
67
|
else
|
58
|
-
Form.exists?(['lower(name) = ? AND id != ?', form.name.to_s.downcase, form.id])
|
68
|
+
Motor::Form.exists?(['lower(name) = ? AND id != ?', form.name.to_s.downcase, form.id])
|
59
69
|
end
|
60
70
|
end
|
61
71
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module NetHttpUtils
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def get(url, params = {}, headers = {})
|
8
|
+
request = build_request(Net::HTTP::Get, url, params, headers, nil)
|
9
|
+
|
10
|
+
execute_request(request)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post(url, params = {}, headers = {}, body = '')
|
14
|
+
request = build_request(Net::HTTP::Post, url, params, headers, body)
|
15
|
+
|
16
|
+
execute_request(request)
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_request(method_class, url, params, headers, body)
|
20
|
+
uri = URI(url)
|
21
|
+
uri.query = params.to_query
|
22
|
+
|
23
|
+
request = method_class.new(uri)
|
24
|
+
request.body = body if body.present?
|
25
|
+
headers.each { |key, value| request[key] = value }
|
26
|
+
|
27
|
+
request
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute_request(request)
|
31
|
+
uri = request.uri
|
32
|
+
|
33
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.port == 443) do |http|
|
34
|
+
http.request(request)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -29,16 +29,20 @@ module Motor
|
|
29
29
|
retry
|
30
30
|
end
|
31
31
|
|
32
|
-
def update_from_params!(query, params)
|
32
|
+
def update_from_params!(query, params, force_replace: false)
|
33
|
+
tag_ids = query.tags.ids
|
34
|
+
|
33
35
|
query = assign_attributes(query, params)
|
34
36
|
|
35
|
-
raise NameAlreadyExists if name_already_exists?(query)
|
37
|
+
raise NameAlreadyExists if !force_replace && name_already_exists?(query)
|
36
38
|
|
37
39
|
ApplicationRecord.transaction do
|
40
|
+
archive_with_existing_name(query) if force_replace
|
41
|
+
|
38
42
|
query.save!
|
39
43
|
end
|
40
44
|
|
41
|
-
query.tags.reload
|
45
|
+
query.touch if tag_ids.sort != query.tags.reload.ids.sort && params[:updated_at].blank?
|
42
46
|
|
43
47
|
query
|
44
48
|
rescue ActiveRecord::RecordNotUnique
|
@@ -47,10 +51,16 @@ module Motor
|
|
47
51
|
|
48
52
|
def assign_attributes(query, params)
|
49
53
|
query.assign_attributes(params.slice(:name, :description, :sql_body, :preferences))
|
54
|
+
query.updated_at = [params[:updated_at], Time.current].min if params[:updated_at].present?
|
50
55
|
|
51
56
|
Motor::Tags.assign_tags(query, params[:tags])
|
52
57
|
end
|
53
58
|
|
59
|
+
def archive_with_existing_name(query)
|
60
|
+
Motor::Query.where(['lower(name) = ? AND id != ?', query.name.to_s.downcase, query.id])
|
61
|
+
.update_all(deleted_at: Time.current)
|
62
|
+
end
|
63
|
+
|
54
64
|
def name_already_exists?(query)
|
55
65
|
if query.new_record?
|
56
66
|
Query.exists?(['lower(name) = ?', query.name.to_s.downcase])
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :motor do
|
4
|
+
desc 'Update configs/motor.yml file'
|
5
|
+
|
6
|
+
task dump: :environment do
|
7
|
+
Motor::Configs::WriteToFile.write_with_lock
|
8
|
+
|
9
|
+
puts '✅ configs/motor.yml has been updated'
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Load configs from configs/motor.yml file'
|
13
|
+
|
14
|
+
task load: :environment do
|
15
|
+
Motor::Configs::SyncFromFile.call(with_exception: true)
|
16
|
+
|
17
|
+
puts '✅ configs have been loaded from configs/motor.yml'
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Synchronize configs with remote application'
|
21
|
+
|
22
|
+
task sync: :environment do
|
23
|
+
remote_url = ENV['MOTOR_SYNC_REMOTE_URL']
|
24
|
+
api_key = ENV['MOTOR_SYNC_API_KEY']
|
25
|
+
|
26
|
+
raise 'Specify target app url using `MOTOR_SYNC_REMOTE_URL` env variable' if remote_url.blank?
|
27
|
+
raise 'Specify sync api key using `MOTOR_SYNC_API_KEY` env variable' if api_key.blank?
|
28
|
+
|
29
|
+
Motor::Configs::SyncWithRemote.call(remote_url, api_key)
|
30
|
+
Motor::Configs::WriteToFile.write_with_lock
|
31
|
+
|
32
|
+
puts "✅ Motor Admin configurations have been synced with #{remote_url}"
|
33
|
+
rescue Motor::Configs::SyncWithRemote::ApiNotFound
|
34
|
+
puts '⚠️ Synchronization failed: you need to specify `MOTOR_SYNC_API_KEY` ' \
|
35
|
+
'env variable in your remote app in order to enable this feature'
|
36
|
+
end
|
37
|
+
end
|
data/lib/motor/version.rb
CHANGED
Binary file
|
Binary file
|
data/ui/dist/manifest.json
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
"fonts/ionicons.ttf?v=3.0.0-alpha.3": "fonts/ionicons.ttf",
|
6
6
|
"fonts/ionicons.woff2?v=3.0.0-alpha.3": "fonts/ionicons.woff2",
|
7
7
|
"fonts/ionicons.woff?v=3.0.0-alpha.3": "fonts/ionicons.woff",
|
8
|
-
"main-
|
9
|
-
"main-
|
10
|
-
"main-
|
11
|
-
"main.css": "main-
|
12
|
-
"main.js": "main-
|
8
|
+
"main-57d82791202293600221.css.gz": "main-57d82791202293600221.css.gz",
|
9
|
+
"main-57d82791202293600221.js.LICENSE.txt": "main-57d82791202293600221.js.LICENSE.txt",
|
10
|
+
"main-57d82791202293600221.js.gz": "main-57d82791202293600221.js.gz",
|
11
|
+
"main.css": "main-57d82791202293600221.css",
|
12
|
+
"main.js": "main-57d82791202293600221.js"
|
13
13
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motor-admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.40
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pete Matsyburka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord-filter
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.6.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: audited
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.9'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.9'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: cancancan
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,12 +146,14 @@ files:
|
|
132
146
|
- LICENSE
|
133
147
|
- README.md
|
134
148
|
- Rakefile
|
149
|
+
- app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb
|
135
150
|
- app/controllers/concerns/motor/wrap_io_params.rb
|
136
151
|
- app/controllers/motor/active_storage_attachments_controller.rb
|
137
152
|
- app/controllers/motor/alerts_controller.rb
|
138
153
|
- app/controllers/motor/api_base_controller.rb
|
139
154
|
- app/controllers/motor/application_controller.rb
|
140
155
|
- app/controllers/motor/assets_controller.rb
|
156
|
+
- app/controllers/motor/audits_controller.rb
|
141
157
|
- app/controllers/motor/configs_controller.rb
|
142
158
|
- app/controllers/motor/dashboards_controller.rb
|
143
159
|
- app/controllers/motor/data_controller.rb
|
@@ -157,6 +173,7 @@ files:
|
|
157
173
|
- app/models/motor/alert.rb
|
158
174
|
- app/models/motor/alert_lock.rb
|
159
175
|
- app/models/motor/application_record.rb
|
176
|
+
- app/models/motor/audit.rb
|
160
177
|
- app/models/motor/config.rb
|
161
178
|
- app/models/motor/dashboard.rb
|
162
179
|
- app/models/motor/form.rb
|
@@ -200,22 +217,33 @@ files:
|
|
200
217
|
- lib/motor/build_schema/persist_resource_configs.rb
|
201
218
|
- lib/motor/build_schema/reorder_schema.rb
|
202
219
|
- lib/motor/build_schema/utils.rb
|
220
|
+
- lib/motor/configs.rb
|
221
|
+
- lib/motor/configs/build_configs_hash.rb
|
222
|
+
- lib/motor/configs/build_ui_app_tag.rb
|
223
|
+
- lib/motor/configs/load_from_cache.rb
|
224
|
+
- lib/motor/configs/sync_from_file.rb
|
225
|
+
- lib/motor/configs/sync_from_hash.rb
|
226
|
+
- lib/motor/configs/sync_middleware.rb
|
227
|
+
- lib/motor/configs/sync_with_remote.rb
|
228
|
+
- lib/motor/configs/write_to_file.rb
|
203
229
|
- lib/motor/dashboards.rb
|
204
230
|
- lib/motor/dashboards/persistance.rb
|
205
231
|
- lib/motor/forms.rb
|
206
232
|
- lib/motor/forms/persistance.rb
|
207
233
|
- lib/motor/hash_serializer.rb
|
234
|
+
- lib/motor/net_http_utils.rb
|
208
235
|
- lib/motor/queries.rb
|
209
236
|
- lib/motor/queries/persistance.rb
|
210
237
|
- lib/motor/queries/postgresql_exec_query.rb
|
211
238
|
- lib/motor/queries/render_sql_template.rb
|
212
239
|
- lib/motor/queries/run_query.rb
|
240
|
+
- lib/motor/railtie.rb
|
213
241
|
- lib/motor/tags.rb
|
214
|
-
- lib/motor/
|
242
|
+
- lib/motor/tasks/motor.rake
|
215
243
|
- lib/motor/version.rb
|
216
244
|
- ui/dist/fonts/ionicons.woff2
|
217
|
-
- ui/dist/main-
|
218
|
-
- ui/dist/main-
|
245
|
+
- ui/dist/main-57d82791202293600221.css.gz
|
246
|
+
- ui/dist/main-57d82791202293600221.js.gz
|
219
247
|
- ui/dist/manifest.json
|
220
248
|
homepage:
|
221
249
|
licenses:
|
data/lib/motor/ui_configs.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Motor
|
4
|
-
module UiConfigs
|
5
|
-
CACHE_STORE =
|
6
|
-
if Motor.development?
|
7
|
-
ActiveSupport::Cache::NullStore.new
|
8
|
-
else
|
9
|
-
ActiveSupport::Cache::MemoryStore.new(size: 5.megabytes)
|
10
|
-
end
|
11
|
-
|
12
|
-
module_function
|
13
|
-
|
14
|
-
# @return [String]
|
15
|
-
def app_tag
|
16
|
-
CACHE_STORE.fetch(cache_key) do
|
17
|
-
CACHE_STORE.clear
|
18
|
-
|
19
|
-
Motor::ApplicationController.helpers.content_tag(
|
20
|
-
:div, '', id: 'app', data: ui_data
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# @return [Hash]
|
26
|
-
def ui_data
|
27
|
-
{
|
28
|
-
base_path: Motor::Admin.routes.url_helpers.motor_path,
|
29
|
-
schema: Motor::BuildSchema.call,
|
30
|
-
header_links: header_links_data_hash,
|
31
|
-
queries: queries_data_hash,
|
32
|
-
dashboards: dashboards_data_hash,
|
33
|
-
alerts: alerts_data_hash,
|
34
|
-
forms: forms_data_hash
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
|
-
def header_links_data_hash
|
39
|
-
Motor::Config.find_by(key: 'header.links')&.value || []
|
40
|
-
end
|
41
|
-
|
42
|
-
def queries_data_hash
|
43
|
-
Motor::Query.all.active.preload(:tags)
|
44
|
-
.as_json(only: %i[id name updated_at],
|
45
|
-
include: { tags: { only: %i[id name] } })
|
46
|
-
end
|
47
|
-
|
48
|
-
def dashboards_data_hash
|
49
|
-
Motor::Dashboard.all.active.preload(:tags)
|
50
|
-
.as_json(only: %i[id title updated_at],
|
51
|
-
include: { tags: { only: %i[id name] } })
|
52
|
-
end
|
53
|
-
|
54
|
-
def alerts_data_hash
|
55
|
-
Motor::Alert.all.active.preload(:tags)
|
56
|
-
.as_json(only: %i[id name is_enabled updated_at],
|
57
|
-
include: { tags: { only: %i[id name] } })
|
58
|
-
end
|
59
|
-
|
60
|
-
def forms_data_hash
|
61
|
-
Motor::Form.all.active.preload(:tags)
|
62
|
-
.as_json(only: %i[id name updated_at],
|
63
|
-
include: { tags: { only: %i[id name] } })
|
64
|
-
end
|
65
|
-
|
66
|
-
# @return [String]
|
67
|
-
def cache_key
|
68
|
-
ActiveRecord::Base.connection.execute(
|
69
|
-
"(#{
|
70
|
-
[
|
71
|
-
Motor::Config.select('MAX(updated_at)').to_sql,
|
72
|
-
Motor::Resource.select('MAX(updated_at)').to_sql,
|
73
|
-
Motor::Dashboard.select('MAX(updated_at)').to_sql,
|
74
|
-
Motor::Alert.select('MAX(updated_at)').to_sql,
|
75
|
-
Motor::Query.select('MAX(updated_at)').to_sql,
|
76
|
-
Motor::Form.select('MAX(updated_at)').to_sql
|
77
|
-
].join(') UNION (')
|
78
|
-
})"
|
79
|
-
).to_a.hash.to_s
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
Binary file
|