avo 0.4.1 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/controllers/avo/application_controller.rb +12 -1
  4. data/app/controllers/avo/relations_controller.rb +1 -1
  5. data/app/controllers/avo/resource_overview_controller.rb +1 -6
  6. data/app/controllers/avo/resources_controller.rb +11 -17
  7. data/app/controllers/avo/search_controller.rb +3 -3
  8. data/app/views/layouts/avo/_javascript.html.erb +3 -3
  9. data/app/views/layouts/avo/_translations.html.erb +2 -2
  10. data/app/views/layouts/avo/application.html.erb +3 -3
  11. data/lib/avo/app/app.rb +10 -0
  12. data/lib/avo/app/fields/belongs_to.rb +12 -1
  13. data/lib/avo/app/fields/has_many.rb +4 -2
  14. data/lib/avo/app/filter.rb +1 -12
  15. data/lib/avo/app/resource.rb +10 -3
  16. data/lib/avo/app/services/authorization_service.rb +8 -0
  17. data/lib/avo/configuration.rb +12 -0
  18. data/lib/avo/version.rb +1 -1
  19. data/lib/generators/avo/templates/initializer/avo.rb +37 -1
  20. data/public/avo-packs/css/application-c9595d99.css +3 -0
  21. data/public/avo-packs/css/application-c9595d99.css.br +0 -0
  22. data/public/avo-packs/css/application-c9595d99.css.gz +0 -0
  23. data/public/avo-packs/js/application-54cdc48985a045c704ef.js +3 -0
  24. data/public/avo-packs/js/{application-84e2d573c3c15df1fb7b.js.LICENSE.txt → application-54cdc48985a045c704ef.js.LICENSE.txt} +0 -0
  25. data/public/avo-packs/js/application-54cdc48985a045c704ef.js.br +0 -0
  26. data/public/avo-packs/js/application-54cdc48985a045c704ef.js.gz +0 -0
  27. data/public/avo-packs/js/application-54cdc48985a045c704ef.js.map +1 -0
  28. data/public/avo-packs/js/application-54cdc48985a045c704ef.js.map.br +0 -0
  29. data/public/avo-packs/js/application-54cdc48985a045c704ef.js.map.gz +0 -0
  30. data/public/avo-packs/manifest.json +6 -6
  31. data/public/avo-packs/manifest.json.br +0 -0
  32. data/public/avo-packs/manifest.json.gz +0 -0
  33. metadata +12 -12
  34. data/public/avo-packs/css/application-2f609d81.css +0 -3
  35. data/public/avo-packs/css/application-2f609d81.css.br +0 -0
  36. data/public/avo-packs/css/application-2f609d81.css.gz +0 -0
  37. data/public/avo-packs/js/application-84e2d573c3c15df1fb7b.js +0 -3
  38. data/public/avo-packs/js/application-84e2d573c3c15df1fb7b.js.br +0 -0
  39. data/public/avo-packs/js/application-84e2d573c3c15df1fb7b.js.gz +0 -0
  40. data/public/avo-packs/js/application-84e2d573c3c15df1fb7b.js.map +0 -1
  41. data/public/avo-packs/js/application-84e2d573c3c15df1fb7b.js.map.br +0 -0
  42. data/public/avo-packs/js/application-84e2d573c3c15df1fb7b.js.map.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12b4c2f7a1b63d7296ac6f9b8edb5f133884ca5b10d1ed5c5a85e230364dad07
4
- data.tar.gz: 5dd72ab388c40de38a1a36e3bf077360afabf0e75fe1922feec31f1cc9cd7913
3
+ metadata.gz: f524eb45dfab913083b9fc23de6c35146d59436336d3e444ae8b525b9a70e6b2
4
+ data.tar.gz: 4075e8ca48aff4aa7cbd21a52ee6b6e67535a0bcf69652ed3f9298d39fbfde2f
5
5
  SHA512:
6
- metadata.gz: d2369b3f99c6244a3e0a4966cac220283f2f2bef7c99edbc31e56407f4a3100460691b663486a7bf96626eee5086861e3295f6e04f066cedff79c25f9b4927c5
7
- data.tar.gz: d98ce0432dfa0157ea480f21bb028c65bc33e9e2a59e88731efbde478806dcae96a04524ce04993741778329bddaa7083a8be69b71bea4b1282b2219550e2b01
6
+ metadata.gz: e3c1a13390fee90c6fb892eeae21d66151a66aa29055d16437251060f341bd86eba8315caf0a249330ee5d5f4b1943276cf79862e0bb361ec07f5ba7df50fc1d
7
+ data.tar.gz: 402ded6bc6111f30321d03eb2282895acdc25761567efb42e260e7c971854a305022f13afe8d300c947792796e2e5fe17c0f36204938ce14c05f4679cc214ccc
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (0.4.1)
4
+ avo (0.4.6)
5
5
  countries
