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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb +70 -0
  3. data/app/controllers/motor/alerts_controller.rb +12 -6
  4. data/app/controllers/motor/audits_controller.rb +16 -0
  5. data/app/controllers/motor/configs_controller.rb +1 -0
  6. data/app/controllers/motor/dashboards_controller.rb +4 -0
  7. data/app/controllers/motor/data_controller.rb +2 -57
  8. data/app/controllers/motor/forms_controller.rb +4 -0
  9. data/app/controllers/motor/queries_controller.rb +4 -0
  10. data/app/controllers/motor/resources_controller.rb +1 -0
  11. data/app/controllers/motor/ui_controller.rb +4 -0
  12. data/app/models/motor/alert.rb +4 -2
  13. data/app/models/motor/application_record.rb +10 -0
  14. data/app/models/motor/audit.rb +9 -0
  15. data/app/models/motor/config.rb +2 -0
  16. data/app/models/motor/dashboard.rb +3 -1
  17. data/app/models/motor/form.rb +3 -1
  18. data/app/models/motor/query.rb +4 -1
  19. data/app/models/motor/resource.rb +2 -0
  20. data/app/views/motor/ui/show.html.erb +1 -1
  21. data/config/routes.rb +1 -0
  22. data/lib/generators/motor/templates/install.rb +40 -16
  23. data/lib/motor.rb +11 -2
  24. data/lib/motor/admin.rb +8 -0
  25. data/lib/motor/alerts/persistance.rb +17 -3
  26. data/lib/motor/alerts/scheduler.rb +1 -1
  27. data/lib/motor/api_query/sort.rb +1 -1
  28. data/lib/motor/build_schema.rb +3 -3
  29. data/lib/motor/build_schema/load_from_rails.rb +2 -1
  30. data/lib/motor/build_schema/merge_schema_configs.rb +8 -4
  31. data/lib/motor/build_schema/reorder_schema.rb +10 -4
  32. data/lib/motor/configs.rb +17 -0
  33. data/lib/motor/configs/build_configs_hash.rb +83 -0
  34. data/lib/motor/configs/build_ui_app_tag.rb +71 -0
  35. data/lib/motor/configs/load_from_cache.rb +81 -0
  36. data/lib/motor/configs/sync_from_file.rb +36 -0
  37. data/lib/motor/configs/sync_from_hash.rb +124 -0
  38. data/lib/motor/configs/sync_middleware.rb +72 -0
  39. data/lib/motor/configs/sync_with_remote.rb +47 -0
  40. data/lib/motor/configs/write_to_file.rb +36 -0
  41. data/lib/motor/dashboards/persistance.rb +15 -5
  42. data/lib/motor/forms/persistance.rb +15 -5
  43. data/lib/motor/net_http_utils.rb +38 -0
  44. data/lib/motor/queries/persistance.rb +13 -3
  45. data/lib/motor/railtie.rb +11 -0
  46. data/lib/motor/tasks/motor.rake +37 -0
  47. data/lib/motor/version.rb +1 -1
  48. data/ui/dist/{main-052729fa924c6434623f.css.gz → main-57d82791202293600221.css.gz} +0 -0
  49. data/ui/dist/main-57d82791202293600221.js.gz +0 -0
  50. data/ui/dist/manifest.json +5 -5
  51. metadata +33 -5
  52. data/lib/motor/ui_configs.rb +0 -82
  53. data/ui/dist/main-052729fa924c6434623f.js.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d39e56e7ea8a0b52d05594f2b1fb6f12860d9fd5771fbcf9bec758ce5752f08
4
- data.tar.gz: 5cd61073f5a310dd5562225476134358cec33ab1df16983b0faca249a434c91e
3
+ metadata.gz: c650dcb3b3585c6776bb7ece77590fe9e69e5c64323dfa7827870f11203afe09
4
+ data.tar.gz: 4e9e8e62612c93686c1c5ed2532b14a260e44078830302f7155e49a45a0b6a66
5
5
  SHA512:
6
- metadata.gz: bcb86c3d249b14ae24d8a37fc5418ab41e789602ede38c5ab31dbda19d82100ac1f1321ff868fef6c7e892fdde2559905afbcfe22e85c65b63ce0c826092bfc1
7
- data.tar.gz: 051cfe7a8bdcee2ca9f173954de10108d5682c5f59c2a4291443f32552f31020baeaec78a2f7806d78be13df73f5a9a73742b77c9c4943eee1a60db81ec18100
6
+ metadata.gz: a8325df21f414fc4dfb5e61173ca94312662012d3a3ba12cb128a6c7c91d88b0cc97bfb344d8466500f43fd28bc6c3195eaa662e11ddb4c3333fbe1257611ad2
7
+ data.tar.gz: 787be19b2a2407237060341ff623e20f40a86fc5a76ce075e75c1dd62fbede8bbd94dd7a0312072cd60af12571c9dcf7edf2afe7e088e6c75267893156cd8482
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module LoadAndAuthorizeDynamicResource
5
+ extend ActiveSupport::Concern
6
+
7
+ INSTANCE_VARIABLE_NAME = 'resource'
8
+
9
+ included do
10
+ before_action :load_and_authorize_resource
11
+ before_action :load_and_authorize_association
12
+ end
13
+
14
+ def resource_class
15
+ @resource_class ||=
16
+ Motor::BuildSchema::Utils.classify_slug(resource_name_prefix + params[:resource])
17
+ end
18
+
19
+ def resource_name_prefix
20
+ ''
21
+ end
22
+
23
+ def load_and_authorize_resource
24
+ options = {
25
+ class: resource_class,
26
+ parent: false,
27
+ instance_name: INSTANCE_VARIABLE_NAME
28
+ }
29
+
30
+ if params[:resource_id].present?
31
+ options = options.merge(
32
+ parent: true,
33
+ id_param: :resource_id
34
+ )
35
+ end
36
+
37
+ CanCan::ControllerResource.new(
38
+ self,
39
+ options
40
+ ).load_and_authorize_resource
41
+ rescue ActiveRecord::RecordNotFound
42
+ head :not_found
43
+ rescue StandardError => e
44
+ render json: { errors: [e.message] }, status: :unprocessable_entity
45
+ end
46
+
47
+ def load_and_authorize_association
48
+ return if params[:association].blank?
49
+
50
+ association = resource_class.reflections[params[:association]]
51
+
52
+ if association
53
+ CanCan::ControllerResource.new(
54
+ self,
55
+ class: association.klass,
56
+ parent: false,
57
+ through: :resource,
58
+ through_association: params[:association].to_sym,
59
+ instance_name: INSTANCE_VARIABLE_NAME
60
+ ).load_and_authorize_resource
61
+ else
62
+ render json: { message: 'Unknown association' }, status: :not_found
63
+ end
64
+ rescue ActiveRecord::RecordNotFound
65
+ head :not_found
66
+ rescue StandardError => e
67
+ render json: { errors: [e.message] }, status: :unprocessable_entity
68
+ end
69
+ end
70
+ end
@@ -18,12 +18,15 @@ module Motor
18
18
  end
19
19
 
20
20
  def create
21
- ApplicationRecord.transaction { @alert.save! }
22
- Motor::Alerts::ScheduledAlertsCache.clear
23
-
24
- render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
25
- rescue Motor::Alerts::Persistance::NameAlreadyExists
26
- name_already_exists_response
21
+ if Motor::Alerts::Persistance.name_already_exists?(@alert)
22
+ name_already_exists_response
23
+ else
24
+ ApplicationRecord.transaction { @alert.save! }
25
+ Motor::Alerts::ScheduledAlertsCache.clear
26
+ Motor::Configs::WriteToFile.call
27
+
28
+ render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
29
+ end
27
30
  rescue Motor::Alerts::Persistance::InvalidInterval
28
31
  invalid_interval_response
29
32
  end
@@ -31,6 +34,7 @@ module Motor
31
34
  def update
32
35
  Motor::Alerts::Persistance.update_from_params!(@alert, alert_params)
33
36
  Motor::Alerts::ScheduledAlertsCache.clear
37
+ Motor::Configs::WriteToFile.call
34
38
 
35
39
  render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
36
40
  rescue Motor::Alerts::Persistance::NameAlreadyExists
@@ -42,6 +46,8 @@ module Motor
42
46
  def destroy
43
47
  @alert.update!(deleted_at: Time.current)
44
48
 
49
+ Motor::Configs::WriteToFile.call
50
+
45
51
  head :ok
46
52
  end
47
53
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ class AuditsController < ApiBaseController
5
+ load_and_authorize_resource :audit
6
+
7
+ def index
8
+ audits = Motor::ApiQuery.call(@audits, params)
9
+
10
+ render json: {
11
+ data: Motor::ApiQuery::BuildJson.call(audits, params),
12
+ meta: Motor::ApiQuery::BuildMeta.call(audits, params)
13
+ }
14
+ end
15
+ end
16
+ end
@@ -17,6 +17,7 @@ module Motor
17
17
  end
18
18
 
19
19
  @config.save!
20
+ Motor::Configs::WriteToFile.call
20
21
 
21
22
  render json: { data: Motor::ApiQuery::BuildJson.call(@config, params) }
22
23
  rescue ActiveRecord::RecordNotUnique
