motor-admin 0.1.57 → 0.1.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/app/controllers/concerns/motor/current_ability.rb +21 -0
- data/app/controllers/concerns/motor/current_user_method.rb +8 -7
- data/app/controllers/motor/alerts_controller.rb +4 -4
- data/app/controllers/motor/api_base_controller.rb +1 -12
- data/app/controllers/motor/application_controller.rb +1 -0
- data/app/controllers/motor/audits_controller.rb +1 -1
- data/app/controllers/motor/configs_controller.rb +2 -2
- data/app/controllers/motor/dashboards_controller.rb +8 -4
- data/app/controllers/motor/data_controller.rb +9 -4
- data/app/controllers/motor/forms_controller.rb +4 -4
- data/app/controllers/motor/queries_controller.rb +4 -4
- data/app/controllers/motor/resources_controller.rb +2 -2
- data/app/controllers/motor/run_queries_controller.rb +12 -1
- data/app/controllers/motor/ui_controller.rb +1 -1
- data/app/views/motor/ui/show.html.erb +1 -1
- data/lib/motor.rb +1 -0
- data/lib/motor/admin.rb +8 -0
- data/lib/motor/api_query/build_json.rb +101 -47
- data/lib/motor/assets.rb +10 -1
- data/lib/motor/build_schema.rb +3 -1
- data/lib/motor/build_schema/active_storage_attachment_schema.rb +1 -0
- data/lib/motor/build_schema/apply_permissions.rb +50 -0
- data/lib/motor/build_schema/find_icon.rb +6 -1
- data/lib/motor/cancan_utils.rb +7 -0
- data/lib/motor/cancan_utils/ability_patch.rb +29 -0
- data/lib/motor/cancan_utils/can_manage_all.rb +14 -0
- data/lib/motor/configs/build_ui_app_tag.rb +26 -16
- data/lib/motor/configs/load_from_cache.rb +20 -8
- data/lib/motor/queries/run_query.rb +7 -3
- data/lib/motor/version.rb +1 -1
- data/ui/dist/{main-dd83302a0e62f7cfdba6.css.gz → main-ba741735a93c9314bbfa.css.gz} +0 -0
- data/ui/dist/main-ba741735a93c9314bbfa.js.gz +0 -0
- data/ui/dist/manifest.json +5 -5
- metadata +11 -6
- data/ui/dist/main-dd83302a0e62f7cfdba6.js.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98eed032de058a25fc5951c40afac9faeedd33ad66299ab381f15527e122aeeb
|
4
|
+
data.tar.gz: 4797ba6520bf3614ced8ea7aa800145f2ee7c35934820c5ae623dfe19c007a45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d966ae337a44f486a56f0dcb741d06787af84e67e4a4f5c5f750796b6a8b7979e9685ec9485854e34d994477ddcfdbc55882d9efc0dd26b356f8bbfe66bb0dd
|
7
|
+
data.tar.gz: 82e3f0b57ef8aa4902a36da9a8d94814f3d42f5b18cd73d70a95e59d69b5737d8652505bf3b6468629b51fef06c55e55b3ab03840838db8b1222edbc9ef9a3df
|
data/README.md
CHANGED
@@ -32,6 +32,7 @@ $ rails motor:install && rake db:migrate
|
|
32
32
|
* [Data visualization](#data-visualization)
|
33
33
|
* [Dashboards](#dashboards)
|
34
34
|
* [Email alerts](#email-alerts)
|
35
|
+
* [Authorization](#authorization)
|
35
36
|
* [Intelligence search](#intelligence-search)
|
36
37
|
* [Optimized for mobile](#optimized-for-mobile)
|
37
38
|
* [Configurations sync between environments](#configurations-sync)
|
@@ -90,6 +91,9 @@ Sender address can be specified using `MOTOR_ALERTS_FROM_ADDRESS` environment va
|
|
90
91
|
|
91
92
|
Intelligence search can be opened via the top right corner button or using <kbd>Cmd</kbd> + <kbd>P</kbd> shortcut.
|
92
93
|
|
94
|
+
### Authorization
|
95
|
+
|
96
|
+
Motor Admin allows to set row-level and column-level permissions via [cancan](https://github.com/CanCanCommunity/cancancan) gem. Admin UI permissions should be defined in `app/models/motor/ability.rb` file in `Motor::Ability` class. See [Motor Admin guide](https://github.com/omohokcoj/motor-admin/blob/master/guides/defining_prmissions.md) and [CanCan documentation](https://github.com/CanCanCommunity/cancancan/blob/develop/docs/Defining-Abilities.md) to learn how to define user permissions.
|
93
97
|
|
94
98
|
### Optimized for Mobile
|
95
99
|
|
@@ -141,8 +145,6 @@ MOTOR_DEVELOPMENT=true rails s
|
|
141
145
|
|
142
146
|
## Comming Soon
|
143
147
|
|
144
|
-
* User groups
|
145
|
-
* Row-level permissions
|
146
148
|
* Multiple databases
|
147
149
|
* NoSQL data sources
|
148
150
|
* Pro Bussines intelligence features
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module CurrentAbility
|
5
|
+
def current_ability
|
6
|
+
@current_ability ||=
|
7
|
+
if defined?(Motor::Ability) && current_user
|
8
|
+
klass = Motor::Ability.dup.tap do |k|
|
9
|
+
k.prepend(Motor::CancanUtils::AbilityPatch)
|
10
|
+
end
|
11
|
+
|
12
|
+
params = [current_user]
|
13
|
+
params << request if Motor::Ability.instance_method(:initialize).arity == 2
|
14
|
+
|
15
|
+
klass.new(*params)
|
16
|
+
else
|
17
|
+
Motor::CancanUtils::CanManageAll.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,13 +3,14 @@
|
|
3
3
|
module Motor
|
4
4
|
module CurrentUserMethod
|
5
5
|
def current_user
|
6
|
-
|
7
|
-
current_admin
|
8
|
-
|
9
|
-
current_admin_user
|
10
|
-
|
11
|
-
super
|
12
|
-
|
6
|
+
@current_user ||=
|
7
|
+
if defined?(current_admin)
|
8
|
+
current_admin
|
9
|
+
elsif defined?(current_admin_user)
|
10
|
+
current_admin_user
|
11
|
+
elsif defined?(super)
|
12
|
+
super
|
13
|
+
end
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -10,11 +10,11 @@ module Motor
|
|
10
10
|
authorize_resource :alert, only: :create
|
11
11
|
|
12
12
|
def index
|
13
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@alerts.active, params) }
|
13
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@alerts.active, params, current_ability) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def show
|
17
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
|
17
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params, current_ability) }
|
18
18
|
end
|
19
19
|
|
20
20
|
def create
|
@@ -25,7 +25,7 @@ module Motor
|
|
25
25
|
Motor::Alerts::ScheduledAlertsCache.clear
|
26
26
|
Motor::Configs::WriteToFile.call
|
27
27
|
|
28
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
|
28
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params, current_ability) }
|
29
29
|
end
|
30
30
|
rescue Motor::Alerts::Persistance::InvalidInterval
|
31
31
|
invalid_interval_response
|
@@ -36,7 +36,7 @@ module Motor
|
|
36
36
|
Motor::Alerts::ScheduledAlertsCache.clear
|
37
37
|
Motor::Configs::WriteToFile.call
|
38
38
|
|
39
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
|
39
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params, current_ability) }
|
40
40
|
rescue Motor::Alerts::Persistance::NameAlreadyExists
|
41
41
|
name_already_exists_response
|
42
42
|
rescue Motor::Alerts::Persistance::InvalidInterval
|
@@ -3,14 +3,7 @@
|
|
3
3
|
module Motor
|
4
4
|
class ApiBaseController < ActionController::API
|
5
5
|
include Motor::CurrentUserMethod
|
6
|
-
|
7
|
-
class CanCanAbilityManageAll
|
8
|
-
include CanCan::Ability
|
9
|
-
|
10
|
-
def initialize(_)
|
11
|
-
can :manage, :all
|
12
|
-
end
|
13
|
-
end
|
6
|
+
include Motor::CurrentAbility
|
14
7
|
|
15
8
|
unless Rails.env.test?
|
16
9
|
rescue_from StandardError do |e|
|
@@ -19,9 +12,5 @@ module Motor
|
|
19
12
|
render json: { errors: [e.message] }, status: :internal_server_error
|
20
13
|
end
|
21
14
|
end
|
22
|
-
|
23
|
-
def current_ability
|
24
|
-
CanCanAbilityManageAll.new(current_user)
|
25
|
-
end
|
26
15
|
end
|
27
16
|
end
|
@@ -8,7 +8,7 @@ module Motor
|
|
8
8
|
audits = Motor::ApiQuery.call(@audits, params)
|
9
9
|
|
10
10
|
render json: {
|
11
|
-
data: Motor::ApiQuery::BuildJson.call(audits, params),
|
11
|
+
data: Motor::ApiQuery::BuildJson.call(audits, params, current_ability),
|
12
12
|
meta: Motor::ApiQuery::BuildMeta.call(audits, params)
|
13
13
|
}
|
14
14
|
end
|
@@ -7,7 +7,7 @@ module Motor
|
|
7
7
|
load_and_authorize_resource
|
8
8
|
|
9
9
|
def index
|
10
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@configs, params) }
|
10
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@configs, params, current_ability) }
|
11
11
|
end
|
12
12
|
|
13
13
|
def create
|
@@ -19,7 +19,7 @@ module Motor
|
|
19
19
|
@config.save!
|
20
20
|
Motor::Configs::WriteToFile.call
|
21
21
|
|
22
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@config, params) }
|
22
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@config, params, current_ability) }
|
23
23
|
rescue ActiveRecord::RecordNotUnique
|
24
24
|
retry
|
25
25
|
end
|
@@ -10,11 +10,11 @@ module Motor
|
|
10
10
|
authorize_resource :dashboard, only: :create
|
11
11
|
|
12
12
|
def index
|
13
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboards.active, params) }
|
13
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboards.active, params, current_ability) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def show
|
17
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
|
17
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params, current_ability) }
|
18
18
|
end
|
19
19
|
|
20
20
|
def create
|
@@ -24,7 +24,7 @@ module Motor
|
|
24
24
|
ApplicationRecord.transaction { @dashboard.save! }
|
25
25
|
Motor::Configs::WriteToFile.call
|
26
26
|
|
27
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
|
27
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params, current_ability) }
|
28
28
|
end
|
29
29
|
rescue ActiveRecord::RecordNotUnique
|
30
30
|
retry
|
@@ -34,7 +34,7 @@ module Motor
|
|
34
34
|
Motor::Dashboards::Persistance.update_from_params!(@dashboard, dashboard_params)
|
35
35
|
Motor::Configs::WriteToFile.call
|
36
36
|
|
37
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
|
37
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params, current_ability) }
|
38
38
|
rescue Motor::Dashboards::Persistance::TitleAlreadyExists
|
39
39
|
render json: { errors: [{ source: 'title', detail: 'Title already exists' }] }, status: :unprocessable_entity
|
40
40
|
end
|
@@ -51,6 +51,10 @@ module Motor
|
|
51
51
|
|
52
52
|
def build_dashboard
|
53
53
|
@dashboard = Motor::Dashboards::Persistance.build_from_params(dashboard_params)
|
54
|
+
|
55
|
+
@dashboard.define_singleton_method(:tags) do
|
56
|
+
taggable_tags.map(&:tag)
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
def dashboard_params
|
@@ -11,19 +11,19 @@ module Motor
|
|
11
11
|
@resources = Motor::ApiQuery.call(@resources, params)
|
12
12
|
|
13
13
|
render json: {
|
14
|
-
data: Motor::ApiQuery::BuildJson.call(@resources, params),
|
14
|
+
data: Motor::ApiQuery::BuildJson.call(@resources, params, current_ability),
|
15
15
|
meta: Motor::ApiQuery::BuildMeta.call(@resources, params)
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
19
19
|
def show
|
20
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params) }
|
20
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params, current_ability) }
|
21
21
|
end
|
22
22
|
|
23
23
|
def create
|
24
24
|
@resource.save!
|
25
25
|
|
26
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params) }
|
26
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params, current_ability) }
|
27
27
|
rescue ActiveRecord::RecordInvalid
|
28
28
|
render json: { errors: @resource.errors }, status: :unprocessable_entity
|
29
29
|
end
|
@@ -31,7 +31,7 @@ module Motor
|
|
31
31
|
def update
|
32
32
|
@resource.update!(resource_params)
|
33
33
|
|
34
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params) }
|
34
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params, current_ability) }
|
35
35
|
rescue ActiveRecord::RecordInvalid
|
36
36
|
render json: { errors: @resource.errors }, status: :unprocessable_entity
|
37
37
|
end
|
@@ -47,6 +47,11 @@ module Motor
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def execute
|
50
|
+
resource_preferences = Motor::Resource.find_by(name: @resource.class.name.underscore).preferences
|
51
|
+
resource_action = resource_preferences[:actions].find { |a| a[:preferences][:method_name] == params[:method] }
|
52
|
+
|
53
|
+
authorize!(resource_action[:name].to_sym, @resource)
|
54
|
+
|
50
55
|
@resource.public_send(params[:method].to_sym)
|
51
56
|
|
52
57
|
head :ok
|
@@ -10,11 +10,11 @@ module Motor
|
|
10
10
|
authorize_resource :form, only: :create
|
11
11
|
|
12
12
|
def index
|
13
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@forms.active, params) }
|
13
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@forms.active, params, current_ability) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def show
|
17
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
|
17
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@form, params, current_ability) }
|
18
18
|
end
|
19
19
|
|
20
20
|
def create
|
@@ -24,7 +24,7 @@ module Motor
|
|
24
24
|
ApplicationRecord.transaction { @form.save! }
|
25
25
|
Motor::Configs::WriteToFile.call
|
26
26
|
|
27
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
|
27
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@form, params, current_ability) }
|
28
28
|
end
|
29
29
|
rescue ActiveRecord::RecordNotUnique
|
30
30
|
retry
|
@@ -34,7 +34,7 @@ module Motor
|
|
34
34
|
Motor::Forms::Persistance.update_from_params!(@form, form_params)
|
35
35
|
Motor::Configs::WriteToFile.call
|
36
36
|
|
37
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
|
37
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@form, params, current_ability) }
|
38
38
|
rescue Motor::Forms::Persistance::NameAlreadyExists
|
39
39
|
render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
|
40
40
|
end
|
@@ -10,11 +10,11 @@ module Motor
|
|
10
10
|
authorize_resource :query, only: :create
|
11
11
|
|
12
12
|
def index
|
13
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@queries.active, params) }
|
13
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@queries.active, params, current_ability) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def show
|
17
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
|
17
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@query, params, current_ability) }
|
18
18
|
end
|
19
19
|
|
20
20
|
def create
|
@@ -24,7 +24,7 @@ module Motor
|
|
24
24
|
ApplicationRecord.transaction { @query.save! }
|
25
25
|
Motor::Configs::WriteToFile.call
|
26
26
|
|
27
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
|
27
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@query, params, current_ability) }
|
28
28
|
end
|
29
29
|
rescue ActiveRecord::RecordNotUnique
|
30
30
|
retry
|
@@ -34,7 +34,7 @@ module Motor
|
|
34
34
|
Motor::Queries::Persistance.update_from_params!(@query, query_params)
|
35
35
|
Motor::Configs::WriteToFile.call
|
36
36
|
|
37
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
|
37
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@query, params, current_ability) }
|
38
38
|
rescue Motor::Queries::Persistance::NameAlreadyExists
|
39
39
|
render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
|
40
40
|
end
|
@@ -7,14 +7,14 @@ module Motor
|
|
7
7
|
load_and_authorize_resource
|
8
8
|
|
9
9
|
def index
|
10
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@resources, params) }
|
10
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@resources, params, current_ability) }
|
11
11
|
end
|
12
12
|
|
13
13
|
def create
|
14
14
|
Motor::BuildSchema::PersistResourceConfigs.call(@resource)
|
15
15
|
Motor::Configs::WriteToFile.call
|
16
16
|
|
17
|
-
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params) }
|
17
|
+
render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params, current_ability) }
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
@@ -20,7 +20,8 @@ module Motor
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def render_result
|
23
|
-
|
23
|
+
variables = params.fetch(:variables, {}).merge(current_user_variables)
|
24
|
+
query_result = Queries::RunQuery.call(@query, variables_hash: variables)
|
24
25
|
|
25
26
|
if query_result.error
|
26
27
|
render json: { errors: [{ detail: query_result.error }] }, status: :unprocessable_entity
|
@@ -29,6 +30,16 @@ module Motor
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
33
|
+
def current_user_variables
|
34
|
+
return {} unless current_user
|
35
|
+
|
36
|
+
current_user
|
37
|
+
.attributes
|
38
|
+
.slice('id', 'email')
|
39
|
+
.transform_keys { |key| "current_user_#{key}" }
|
40
|
+
.compact
|
41
|
+
end
|
42
|
+
|
32
43
|
def query_result_hash(query_result)
|
33
44
|
{
|
34
45
|
data: query_result.data,
|
@@ -1 +1 @@
|
|
1
|
-
<%= raw(Motor::Configs::BuildUiAppTag.call(current_user)) %>
|
1
|
+
<%= raw(Motor::Configs::BuildUiAppTag.call(current_user, current_ability)) %>
|
data/lib/motor.rb
CHANGED
data/lib/motor/admin.rb
CHANGED
@@ -69,6 +69,14 @@ module Motor
|
|
69
69
|
config.after_initialize do
|
70
70
|
next unless defined?(ActiveStorage::Engine)
|
71
71
|
|
72
|
+
ActiveSupport.on_load(:active_storage_attachment) do
|
73
|
+
ActiveStorage::Attachment.include(Motor::ActiveRecordUtils::ActiveStorageLinksExtension)
|
74
|
+
end
|
75
|
+
|
76
|
+
ActiveSupport.on_load(:active_storage_blob) do
|
77
|
+
ActiveStorage::Blob.singleton_class.prepend(Motor::ActiveRecordUtils::ActiveStorageBlobPatch)
|
78
|
+
end
|
79
|
+
|
72
80
|
ActiveStorage::Attachment.include(Motor::ActiveRecordUtils::ActiveStorageLinksExtension)
|
73
81
|
ActiveStorage::Blob.singleton_class.prepend(Motor::ActiveRecordUtils::ActiveStorageBlobPatch)
|
74
82
|
end
|
@@ -5,83 +5,90 @@ module Motor
|
|
5
5
|
module BuildJson
|
6
6
|
module_function
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# @param rel [ActiveRecord::Base, ActiveRecord::Relation]
|
9
|
+
# @param params [Hash]
|
10
|
+
# @param current_ability [CanCan::Ability]
|
11
|
+
# @return [Hash]
|
12
|
+
def call(rel, params, current_ability = Motor::CancanUtils::CanManageAll.new)
|
13
|
+
rel = rel.none if limit_zero_params?(params)
|
11
14
|
rel = rel.preload_associations_lazily if rel.is_a?(ActiveRecord::Relation)
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
assign_include_params(json_params, rel, params)
|
16
|
-
assign_fields_params(json_params, rel, params)
|
17
|
-
|
18
|
-
rel.as_json(json_params)
|
19
|
-
end
|
16
|
+
model = rel.is_a?(ActiveRecord::Relation) ? rel.klass : rel.class
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
include_hash = build_include_hash(params['include'])
|
19
|
+
models_index = build_models_index(model, include_hash)
|
23
20
|
|
24
|
-
|
21
|
+
json_params = normalize_include_params(include_hash)
|
25
22
|
|
26
|
-
|
27
|
-
include_params =
|
28
|
-
include_params.split(',').reduce({}) do |accumulator, path|
|
29
|
-
hash = {}
|
23
|
+
assign_fields_params!(json_params, model, params, current_ability, models_index)
|
30
24
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
acc[part] = acc_hash
|
25
|
+
rel.as_json(json_params.with_indifferent_access)
|
26
|
+
end
|
35
27
|
|
36
|
-
|
37
|
-
|
28
|
+
# @param include_params [Hash]
|
29
|
+
# @return [Hash]
|
30
|
+
def build_include_hash(include_params)
|
31
|
+
return {} if include_params.blank?
|
38
32
|
|
39
|
-
|
40
|
-
|
33
|
+
if include_params.is_a?(String)
|
34
|
+
build_hash_from_string_path(include_params)
|
35
|
+
else
|
36
|
+
include_params
|
41
37
|
end
|
42
|
-
|
43
|
-
json_params.deep_merge!(normalize_include_params(include_params))
|
44
38
|
end
|
45
39
|
|
46
|
-
|
40
|
+
# @param json_params [Hash]
|
41
|
+
# @param model [Class<ActiveRecord::Base>]
|
42
|
+
# @param params [Hash]
|
43
|
+
# @param current_ability [CanCan::Ability]
|
44
|
+
# @param models_index [Hash]
|
45
|
+
# @return [void]
|
46
|
+
def assign_fields_params!(json_params, model, params, current_ability, models_index)
|
47
47
|
return if params[:fields].blank?
|
48
48
|
|
49
|
-
model = rel.is_a?(ActiveRecord::Relation) ? rel.klass : rel.class
|
50
|
-
|
51
49
|
params[:fields].each do |key, fields|
|
52
|
-
|
53
|
-
|
54
|
-
merge_fields_params!(json_params, key, fields, model)
|
55
|
-
end
|
56
|
-
end
|
50
|
+
fields_model = models_index[key]
|
57
51
|
|
58
|
-
|
59
|
-
model_name = model.name.underscore
|
52
|
+
next unless model
|
60
53
|
|
61
|
-
|
62
|
-
json_params.merge!(build_fields_hash(model, fields))
|
63
|
-
else
|
64
|
-
hash = find_key_in_params(json_params, key)
|
54
|
+
fields = fields.split(',') if fields.is_a?(String)
|
65
55
|
|
66
|
-
fields_hash =
|
56
|
+
fields_hash = fields_model == model ? json_params : find_key_in_params(json_params, key)
|
67
57
|
|
68
|
-
|
58
|
+
fields_hash.merge!(build_fields_hash(fields_model, fields, current_ability))
|
69
59
|
end
|
70
60
|
end
|
71
61
|
|
72
|
-
|
73
|
-
|
62
|
+
# @param model [Class<ActiveRecord::Base>]
|
63
|
+
# @param fields [Hash]
|
64
|
+
# @param current_ability [CanCan::Ability]
|
65
|
+
# @return [Hash]
|
66
|
+
def build_fields_hash(model, fields, current_ability)
|
67
|
+
return { 'methods' => fields } unless model
|
68
|
+
|
69
|
+
column_names = model.column_names.map(&:to_sym)
|
70
|
+
instance_methods = model.instance_methods
|
71
|
+
permitted_attributes = current_ability.permitted_attributes(:read, model)
|
72
|
+
is_permitted_all = column_names == permitted_attributes
|
73
|
+
|
74
74
|
fields_hash = { 'only' => [], 'methods' => [] }
|
75
75
|
|
76
76
|
fields.each_with_object(fields_hash) do |field, acc|
|
77
|
-
|
77
|
+
field_symbol = field.to_sym
|
78
|
+
|
79
|
+
next if !is_permitted_all && permitted_attributes.exclude?(field_symbol)
|
80
|
+
|
81
|
+
if column_names.include?(field_symbol)
|
78
82
|
acc['only'] << field
|
79
|
-
elsif
|
83
|
+
elsif instance_methods.include?(field_symbol)
|
80
84
|
acc['methods'] << field
|
81
85
|
end
|
82
86
|
end
|
83
87
|
end
|
84
88
|
|
89
|
+
# @param params [Hash]
|
90
|
+
# @param key [String]
|
91
|
+
# @return [Hash]
|
85
92
|
def find_key_in_params(params, key)
|
86
93
|
params = params['include']
|
87
94
|
|
@@ -93,6 +100,8 @@ module Motor
|
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
103
|
+
# @param params [Hash]
|
104
|
+
# @return [Hash]
|
96
105
|
def normalize_include_params(params)
|
97
106
|
case params
|
98
107
|
when Array
|
@@ -112,6 +121,51 @@ module Motor
|
|
112
121
|
raise ArgumentError, "Wrong include param type #{params.class}"
|
113
122
|
end
|
114
123
|
end
|
124
|
+
|
125
|
+
# @param model [Class<ActiveRecord::Base>]
|
126
|
+
# @param includes_hash [Hash]
|
127
|
+
# @return [Hash]
|
128
|
+
def build_models_index(model, includes_hash)
|
129
|
+
default_index = {
|
130
|
+
model.name.underscore => model,
|
131
|
+
model.name.underscore.split('/').last => model
|
132
|
+
}
|
133
|
+
|
134
|
+
includes_hash.reduce(default_index) do |acc, (key, value)|
|
135
|
+
reflection = model.reflections[key]
|
136
|
+
|
137
|
+
next acc unless reflection
|
138
|
+
next acc if reflection.polymorphic?
|
139
|
+
|
140
|
+
acc[key] = reflection.klass
|
141
|
+
|
142
|
+
acc.merge(build_models_index(reflection.klass, value))
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# @param string_path [String]
|
147
|
+
# @return [Hash]
|
148
|
+
def build_hash_from_string_path(string_path)
|
149
|
+
string_path.split(',').reduce({}) do |accumulator, path|
|
150
|
+
hash = {}
|
151
|
+
|
152
|
+
path.split('.').reduce(hash) do |acc, part|
|
153
|
+
acc_hash = {}
|
154
|
+
|
155
|
+
acc[part] = acc_hash
|
156
|
+
|
157
|
+
acc_hash
|
158
|
+
end
|
159
|
+
|
160
|
+
accumulator.deep_merge(hash)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# @param params [Hash]
|
165
|
+
# @return [Boolean]
|
166
|
+
def limit_zero_params?(params)
|
167
|
+
params.dig(:page, :limit).yield_self { |limit| limit.present? && limit.to_i.zero? }
|
168
|
+
end
|
115
169
|
end
|
116
170
|
end
|
117
171
|
end
|
data/lib/motor/assets.rb
CHANGED
@@ -8,10 +8,19 @@ module Motor
|
|
8
8
|
MANIFEST_PATH = ASSETS_PATH.join('manifest.json')
|
9
9
|
DEV_SERVER_URL = 'http://localhost:9090/'
|
10
10
|
|
11
|
+
CACHE_STORE =
|
12
|
+
if Rails.env.production?
|
13
|
+
ActiveSupport::Cache::MemoryStore.new(size: 5.megabytes)
|
14
|
+
else
|
15
|
+
ActiveSupport::Cache::NullStore.new
|
16
|
+
end
|
17
|
+
|
11
18
|
module_function
|
12
19
|
|
13
20
|
def manifest
|
14
|
-
|
21
|
+
CACHE_STORE.fetch('manifest') do
|
22
|
+
JSON.parse(MANIFEST_PATH.read)
|
23
|
+
end
|
15
24
|
end
|
16
25
|
|
17
26
|
def icons
|
data/lib/motor/build_schema.rb
CHANGED
@@ -58,9 +58,10 @@ module Motor
|
|
58
58
|
|
59
59
|
module_function
|
60
60
|
|
61
|
-
def call(cache_keys = {})
|
61
|
+
def call(cache_keys = {}, current_ability = nil)
|
62
62
|
schema = LoadFromRails.call
|
63
63
|
schema = MergeSchemaConfigs.call(schema, cache_keys)
|
64
|
+
schema = ApplyPermissions.call(schema, current_ability) if current_ability
|
64
65
|
|
65
66
|
ReorderSchema.call(schema, cache_keys)
|
66
67
|
end
|
@@ -75,4 +76,5 @@ require_relative './build_schema/find_icon'
|
|
75
76
|
require_relative './build_schema/persist_resource_configs'
|
76
77
|
require_relative './build_schema/reorder_schema'
|
77
78
|
require_relative './build_schema/merge_schema_configs'
|
79
|
+
require_relative './build_schema/apply_permissions'
|
78
80
|
require_relative './build_schema/utils'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module BuildSchema
|
5
|
+
module ApplyPermissions
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def call(schema, ability)
|
9
|
+
schema.map do |model|
|
10
|
+
klass = model[:class_name].constantize
|
11
|
+
|
12
|
+
next unless ability.can?(:read, klass)
|
13
|
+
|
14
|
+
model[:associations] = filter_associations(model[:associations], ability)
|
15
|
+
model[:columns] = filter_columns(klass, model[:columns], ability)
|
16
|
+
model[:actions] = filter_actions(klass, model[:actions], ability)
|
17
|
+
|
18
|
+
model
|
19
|
+
end.compact
|
20
|
+
end
|
21
|
+
|
22
|
+
def filter_associations(associations, ability)
|
23
|
+
associations.select do |assoc|
|
24
|
+
ability.can?(:read, assoc[:model_name].classify.constantize)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def filter_columns(model, columns, ability)
|
29
|
+
columns.map do |column|
|
30
|
+
next unless ability.can?(:read, model, column[:name])
|
31
|
+
|
32
|
+
next if column.dig(:reference, :model_name).present? &&
|
33
|
+
!ability.can?(:read, column[:reference][:model_name].classify.constantize)
|
34
|
+
|
35
|
+
unless ability.can?(:update, model, column[:name])
|
36
|
+
column = column.merge(access_type: BuildSchema::ColumnAccessTypes::READ_ONLY)
|
37
|
+
end
|
38
|
+
|
39
|
+
column
|
40
|
+
end.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def filter_actions(model, actions, ability)
|
44
|
+
actions.select do |action|
|
45
|
+
ability.can?(action[:name].to_sym, model)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -35,6 +35,7 @@ module Motor
|
|
35
35
|
'token' => 'key',
|
36
36
|
'secret' => 'lock',
|
37
37
|
'automation' => 'manual-gearbox',
|
38
|
+
'workflow' => 'manual-gearbox',
|
38
39
|
'relationship' => 'hierarchy',
|
39
40
|
'person' => 'user',
|
40
41
|
'people' => 'users',
|
@@ -96,6 +97,9 @@ module Motor
|
|
96
97
|
'page' => 'brand-pagekit',
|
97
98
|
'date' => 'calendar-event',
|
98
99
|
'customer' => 'users',
|
100
|
+
'client' => 'users',
|
101
|
+
'ticket' => 'ticket',
|
102
|
+
'event' => 'event',
|
99
103
|
'contact' => 'users',
|
100
104
|
'member' => 'users',
|
101
105
|
'admin' => 'user-check',
|
@@ -107,7 +111,8 @@ module Motor
|
|
107
111
|
'product' => 'building-store',
|
108
112
|
'html' => 'code',
|
109
113
|
'stripe' => 'brand-stripe',
|
110
|
-
'email' => 'mail'
|
114
|
+
'email' => 'mail',
|
115
|
+
'status' => 'hash'
|
111
116
|
}.freeze
|
112
117
|
|
113
118
|
DEFAULT_ICON = 'database'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module CancanUtils
|
5
|
+
module AbilityPatch
|
6
|
+
def serialized_rules
|
7
|
+
@rules.map do |rule|
|
8
|
+
{
|
9
|
+
base_behavior: rule.base_behavior,
|
10
|
+
actions: expand_actions(rule.actions),
|
11
|
+
subjects: rule.subjects.map(&:to_s),
|
12
|
+
attributes: rule.attributes,
|
13
|
+
conditions: rule.conditions.as_json
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def rules_hash
|
19
|
+
serialized_rules.hash
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def default_alias_actions
|
25
|
+
super.merge(destroy: %i[remove delete])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -12,57 +12,67 @@ module Motor
|
|
12
12
|
|
13
13
|
module_function
|
14
14
|
|
15
|
-
def call(current_user = nil)
|
15
|
+
def call(current_user = nil, current_ability = nil)
|
16
16
|
cache_keys = LoadFromCache.load_cache_keys
|
17
17
|
|
18
18
|
CACHE_STORE.fetch("#{cache_keys.hash}#{current_user&.id}") do
|
19
19
|
CACHE_STORE.clear
|
20
20
|
|
21
|
-
|
21
|
+
data = build_data(cache_keys, current_user, current_ability)
|
22
|
+
Motor::ApplicationController.helpers.tag.div('', id: 'app', data: data)
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
26
|
# @return [Hash]
|
26
|
-
def build_data(cache_keys = {}, current_user = nil)
|
27
|
+
def build_data(cache_keys = {}, current_user = nil, current_ability = nil)
|
27
28
|
{
|
28
29
|
current_user: current_user&.as_json(only: %i[id email]),
|
30
|
+
current_rules: current_ability.serialized_rules,
|
29
31
|
audits_count: Motor::Audit.count,
|
30
32
|
base_path: Motor::Admin.routes.url_helpers.motor_path,
|
31
|
-
schema: Motor::BuildSchema.call(cache_keys),
|
33
|
+
schema: Motor::BuildSchema.call(cache_keys, current_ability),
|
32
34
|
header_links: header_links_data_hash(cache_keys[:configs]),
|
33
|
-
queries: queries_data_hash(cache_keys
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
queries: queries_data_hash(build_cache_key(cache_keys, :queries, current_user, current_ability),
|
36
|
+
current_ability),
|
37
|
+
dashboards: dashboards_data_hash(build_cache_key(cache_keys, :dashboards, current_user, current_ability),
|
38
|
+
current_ability),
|
39
|
+
alerts: alerts_data_hash(build_cache_key(cache_keys, :alerts, current_user, current_ability),
|
40
|
+
current_ability),
|
41
|
+
forms: forms_data_hash(build_cache_key(cache_keys, :forms, current_user, current_ability), current_ability)
|
37
42
|
}
|
38
43
|
end
|
39
44
|
|
45
|
+
# @return [String]
|
46
|
+
def build_cache_key(cache_keys, key, current_user, current_ability)
|
47
|
+
"#{cache_keys[key].hash}#{current_user&.id}#{current_ability&.rules_hash}"
|
48
|
+
end
|
49
|
+
|
40
50
|
def header_links_data_hash(cache_key = nil)
|
41
51
|
configs = Motor::Configs::LoadFromCache.load_configs(cache_key: cache_key)
|
42
52
|
|
43
53
|
configs.find { |c| c.key == 'header.links' }&.value || []
|
44
54
|
end
|
45
55
|
|
46
|
-
def queries_data_hash(cache_key = nil)
|
47
|
-
Motor::Configs::LoadFromCache.load_queries(cache_key: cache_key)
|
56
|
+
def queries_data_hash(cache_key = nil, current_ability = nil)
|
57
|
+
Motor::Configs::LoadFromCache.load_queries(cache_key: cache_key, current_ability: current_ability)
|
48
58
|
.as_json(only: %i[id name updated_at],
|
49
59
|
include: { tags: { only: %i[id name] } })
|
50
60
|
end
|
51
61
|
|
52
|
-
def dashboards_data_hash(cache_key = nil)
|
53
|
-
Motor::Configs::LoadFromCache.load_dashboards(cache_key: cache_key)
|
62
|
+
def dashboards_data_hash(cache_key = nil, current_ability = nil)
|
63
|
+
Motor::Configs::LoadFromCache.load_dashboards(cache_key: cache_key, current_ability: current_ability)
|
54
64
|
.as_json(only: %i[id title updated_at],
|
55
65
|
include: { tags: { only: %i[id name] } })
|
56
66
|
end
|
57
67
|
|
58
|
-
def alerts_data_hash(cache_key = nil)
|
59
|
-
Motor::Configs::LoadFromCache.load_alerts(cache_key: cache_key)
|
68
|
+
def alerts_data_hash(cache_key = nil, current_ability = nil)
|
69
|
+
Motor::Configs::LoadFromCache.load_alerts(cache_key: cache_key, current_ability: current_ability)
|
60
70
|
.as_json(only: %i[id name is_enabled updated_at],
|
61
71
|
include: { tags: { only: %i[id name] } })
|
62
72
|
end
|
63
73
|
|
64
|
-
def forms_data_hash(cache_key = nil)
|
65
|
-
Motor::Configs::LoadFromCache.load_forms(cache_key: cache_key)
|
74
|
+
def forms_data_hash(cache_key = nil, current_ability = nil)
|
75
|
+
Motor::Configs::LoadFromCache.load_forms(cache_key: cache_key, current_ability: current_ability)
|
66
76
|
.as_json(only: %i[id name updated_at],
|
67
77
|
include: { tags: { only: %i[id name] } })
|
68
78
|
end
|
@@ -32,27 +32,39 @@ module Motor
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def load_queries(cache_key: nil)
|
35
|
+
def load_queries(cache_key: nil, current_ability: nil)
|
36
36
|
maybe_fetch_from_cache('queries', cache_key) do
|
37
|
-
Motor::Query.all.active.preload(:tags)
|
37
|
+
rel = Motor::Query.all.active.preload(:tags)
|
38
|
+
rel = rel.accessible_by(current_ability) if current_ability
|
39
|
+
|
40
|
+
rel.load
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
41
|
-
def load_dashboards(cache_key: nil)
|
44
|
+
def load_dashboards(cache_key: nil, current_ability: nil)
|
42
45
|
maybe_fetch_from_cache('dashboards', cache_key) do
|
43
|
-
Motor::Dashboard.all.active.preload(:tags)
|
46
|
+
rel = Motor::Dashboard.all.active.preload(:tags)
|
47
|
+
rel = rel.accessible_by(current_ability) if current_ability
|
48
|
+
|
49
|
+
rel.load
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
47
|
-
def load_alerts(cache_key: nil)
|
53
|
+
def load_alerts(cache_key: nil, current_ability: nil)
|
48
54
|
maybe_fetch_from_cache('alerts', cache_key) do
|
49
|
-
Motor::Alert.all.active.preload(:tags)
|
55
|
+
rel = Motor::Alert.all.active.preload(:tags)
|
56
|
+
rel = rel.accessible_by(current_ability) if current_ability
|
57
|
+
|
58
|
+
rel.load
|
50
59
|
end
|
51
60
|
end
|
52
61
|
|
53
|
-
def load_forms(cache_key: nil)
|
62
|
+
def load_forms(cache_key: nil, current_ability: nil)
|
54
63
|
maybe_fetch_from_cache('forms', cache_key) do
|
55
|
-
Motor::Form.all.active.preload(:tags)
|
64
|
+
rel = Motor::Form.all.active.preload(:tags)
|
65
|
+
rel = rel.accessible_by(current_ability) if current_ability
|
66
|
+
|
67
|
+
rel.load
|
56
68
|
end
|
57
69
|
end
|
58
70
|
|
@@ -16,6 +16,8 @@ module Motor
|
|
16
16
|
|
17
17
|
PG_ERROR_REGEXP = /\APG.+ERROR:/.freeze
|
18
18
|
|
19
|
+
RESERVED_VARIABLES = %w[current_user_id current_user_email].freeze
|
20
|
+
|
19
21
|
module_function
|
20
22
|
|
21
23
|
# @param query [Motor::Query]
|
@@ -110,11 +112,13 @@ module Motor
|
|
110
112
|
end
|
111
113
|
|
112
114
|
# @param variable_configs [Array<Hash>]
|
113
|
-
# @param
|
115
|
+
# @param variables_hash [Hash]
|
114
116
|
# @return [Hash]
|
115
117
|
def merge_variable_default_values(variable_configs, variables_hash)
|
116
|
-
variable_configs.each_with_object(
|
117
|
-
|
118
|
+
variable_configs.each_with_object(variables_hash.slice(*RESERVED_VARIABLES)) do |variable, acc|
|
119
|
+
next if RESERVED_VARIABLES.include?(variable[:name])
|
120
|
+
|
121
|
+
acc[variable[:name]] ||= variables_hash[variable[:name]] || variable[:default_value]
|
118
122
|
end
|
119
123
|
end
|
120
124
|
end
|
data/lib/motor/version.rb
CHANGED
Binary file
|
Binary file
|
data/ui/dist/manifest.json
CHANGED
@@ -2068,11 +2068,11 @@
|
|
2068
2068
|
"mail-opened.svg": "icons/mail-opened.svg",
|
2069
2069
|
"mail.svg": "icons/mail.svg",
|
2070
2070
|
"mailbox.svg": "icons/mailbox.svg",
|
2071
|
-
"main-
|
2072
|
-
"main-
|
2073
|
-
"main-
|
2074
|
-
"main.css": "main-
|
2075
|
-
"main.js": "main-
|
2071
|
+
"main-ba741735a93c9314bbfa.css.gz": "main-ba741735a93c9314bbfa.css.gz",
|
2072
|
+
"main-ba741735a93c9314bbfa.js.LICENSE.txt": "main-ba741735a93c9314bbfa.js.LICENSE.txt",
|
2073
|
+
"main-ba741735a93c9314bbfa.js.gz": "main-ba741735a93c9314bbfa.js.gz",
|
2074
|
+
"main.css": "main-ba741735a93c9314bbfa.css",
|
2075
|
+
"main.js": "main-ba741735a93c9314bbfa.js",
|
2076
2076
|
"man.svg": "icons/man.svg",
|
2077
2077
|
"manual-gearbox.svg": "icons/manual-gearbox.svg",
|
2078
2078
|
"map-2.svg": "icons/map-2.svg",
|
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.58
|
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-06-
|
11
|
+
date: 2021-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord-filter
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '5.0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: cancancan
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- LICENSE
|
122
122
|
- README.md
|
123
123
|
- Rakefile
|
124
|
+
- app/controllers/concerns/motor/current_ability.rb
|
124
125
|
- app/controllers/concerns/motor/current_user_method.rb
|
125
126
|
- app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb
|
126
127
|
- app/controllers/concerns/motor/wrap_io_params.rb
|
@@ -191,6 +192,7 @@ files:
|
|
191
192
|
- lib/motor/build_schema.rb
|
192
193
|
- lib/motor/build_schema/active_storage_attachment_schema.rb
|
193
194
|
- lib/motor/build_schema/adjust_devise_model_schema.rb
|
195
|
+
- lib/motor/build_schema/apply_permissions.rb
|
194
196
|
- lib/motor/build_schema/find_display_column.rb
|
195
197
|
- lib/motor/build_schema/find_icon.rb
|
196
198
|
- lib/motor/build_schema/load_from_rails.rb
|
@@ -198,6 +200,9 @@ files:
|
|
198
200
|
- lib/motor/build_schema/persist_resource_configs.rb
|
199
201
|
- lib/motor/build_schema/reorder_schema.rb
|
200
202
|
- lib/motor/build_schema/utils.rb
|
203
|
+
- lib/motor/cancan_utils.rb
|
204
|
+
- lib/motor/cancan_utils/ability_patch.rb
|
205
|
+
- lib/motor/cancan_utils/can_manage_all.rb
|
201
206
|
- lib/motor/configs.rb
|
202
207
|
- lib/motor/configs/build_configs_hash.rb
|
203
208
|
- lib/motor/configs/build_ui_app_tag.rb
|
@@ -1485,8 +1490,8 @@ files:
|
|
1485
1490
|
- ui/dist/icons/zoom-money.svg.gz
|
1486
1491
|
- ui/dist/icons/zoom-out.svg.gz
|
1487
1492
|
- ui/dist/icons/zoom-question.svg.gz
|
1488
|
-
- ui/dist/main-
|
1489
|
-
- ui/dist/main-
|
1493
|
+
- ui/dist/main-ba741735a93c9314bbfa.css.gz
|
1494
|
+
- ui/dist/main-ba741735a93c9314bbfa.js.gz
|
1490
1495
|
- ui/dist/manifest.json
|
1491
1496
|
homepage:
|
1492
1497
|
licenses:
|
Binary file
|