6
6
  httparty
7
7
  i18n-js
@@ -3,6 +3,9 @@ module Avo
3
3
  rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
4
4
  protect_from_forgery with: :exception
5
5
  before_action :init_app
6
+ before_action :_authenticate!
7
+
8
+ helper_method :_current_user
6
9
 
7
10
  def init_app
8
11
  Avo::App.boot if Avo::IN_DEVELOPMENT
@@ -22,6 +25,10 @@ module Avo
22
25
  end
23
26
  end
24
27
 
28
+ def _current_user
29
+ instance_eval(&Avo.configuration.current_user)
30
+ end
31
+
25
32
  private
26
33
  def resource
27
34
  eager_load_files(resource_model).find params[:id]
@@ -54,11 +61,15 @@ module Avo
54
61
  record = resource
55
62
  end
56
63
 
57
- return render_unauthorized unless AuthorizationService::authorize_action current_user, record, params[:action]
64
+ return render_unauthorized unless AuthorizationService::authorize_action _current_user, record, params[:action]
58
65
  end
59
66
 
60
67
  def render_unauthorized
61
68
  render json: { message: I18n.t('avo.unauthorized') }, status: 403
62
69
  end
70
+
71
+ def _authenticate!
72
+ instance_eval(&Avo.configuration.authenticate)
73
+ end
63
74
  end
64
75
  end
@@ -28,7 +28,7 @@ module Avo
28
28
  end
29
29
 
30
30
  def attachment_model
31
- attachment_class.safe_constantize.find params[:attachment_id]
31
+ resource._reflections[params[:attachment_name].to_s].klass.find params[:attachment_id]
32
32
  end
33
33
  end
34
34
  end
@@ -4,7 +4,7 @@ module Avo
4
4
  class ResourceOverviewController < ApplicationController
5
5
  def index
6
6
  resources = App.get_resources
7
- .select { |resource| AuthorizationService::authorize session_user, resource.model, Avo.configuration.authorization_methods.stringify_keys['index'] }
7
+ .select { |resource| AuthorizationService::authorize _current_user, resource.model, Avo.configuration.authorization_methods.stringify_keys['index'] }
8
8
  .sort_by(&:name)
9
9
  .map do |resource|
10
10
  {
@@ -20,10 +20,5 @@ module Avo
20
20
  hide_docs: Avo.configuration.hide_documentation_link,
21
21
  }
22
22
  end
23
-
24
- private
25
- def session_user
26
- current_user.present? ? current_user : nil
27
- end
28
23
  end
29
24
  end
@@ -10,14 +10,14 @@ module Avo
10
10
  params[:sort_by] = params[:sort_by].present? ? params[:sort_by] : :created_at
11
11
  params[:sort_direction] = params[:sort_direction].present? ? params[:sort_direction] : :desc
12
12
 
13
- query = AuthorizationService.with_policy current_user, resource_model
13
+ query = AuthorizationService.with_policy _current_user, resource_model
14
14
 
15
15
  if params[:via_resource_name].present? and params[:via_resource_id].present? and params[:via_relationship].present?
16
16
  # get the related resource (via_resource)
17
17
  related_model = App.get_resource_by_name(params[:via_resource_name]).model
18
18
 
19
19
  relation = related_model.find(params[:via_resource_id]).public_send(params[:via_relationship])
20
- query = AuthorizationService.with_policy current_user, relation
20
+ query = AuthorizationService.with_policy _current_user, relation
21
21
 
22
22
  params[:per_page] = Avo.configuration.via_per_page
23
23
  elsif ['has_many', 'has_and_belongs_to_many'].include? params[:for_relation]
@@ -52,7 +52,7 @@ module Avo
52
52
 
53
53
  resources_with_fields = []
54
54
  resources.each do |resource|
55
- resources_with_fields << Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :index, user: current_user)
55
+ resources_with_fields << Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :index, user: _current_user)
56
56
  end
57
57
 