@@ -22,6 +22,7 @@ module Motor
22
22
  render json: { errors: [{ source: 'title', detail: 'Title already exists' }] }, status: :unprocessable_entity
23
23
  else
24
24
  ApplicationRecord.transaction { @dashboard.save! }
25
+ Motor::Configs::WriteToFile.call
25
26
 
26
27
  render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
27
28
  end
@@ -31,6 +32,7 @@ module Motor
31
32
 
32
33
  def update
33
34
  Motor::Dashboards::Persistance.update_from_params!(@dashboard, dashboard_params)
35
+ Motor::Configs::WriteToFile.call
34
36
 
35
37
  render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
36
38
  rescue Motor::Dashboards::Persistance::TitleAlreadyExists
@@ -40,6 +42,8 @@ module Motor
40
42
  def destroy
41
43
  @dashboard.update!(deleted_at: Time.current)
42
44
 
45
+ Motor::Configs::WriteToFile.call
46
+
43
47
  head :ok
44
48
  end
45
49
 
@@ -2,14 +2,10 @@
2
2
 
3
3
  module Motor
4
4
  class DataController < ApiBaseController
5
- include Motor::WrapIoParams
6
-
7
- INSTANCE_VARIABLE_NAME = 'resource'
8
-
9
5
  wrap_parameters :data, except: %i[include fields]
10
6
 
11
- before_action :load_and_authorize_resource
12
- before_action :load_and_authorize_association
7
+ include Motor::WrapIoParams
8
+ include Motor::LoadAndAuthorizeDynamicResource
13
9
 
14
10
  def index
15
11
  @resources = Motor::ApiQuery.call(@resources, params)
@@ -64,57 +60,6 @@ module Motor
64
60
 
65
61
  private
66
62
 
67
- def resource_class
68
- @resource_class ||= Motor::BuildSchema::Utils.classify_slug(params[:resource])
69
- end
70
-
71
- def load_and_authorize_resource
72
- options = {
73
- class: resource_class,
74
- parent: false,
75
- instance_name: INSTANCE_VARIABLE_NAME
76
- }
77
-
78
- if params[:resource_id].present?
79
- options = options.merge(
80
- parent: true,
81
- id_param: :resource_id
82
- )
83
- end
84
-
85
- CanCan::ControllerResource.new(
86
- self,
87
- options
88
- ).load_and_authorize_resource
89
- rescue ActiveRecord::RecordNotFound
90
- head :not_found
91
- rescue StandardError => e
92
- render json: { errors: [e.message] }, status: :unprocessable_entity
93
- end
94
-
95
- def load_and_authorize_association
96
- return if params[:association].blank?
97
-
98
- association = resource_class.reflections[params[:association]]
99
-
100
- if association
101
- CanCan::ControllerResource.new(
102
- self,
103
- class: association.klass,
104
- parent: false,
105
- through: :resource,
106
- through_association: params[:association].to_sym,
107
- instance_name: INSTANCE_VARIABLE_NAME
108
- ).load_and_authorize_resource
109
- else
110
- render json: { message: 'Unknown association' }, status: :not_found
111
- end
112
- rescue ActiveRecord::RecordNotFound
113
- head :not_found
114
- rescue StandardError => e
115
- render json: { errors: [e.message] }, status: :unprocessable_entity
116
- end
117
-
118
63
  def resource_params
119
64
  if params[:data].present?
120
65
  params.require(:data).except(resource_class.primary_key).permit!
@@ -22,6 +22,7 @@ module Motor
22
22
  render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
23
23
  else
24
24
  ApplicationRecord.transaction { @form.save! }
25
+ Motor::Configs::WriteToFile.call
25
26
 
26
27
  render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
27
28
  end
@@ -31,6 +32,7 @@ module Motor
31
32
 
32
33
  def update
33
34
  Motor::Forms::Persistance.update_from_params!(@form, form_params)
35
+ Motor::Configs::WriteToFile.call
34
36
 
35
37
  render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
36
38
  rescue Motor::Forms::Persistance::NameAlreadyExists
@@ -40,6 +42,8 @@ module Motor
40
42
  def destroy
41
43
  @form.update!(deleted_at: Time.current)
42
44
 
45
+ Motor::Configs::WriteToFile.call
46
+
43
47
  head :ok
44
48
  end
45
49
 
@@ -22,6 +22,7 @@ module Motor
22
22
  render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
23
23
  else
24
24
  ApplicationRecord.transaction { @query.save! }
25
+ Motor::Configs::WriteToFile.call
25
26
 
26
27
  render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
27
28
  end
@@ -31,6 +32,7 @@ module Motor
31
32
 
32
33
  def update
33
34
  Motor::Queries::Persistance.update_from_params!(@query, query_params)