58
58
  render json: {
@@ -66,7 +66,7 @@ module Avo
66
66
 
67
67
  def show
68
68
  render json: {
69
- resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: @view || :show, user: current_user),
69
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: @view || :show, user: _current_user),
70
70
  }
71
71
  end
72
72
 
@@ -94,7 +94,7 @@ module Avo
94
94
 
95
95
  render json: {
96
96
  success: true,
97
- resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :show, user: current_user),
97
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :show, user: _current_user),
98
98
  message: I18n.t('avo.resource_updated'),
99
99
  }
100
100
  end
@@ -117,14 +117,14 @@ module Avo
117
117
 
118
118
  render json: {
119
119
  success: true,
120
- resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :create, user: current_user),
120
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :create, user: _current_user),
121
121
  message: I18n.t('avo.resource_created'),
122
122
  }
123
123
  end
124
124
 
125
125
  def new
126
126
  render json: {
127
- resource: Avo::Resources::Resource.hydrate_resource(model: resource_model.new, resource: avo_resource, view: :create, user: current_user),
127
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource_model.new, resource: avo_resource, view: :create, user: _current_user),
128
128
  }
129
129
  end
130
130
 
@@ -224,8 +224,8 @@ module Avo
224
224
  avo_resource.get_filters.each do |filter_class|
225
225
  filter = filter_class.new
226
226
 
227
- if filter.default_value.present?
228
- filter_defaults[filter_class.to_s] = filter.default_value
227
+ if filter.default.present?
228
+ filter_defaults[filter_class.to_s] = filter.default
229
229
  end
230
230
  end
231
231
 
@@ -252,17 +252,11 @@ module Avo
252
252
 
253
253
  def build_meta
254
254
  {
255
- per_page_steps: Avo.configuration.per_page_steps,
255
+ per_page_steps: [*Avo.configuration.per_page_steps, Avo.configuration.per_page.to_i].sort.uniq,
256
256
  available_view_types: avo_resource.available_view_types,
257
257
  default_view_type: avo_resource.default_view_type || Avo.configuration.default_view_type,
258
258
  translation_key: avo_resource.translation_key,
259
- authorization: {
260
- create: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['create']),
261
- edit: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['edit']),
262
- update: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['update']),
263
- show: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['show']),
264
- destroy: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['destroy']),
265
- },
259
+ authorization: AuthorizationService::authorized_methods(_current_user, avo_resource.model)
266
260
  }
267
261
  end
268
262
  end
@@ -9,7 +9,7 @@ module Avo
9
9
 
10
10
  resources_to_search_through = App.get_resources
11
11
  .select { |resource| resource.search.present? }
12
- .select { |resource| AuthorizationService.authorize_action current_user, resource.model, 'index' }
12
+ .select { |resource| AuthorizationService.authorize_action _current_user, resource.model, 'index' }
13
13
  .each do |resource_model|
14
14
  found_resources = add_link_to_search_results(search_resource(resource_model), resource_model)
15
15
  resources.push({
@@ -41,7 +41,7 @@ module Avo
41
41
  end
42
42
 
43
43
  def search_resource(avo_resource)
44
- avo_resource.query_search(query: params[:q], via_resource_name: params[:via_resource_name], via_resource_id: params[:via_resource_id], user: current_user)
44
+ avo_resource.query_search(query: params[:q], via_resource_name: params[:via_resource_name], via_resource_id: params[:via_resource_id], user: _current_user)
45
45
  end
46
46
 
47
47
  def authorize_user
@@ -49,7 +49,7 @@ module Avo
49
49
 
50
50
  action = params[:action] == 'resource' ? :index : params[:action]
51
51
 
52
- return render_unauthorized unless AuthorizationService::authorize_action current_user, avo_resource.model, action
52
+ return render_unauthorized unless AuthorizationService::authorize_action _current_user, avo_resource.model, action
53
53
  end
54
54
  end
55
55
  end
@@ -1,8 +1,8 @@
1
- <script>
1
+ <%= javascript_tag nonce: true do %>
2
2
  var rootPath = '<%= Avo.configuration.root_path %>';
3
3
  var timezone = '<%= Avo.configuration.timezone %>';
4
4
  var locale = '<%= Avo.configuration.locale %>';
5
5
  var defaultViewType = '<%= Avo.configuration.default_view_type %>';
6
6
  var license = <%= Avo::App.license.properties.to_json.html_safe %>;
7
- var avoResources = <%= Avo::App.get_available_resources(current_user).as_json.html_safe %>;
8
- </script>
7
+ var avoResources = <%= Avo::App.get_available_resources(_current_user).as_json.html_safe %>;
8
+ <% end %>
@@ -1,5 +1,5 @@
1
- <script>
1
+ <%= javascript_tag nonce: true do %>
2
2
  I18n.defaultLocale = 'en';
3
3
  I18n.locale = "<%= Avo.configuration.language_code %>";
4
- </script>
4
+ <% end %>
5
5
  <%= javascript_include_tag 'translations', skip_pipeline: true %>
@@ -30,8 +30,8 @@
30
30
  </template>
31
31
  </application-sidebar>
32
32
 
33
- <div class="flex-1 h-full overflow-auto">
34
- <div class="relative bg-white p-2 shadow-md h-16 w-full flex items-center z-50" v-if="layout !== 'blank'">
33
+ <div class="flex-1 flex flex-col h-full overflow-auto">
34
+ <div class="relative bg-white p-2 shadow-md h-16 w-full flex flex-shrink-0 items-center z-50" v-if="layout !== 'blank'">
35
35
  <div class="ml-6">
36
36
  <%= render_header %>
37
37
  </div>
@@ -46,7 +46,7 @@
46
46
  <%= yield %>
47
47
  </div>
48
48
 
49
- <div class="content p-8" v-else>
49
+ <div class="content p-8 flex-1 flex flex-col justify-between items-stretch" v-else>
50
50
  <%= yield %>
51
51
  <%= render_footer %>
52
52
  </div>
@@ -132,6 +132,16 @@ module Avo
132
132
  self.get_resource name.singularize.camelize
133
133
  end
134
134
 
135
+ # This returns the Avo resource by singular snake_cased name
136
+ #
137
+ # get_resource_by_name('User') => Avo::Resources::User
138
+ # get_resource_by_name(User) => Avo::Resources::User
139
+ def get_resource_by_model_name(name)
140
+ get_resources.find do |resource|
141
+ resource.class.name.demodulize == name.to_s
142
+ end
143
+ end
144
+
135
145
  # This returns the Rails model class by singular snake_cased name
136
146
  #
137
147
  # get_model_class_by_name('user') => User
@@ -22,7 +22,8 @@ module Avo
22
22
  fields[:searchable] = @searchable
23
23
  fields[:is_relation] = true
24
24
  fields[:database_id] = foreign_key model
25
- target_resource = App.get_resources.find { |r| r.class == "Avo::Resources::#{name}".safe_constantize }
25
+
26
+ target_resource = get_target_resource model
26
27
 
27
28
  relation_model = model.public_send(@relation_method)
28
29
 
@@ -61,6 +62,16 @@ module Avo
61
62
  model.class.reflections[@relation_method].foreign_key
62
63
  end
63
64
  end
65
+
66
+ def get_target_resource(model)
67
+ if model._reflections[id.to_s].klass.present?
68
+ App.get_resource_by_model_name model._reflections[id.to_s].klass.to_s
69
+ elsif model._reflections[id.to_s].options[:class_name].present?
70
+ App.get_resource_by_model_name model._reflections[id.to_s].options[:class_name]
71
+ else
72
+ App.get_resource_by_name class_name.to_s
73
+ end
74
+ end
64
75
  end
65
76
  end
66
77
  end
@@ -6,6 +6,7 @@ module Avo
6
6
  updatable: false,
7
7
  component: 'has-many-field'
8
8
  }
9
+ @through = args[:through]
9
10
 
10
11
  super(name, **args, &block)
11
12
 
@@ -27,6 +28,7 @@ module Avo
27
28
  fields[:relation_class] = target_resource.class.to_s
28
29
  fields[:path] = target_resource.url
29
30
  fields[:relationship] = :has_many
31
+ fields[:through] = @through
30
32
  fields[:relationship_model] = target_resource.model.name
31
33
 
32
34
  fields
@@ -40,8 +42,8 @@ module Avo
40
42
  if @resource.present?
41
43
  App.get_resources.find { |r| r.class == @resource }
42
44
  else
43
- class_name = model._reflections[id.to_s].options[:class_name].present? ? model._reflections[id.to_s].options[:class_name] : model._reflections[id.to_s].name
44
- App.get_resources.find { |r| r.class == "Avo::Resources::#{class_name.to_s.camelcase.singularize}".safe_constantize }
45
+ class_name = model._reflections[id.to_s].options[:class_name].present? ? model._reflections[id.to_s].options[:class_name] : model._reflections[id.to_s].klass.name
46
+ App.get_resource_by_model_name class_name
45
47
  end
46
48
  end
47
49
  end
@@ -4,8 +4,6 @@ module Avo
4
4
  attr_accessor :component
5
5
  attr_accessor :default
6
6
 
7
- @@default = nil
8
-
9
7
  def initialize
10
8
  @name ||= 'Filter'
11
9
  @component ||= 'boolean-filter'
@@ -18,7 +16,7 @@ module Avo
18
16
  name: name,
19
17
  options: options,
20
18
  component: component,
21
- default: default_value,
19
+ default: default,
22
20
  filter_class: self.class.to_s,
23
21
  }