35
+ Motor::Configs::WriteToFile.call
34
36
 
35
37
  render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
36
38
  rescue Motor::Queries::Persistance::NameAlreadyExists
@@ -40,6 +42,8 @@ module Motor
40
42
  def destroy
41
43
  @query.update!(deleted_at: Time.current)
42
44
 
45
+ Motor::Configs::WriteToFile.call
46
+
43
47
  head :ok
44
48
  end
45
49
 
@@ -12,6 +12,7 @@ module Motor
12
12
 
13
13
  def create
14
14
  Motor::BuildSchema::PersistResourceConfigs.call(@resource)
15
+ Motor::Configs::WriteToFile.call
15
16
 
16
17
  render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params) }
17
18
  end
@@ -7,12 +7,16 @@ module Motor
7
7
  def index
8
8
  Motor.reload! if Motor.development?
9
9
 
10
+ Motor::Configs::SyncFromFile.call
11
+
10
12
  render :show
11
13
  end
12
14
 
13
15
  def show
14
16
  Motor.reload! if Motor.development?
15
17
 
18
+ Motor::Configs::SyncFromFile.call
19
+
16
20
  render :show
17
21
  end
18
22
  end
@@ -2,11 +2,13 @@
2
2
 
3
3
  module Motor
4
4
  class Alert < ::Motor::ApplicationRecord
5
+ audited
6
+
5
7
  belongs_to :query
6
8
  belongs_to :author, polymorphic: true, optional: true
7
9
 
8
- has_many :alert_locks
9
- has_many :taggable_tags, as: :taggable
10
+ has_many :alert_locks, dependent: :destroy
11
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
10
12
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
11
13
 
12
14
  serialize :preferences, HashSerializer
@@ -4,5 +4,15 @@ module Motor
4
4
  class ApplicationRecord < ActiveRecord::Base
5
5
  self.abstract_class = true
6
6
  self.table_name_prefix = 'motor_'
7
+
8
+ def self.audited(*args)
9
+ default_class = Audited.audit_class
10
+
11
+ Audited.audit_class = Motor::Audit
12
+
13
+ super
14
+ ensure
15
+ Audited.audit_class = default_class
16
+ end
7
17
  end
8
18
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ class Audit < Audited::Audit
5
+ self.table_name = 'motor_audits'
6
+
7
+ serialize :audited_changes, HashSerializer
8
+ end
9
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Motor
4
4
  class Config < ::Motor::ApplicationRecord
5
+ audited
6
+
5
7
  serialize :value, HashSerializer
6
8
  end
7
9
  end
@@ -2,9 +2,11 @@
2
2
 
3
3
  module Motor
4
4
  class Dashboard < ::Motor::ApplicationRecord
5
+ audited
6
+
5
7
  belongs_to :author, polymorphic: true, optional: true
6
8
 
7
- has_many :taggable_tags, as: :taggable
9
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
8
10
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
9
11
 
10
12
  serialize :preferences, HashSerializer
@@ -2,9 +2,11 @@
2
2
 
3
3
  module Motor
4
4
  class Form < ::Motor::ApplicationRecord
5
+ audited
6
+
5
7
  belongs_to :author, polymorphic: true, optional: true
6
8
 
7
- has_many :taggable_tags, as: :taggable
9
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
8
10
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
9
11
 
10
12
  serialize :preferences, HashSerializer
@@ -2,10 +2,13 @@
2
2
 
3
3
  module Motor
4
4
  class Query < ::Motor::ApplicationRecord
5
+ audited
6
+
5
7
  belongs_to :author, polymorphic: true, optional: true
6
8
 
7
- has_many :taggable_tags, as: :taggable
9
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
8
10
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
11
+ has_many :alerts, dependent: :destroy
9
12
 
10
13
  serialize :preferences, HashSerializer
11
14
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Motor
4
4
  class Resource < ::Motor::ApplicationRecord
5
+ audited
6
+
5
7
  serialize :preferences, HashSerializer
6
8
  end
7
9
  end
@@ -1 +1 @@
1
- <%= raw(Motor::UiConfigs.app_tag) %>
1
+ <%= raw(Motor::Configs::BuildUiAppTag.call) %>
data/config/routes.rb CHANGED
@@ -15,6 +15,7 @@ Motor::Admin.routes.draw do
15
15
  resources :alerts, only: %i[index show create update destroy]
16
16
  resources :active_storage_attachments, only: %i[create], path: 'data/active_storage__attachments'
17
17
  resource :schema, only: %i[show update]
18
+ resources :audits, only: %i[index]
18
19
  resources :resources, path: '/data/:resource',
19
20
  only: %i[index show update create destroy],
20
21
  controller: 'data' do