24
22
  end
@@ -32,14 +30,5 @@ module Avo
32
30
  def id
33
31
  self.class.name.underscore.gsub('/', '_')
34
32
  end
35
-
36
- # These methods helps us set a default value in the testing environment
37
- def default_value
38
- @@default || default
39
- end
40
-
41
- def self.set_default(value)
42
- @@default = value
43
- end
44
33
  end
45
34
  end
@@ -13,7 +13,14 @@ module Avo
13
13
 
14
14
  class << self
15
15
  def hydrate_resource(model:, resource:, view: :index, user:)
16
- default_panel_name = I18n.t 'avo.resource_details', name: resource.name
16
+ case view
17
+ when :show
18
+ panel_name = I18n.t 'avo.resource_details', name: resource.name.downcase.upcase_first
19
+ when :edit
20
+ panel_name = I18n.t('avo.edit_item', item: resource.name.downcase).upcase_first
21
+ when :create
22
+ panel_name = I18n.t('avo.create_new_item', item: resource.name.downcase).upcase_first
23
+ end
17
24
 
18
25
  resource_with_fields = {
19
26
  id: model.id,
@@ -26,7 +33,7 @@ module Avo
26
33
  fields: [],
27
34
  grid_fields: {},
28
35
  panels: [{
29
- name: default_panel_name,
36
+ name: panel_name,
30
37
  component: 'panel',
31
38
  }]
32
39
  }
@@ -46,7 +53,7 @@ module Avo
46
53
 
47
54
  next if furnished_field.blank?
48
55
 
49
- furnished_field[:panel_name] = default_panel_name
56
+ furnished_field[:panel_name] = panel_name
50
57
  furnished_field[:show_on_show] = field.show_on_show
51
58
 
52
59
  if field.has_own_panel?
@@ -3,6 +3,7 @@ module Avo
3
3
  class << self
4
4
  def authorize(user, record, action)
5
5
  return true if skip_authorization
6
+ return true if user.nil?
6
7
 
7
8
  begin
8
9
  if Pundit.policy user, record
@@ -24,6 +25,7 @@ module Avo
24
25
 
25
26
  def with_policy(user, model)
26
27
  return model if skip_authorization
28
+ return model if user.nil?
27
29
 
28
30
  begin
29
31
  Pundit.policy_scope! user, model
@@ -35,6 +37,12 @@ module Avo
35
37
  def skip_authorization
36
38
  Avo::App.license.lacks :authorization
37
39
  end
40
+
41
+ def authorized_methods(user, record)
42
+ [:create, :edit, :update, :show, :destroy].map do |method|
43
+ [method, authorize(user, record, Avo.configuration.authorization_methods[method])]
44
+ end.to_h
45
+ end
38
46
  end
39
47
  end
40
48
  end
@@ -14,6 +14,8 @@ module Avo
14
14
  attr_accessor :license
15
15
  attr_accessor :license_key
16
16
  attr_accessor :authorization_methods
17
+ attr_accessor :authenticate
18
+ attr_accessor :current_user
17
19
 
18
20
  def initialize
19
21
  @root_path = '/avo'
@@ -29,6 +31,8 @@ module Avo
29
31
  @hide_documentation_link = false
30
32
  @license = 'community'
31
33
  @license_key = nil
34
+ @current_user = proc {}
35
+ @authenticate = proc {}
32
36
  @authorization_methods = {
33
37
  index: 'index?',
34
38
  show: 'show?',
@@ -51,6 +55,14 @@ module Avo
51
55
  'en'
52
56
  end
53
57
  end
58
+
59
+ def current_user_method(&block)
60
+ @current_user = block if block.present?
61
+ end
62
+
63
+ def authenticate_with(&block)
64
+ @authenticate = block if block.present?
65
+ end
54
66
  end
55
67
 
56
68
  def self.configuration