avo 0.2.2 → 0.3.2

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +49 -48
  3. data/Gemfile.lock +19 -2
  4. data/README.md +30 -9
  5. data/app/controllers/avo/application_controller.rb +34 -1
  6. data/app/controllers/avo/filters_controller.rb +19 -0
  7. data/app/controllers/avo/relations_controller.rb +34 -0
  8. data/app/controllers/avo/resource_overview_controller.rb +14 -7
  9. data/app/controllers/avo/resources_controller.rb +66 -142
  10. data/app/controllers/avo/search_controller.rb +55 -0
  11. data/app/helpers/avo/application_helper.rb +6 -2
  12. data/app/views/layouts/avo/_javascript.html.erb +1 -0
  13. data/app/views/layouts/avo/application.html.erb +34 -17
  14. data/app/views/partials/_header.html.erb +1 -1
  15. data/avo.gemspec +4 -2
  16. data/config/credentials.yml.enc +1 -0
  17. data/config/routes.rb +11 -7
  18. data/lib/avo.rb +2 -0
  19. data/lib/avo/app/app.rb +18 -29
  20. data/lib/avo/app/authorization_service.rb +40 -0
  21. data/lib/avo/app/fields/has_and_belongs_to_many.rb +1 -0
  22. data/lib/avo/app/fields/has_many.rb +1 -0
  23. data/lib/avo/app/fields/id_field.rb +4 -4
  24. data/lib/avo/app/licensing/community_license.rb +4 -0
  25. data/lib/avo/app/licensing/hq.rb +85 -0
  26. data/lib/avo/app/licensing/license.rb +48 -0
  27. data/lib/avo/app/licensing/license_manager.rb +25 -0
  28. data/lib/avo/app/licensing/null_license.rb +12 -0
  29. data/lib/avo/app/licensing/pro_license.rb +9 -0
  30. data/lib/avo/app/resource.rb +32 -12
  31. data/lib/avo/configuration.rb +14 -0
  32. data/lib/avo/engine.rb +3 -3
  33. data/lib/avo/version.rb +1 -1
  34. data/lib/generators/avo/templates/initializer.rb +2 -0
  35. data/lib/generators/avo/templates/views/_header.html.erb +1 -1
  36. data/lib/generators/avo/templates/views/_scripts.html.erb +0 -0
  37. data/public/avo-packs/css/application-73e568bc.css +3 -0
  38. data/public/avo-packs/css/application-73e568bc.css.br +0 -0
  39. data/public/avo-packs/css/application-73e568bc.css.gz +0 -0
  40. data/public/avo-packs/js/application-725ee54e3adbcd950843.js +3 -0
  41. data/public/avo-packs/js/{application-9a0dde96ad9918852965.js.LICENSE.txt → application-725ee54e3adbcd950843.js.LICENSE.txt} +0 -0
  42. data/public/avo-packs/js/application-725ee54e3adbcd950843.js.br +0 -0
  43. data/public/avo-packs/js/application-725ee54e3adbcd950843.js.gz +0 -0
  44. data/public/avo-packs/js/application-725ee54e3adbcd950843.js.map +1 -0
  45. data/public/avo-packs/js/application-725ee54e3adbcd950843.js.map.br +0 -0
  46. data/public/avo-packs/js/application-725ee54e3adbcd950843.js.map.gz +0 -0
  47. data/public/avo-packs/manifest.json +8 -6
  48. data/public/avo-packs/manifest.json.br +0 -0
  49. data/public/avo-packs/manifest.json.gz +0 -0
  50. data/public/avo-packs/media/svgs/arrow-circle-right-1ad1e15ec9a7aa54b67d126566a5aa2d.svg +1 -0
  51. data/public/avo-packs/media/svgs/arrow-circle-right-1ad1e15ec9a7aa54b67d126566a5aa2d.svg.br +0 -0
  52. data/public/avo-packs/media/svgs/arrow-circle-right-1ad1e15ec9a7aa54b67d126566a5aa2d.svg.gz +0 -0
  53. data/public/avo-packs/media/svgs/exclamation-8d1c0baa390a8df9bb52176011eb5892.svg +1 -0
  54. data/public/avo-packs/media/svgs/exclamation-8d1c0baa390a8df9bb52176011eb5892.svg.br +0 -0
  55. data/public/avo-packs/media/svgs/exclamation-8d1c0baa390a8df9bb52176011eb5892.svg.gz +0 -0
  56. metadata +61 -21
  57. data/public/avo-packs/css/application-5dc4dd78.css +0 -3
  58. data/public/avo-packs/css/application-5dc4dd78.css.br +0 -0
  59. data/public/avo-packs/css/application-5dc4dd78.css.gz +0 -0
  60. data/public/avo-packs/js/application-9a0dde96ad9918852965.js +0 -3
  61. data/public/avo-packs/js/application-9a0dde96ad9918852965.js.br +0 -0
  62. data/public/avo-packs/js/application-9a0dde96ad9918852965.js.gz +0 -0
  63. data/public/avo-packs/js/application-9a0dde96ad9918852965.js.map +0 -1
  64. data/public/avo-packs/js/application-9a0dde96ad9918852965.js.map.br +0 -0
  65. data/public/avo-packs/js/application-9a0dde96ad9918852965.js.map.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 198006f28e691ccb555906b5533d27ec462f8408db87546ad5b68ac752b851b6
4
- data.tar.gz: 2f8a82f6cdb2be871bc1f6444175cab56c3039cc4a3882e8da811df095520ff3
3
+ metadata.gz: 7fc8f29ce910c3eeb8bb2d80e61bc7b65385fd0b4bbb71ef9cf85556cf943bc3
4
+ data.tar.gz: 277415ac5daec5c8985d3ee62e2ec3dd779ea23df8b5fbc0993fb64da774a54a
5
5
  SHA512:
6
- metadata.gz: a92f2a5ee48bd33d43cb8105044921a1ed2a4af5a5a21a86623df92fa48717cd11988e80b2dad383fad7b0492dc5a00143c1f02c616bbef22cd6b38ee78b73af
7
- data.tar.gz: 65a815513c65738740a796d7b59c3fff96e9acf4d74e360ddb735c979dab615de270fa15e631782b5f93d9804449a7ab10ec6503cb4efc7272f78f214e0c7278
6
+ metadata.gz: e44bf33db4a90366e85780d500d0d476b22b74a8cdec88bb39c1da5e86e5dad6c866bef3f5ab8386f6a51b382aa1ec19ec2f8d20e3aa940ced316d8ca3558701
7
+ data.tar.gz: 2365d6464818c443ccb4808c041c084d1cfa5a795e63419e90524be642c64c817249e59b69b27d569ba97247c50089a58511c8f45d2106716f1d028bb506c3d6
data/Gemfile CHANGED
@@ -23,54 +23,52 @@ gem 'inline_svg'
23
23
  gem 'countries'
24
24
 
25
25
  # Authorization
26
- gem "pundit"
27
-
28
- # These are the dummy app's dependencies
29
- group :development, :test do
30
- # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
31
- gem 'rails', '~> 6.0.2', '>= 6.0.2.2'
32
- # Use postgresql as the database for Active Record
33
- gem 'pg', '>= 0.18', '< 2.0'
34
- # Use Puma as the app server
35
- gem 'puma', '~> 4.3.5'
36
- # Use SCSS for stylesheets
37
- gem 'sass-rails', '>= 6'
38
- # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
39
- # gem 'turbolinks', '~> 5'
40
- # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
41
- gem 'jbuilder', '~> 2.7'
42
- # Use Redis adapter to run Action Cable in production
43
- # gem 'redis', '~> 4.0'
44
- # Use Active Model has_secure_password
45
- # gem 'bcrypt', '~> 3.1.7'
46
-
47
- # Use Active Storage variant
48
- # gem 'image_processing', '~> 1.2'
49
-
50
- # Reduces boot times through caching; required in config/boot.rb
51
- gem 'bootsnap', '>= 1.4.2', require: false
52
- # Call 'byebug' anywhere in the code to stop execution and get a debugger console
53
- gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
54
- gem 'dotenv-rails'
55
- # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
56
- gem 'web-console', '>= 3.3.0'
57
- gem 'listen', '>= 3.0.5', '< 3.2'
58
- # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
59
- gem 'spring'
60
- gem 'spring-watcher-listen', '~> 2.0.0'
61
-
62
- gem 'factory_bot_rails'
63
- gem 'faker'
64
-
65
- # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
66
- gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
67
-
68
- gem 'devise'
69
- gem 'database_cleaner'
70
-
71
- gem 'ruby-debug-ide', require: false
72
- gem 'debase'
73
- end
26
+ gem 'pundit'
27
+
28
+ # Dependencies for dummy_app
29
+ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
30
+ gem 'rails', '~> 6.0.2', '>= 6.0.2.2'
31
+ # Use postgresql as the database for Active Record
32
+ gem 'pg', '>= 0.18', '< 2.0'
33
+ # Use Puma as the app server
34
+ gem 'puma', '~> 4.3.5'
35
+ # Use SCSS for stylesheets
36
+ gem 'sass-rails', '>= 6'
37
+ # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
38
+ # gem 'turbolinks', '~> 5'
39
+ # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
40
+ gem 'jbuilder', '~> 2.7'
41
+ # Use Redis adapter to run Action Cable in production
42
+ # gem 'redis', '~> 4.0'
43
+ # Use Active Model has_secure_password
44
+ # gem 'bcrypt', '~> 3.1.7'
45
+
46
+ # Use Active Storage variant
47
+ # gem 'image_processing', '~> 1.2'
48
+
49
+ # Reduces boot times through caching; required in config/boot.rb
50
+ gem 'bootsnap', '>= 1.4.2', require: false
51
+ # Call 'byebug' anywhere in the code to stop execution and get a debugger console
52
+ gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
53
+ gem 'dotenv-rails'
54
+ # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
55
+ gem 'web-console', '>= 3.3.0'
56
+ gem 'listen', '>= 3.0.5', '< 3.2'
57
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
58
+ gem 'spring'
59
+ gem 'spring-watcher-listen', '~> 2.0.0'
60
+
61
+ gem 'factory_bot_rails'
62
+ gem 'faker'
63
+
64
+ # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
65
+ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
66
+
67
+ gem 'devise'
68
+ gem 'database_cleaner'
69
+
70
+ gem 'ruby-debug-ide', require: false
71
+ gem 'debase'
74
72
 
75
73
  group :development, :test do
76
74
  gem 'rspec-rails', '~> 4.0.0'
@@ -83,6 +81,7 @@ group :development, :test do
83
81
  gem 'rubocop'
84
82
  gem 'simplecov', require: false
85
83
  gem 'simplecov-cobertura'
84
+ gem 'webmock'
86
85
 
87
86
  # Release helper
88
87
  gem 'bump', require: false
@@ -93,3 +92,5 @@ gem 'zeitwerk', '~> 2.3'
93
92
 
94
93
  # Pagination
95
94
  gem 'kaminari'
95
+
96
+ gem 'httparty'
@@ -1,11 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (0.2.2)
4
+ avo (0.3.2)
5
5
  countries
6
+ httparty
6
7
  inline_svg
7
8
  kaminari
8
- rails (~> 6.0.2, >= 6.0.2.1)
9
+ pundit
10
+ rails (>= 6.0)
9
11
  webpacker
10
12
  zeitwerk
11
13
 
@@ -91,6 +93,7 @@ GEM
91
93
  i18n_data (~> 0.10.0)
92
94
  sixarm_ruby_unaccent (~> 1.1)
93
95
  unicode_utils (~> 1.4)
96
+ crack (0.4.4)
94
97
  crass (1.0.6)
95
98
  database_cleaner (1.8.5)
96
99
  debase (0.2.4.1)
@@ -123,6 +126,10 @@ GEM
123
126
  gem-release (2.1.1)
124
127
  globalid (0.4.2)
125
128
  activesupport (>= 4.2.0)
129
+ hashdiff (1.0.1)
130
+ httparty (0.18.1)
131
+ mime-types (~> 3.0)
132
+ multi_xml (>= 0.5.2)
126
133
  i18n (1.8.5)
127
134
  concurrent-ruby (~> 1.0)
128
135
  i18n_data (0.10.0)
@@ -155,11 +162,15 @@ GEM
155
162
  marcel (0.3.3)
156
163
  mimemagic (~> 0.3.2)
157
164
  method_source (1.0.0)
165
+ mime-types (3.3.1)
166
+ mime-types-data (~> 3.2015)
167
+ mime-types-data (3.2020.0512)
158
168
  mimemagic (0.3.5)
159
169
  mini_mime (1.0.2)
160
170
  mini_portile2 (2.4.0)
161
171
  minitest (5.14.2)
162
172
  msgpack (1.3.3)
173
+ multi_xml (0.6.0)
163
174
  nio4r (2.5.4)
164
175
  nokogiri (1.10.10)
165
176
  mini_portile2 (~> 2.4.0)
@@ -296,6 +307,10 @@ GEM
296
307
  nokogiri (~> 1.6)
297
308
  rubyzip (>= 1.3.0)
298
309
  selenium-webdriver (>= 3.0, < 4.0)
310
+ webmock (3.9.3)
311
+ addressable (>= 2.3.6)
312
+ crack (>= 0.3.2)
313
+ hashdiff (>= 0.4.0, < 2.0.0)
299
314
  webpacker (4.3.0)
300
315
  activesupport (>= 4.2)
301
316
  rack-proxy (>= 0.6.1)
@@ -325,6 +340,7 @@ DEPENDENCIES
325
340
  faker
326
341
  fuubar
327
342
  gem-release
343
+ httparty
328
344
  inline_svg
329
345
  jbuilder (~> 2.7)
330
346
  kaminari
@@ -345,6 +361,7 @@ DEPENDENCIES
345
361
  tzinfo-data
346
362
  web-console (>= 3.3.0)
347
363
  webdrivers
364
+ webmock
348
365
  webpacker (~> 4.0)
349
366
  zeitwerk (~> 2.3)
350
367
 
data/README.md CHANGED
@@ -1,15 +1,41 @@
1
1
  ![Tests](https://github.com/avo-hq/avo/workflows/Tests/badge.svg)
2
2
  ![reviewdog](https://github.com/avo-hq/avo/workflows/reviewdog/badge.svg)
3
3
  [![codecov](https://codecov.io/gh/avo-hq/avo/branch/master/graph/badge.svg?token=Q2LMFE4989)](https://codecov.io/gh/avo-hq/avo)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/676a0afa2cc79f03aa29/maintainability)](https://codeclimate.com/github/avo-hq/avo/maintainability)
4
5
 
5
- # Avo
6
- Configuration-based, no-maintenance, extendable Ruby on Rails admin
6
+ ![](https://avohq.io/img/logo-full-stroke-tiny-2x.png)
7
+
8
+ **Configuration-based, no-maintenance, extendable Ruby on Rails admin**
7
9
 
8
10
  Avo is a beautiful next-generation framework that empowers you, the developer, to create fantastic admin panels for your Ruby on Rails apps with the flexibility to fit your needs as you grow.
9
11
 
10
- [Get started](https://avohq.io/get-started)
12
+ ## Get started
13
+
14
+ **Website**: [avohq.io](https://avohq.io)\
15
+ **Documentation**: [docs.avohq.io](https://docs.avohq.io)\
16
+ **Twitter**: [avo_hq](https://twitter.com/avo_hq)\
17
+ **Community chat**: [discord](https://discord.gg/pkTF6y8)\
18
+ **Issue tracker**: [GitHub issues](http://github.com/avo-hq/avo/issues)
19
+
20
+ ## Features
11
21
 
12
- ## Installation
22
+ - **Code driven configuration** - Configure your Rails dashboard entirely by writing Ruby code.
23
+ - **Resource Management** - Create a CRUD interface for Active Record from one command. No more copy-pasting view and controller files around.
24
+ - **Active Storage support** - Amazingly easy, **one-line**, single or multi-file integration with **ActiveStorage**.
25
+ - **Grid view** - Beautiful card layout to showcase your content.
26
+ - **Actions** - Run custom actions to one or more of your resources with as little as pressing a button 💪
27
+ - **Filters** - Write your own custom filters to quickly segment your data.
28
+ - **Keeps your app clean** - You don't need to change your app to use Avo. Drop it in your existing app or add it to a new one and you're done 🙌
29
+ - **Custom fields***- No worries if we missed a field you need. Generate a custom field in a jiffy.
30
+ - **Dashboard widgets and metrics*** - Customize your dashboard with the tools and analytics you need.
31
+ - **Custom tools*** - You need to add a page with something completely new, you've got it!
32
+ - **Authorization** - Leverage Pundit policies to build a robust and scalable authorization system.
33
+ - **Themable*** - Dress it up into your own colors.
34
+ - **Localization*** - Have it available in any language you need.
35
+
36
+ *Some features are still under development
37
+
38
+ # Installation
13
39
  Add this line to your application's `Gemfile`:
14
40
 
15
41
  ```ruby
@@ -20,8 +46,3 @@ And then execute:
20
46
  ```bash
21
47
  $ bundle install
22
48
  ```
23
-
24
- Website: [avohq.io](https://avohq.io)\
25
- Docs: [docs.avohq.io](https://docs.avohq.io)\
26
- Twitter: [avo_hq](https://twitter.com/avo_hq)\
27
- Community: [discord](https://discord.gg/pkTF6y8)
@@ -5,7 +5,10 @@ module Avo
5
5
  before_action :init_app
6
6
 
7
7
  def init_app
8
- Avo::App.init
8
+ Avo::App.boot unless Rails.env.production?
9
+ Avo::App.init request
10
+
11
+ @license = Avo::App.license
9
12
  end
10
13
 
11
14
  def exception_logger(exception)
@@ -20,6 +23,20 @@ module Avo
20
23
  end
21
24
 
22
25
  private
26
+ def resource
27
+ eager_load_files(resource_model).find params[:id]
28
+ end
29
+
30
+ def eager_load_files(query)
31
+ if avo_resource.attached_file_fields.present?
32
+ avo_resource.attached_file_fields.map(&:id).map do |field|
33
+ query = query.send :"with_attached_#{field}"
34
+ end
35
+ end
36
+
37
+ query
38
+ end
39
+
23
40
  def resource_model
24
41
  avo_resource.model
25
42
  end
@@ -27,5 +44,21 @@ module Avo
27
44
  def avo_resource
28
45
  App.get_resource params[:resource_name].to_s.camelize.singularize
29
46
  end
47
+
48
+ def authorize_user
49
+ return if params[:controller] == 'avo/search'
50
+
51
+ model = record = avo_resource.model
52
+
53
+ if ['show', 'edit', 'update'].include?(params[:action]) && params[:controller] == 'avo/resources'
54
+ record = resource
55
+ end
56
+
57
+ return render_unauthorized unless AuthorizationService::authorize_action current_user, record, params[:action]
58
+ end
59
+
60
+ def render_unauthorized
61
+ render json: { message: 'Unauthorized' }, status: 403
62
+ end
30
63
  end
31
64
  end
@@ -0,0 +1,19 @@
1
+ require_dependency 'avo/application_controller'
2
+
3
+ module Avo
4
+ class FiltersController < ApplicationController
5
+ before_action :authorize_user
6
+
7
+ def index
8
+ filters = []
9
+
10
+ avo_resource.get_filters.each do |filter|
11
+ filters.push(filter.new.render_response)
12
+ end
13
+
14
+ render json: {
15
+ filters: filters,
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ require_dependency 'avo/application_controller'
2
+
3
+ module Avo
4
+ class RelationsController < ApplicationController
5
+ before_action :authorize_user
6
+
7
+ def attach
8
+ resource.send(params[:attachment_name]) << attachment_model
9
+
10
+ render json: {
11
+ success: true,
12
+ message: "#{attachment_class} attached.",
13
+ }
14
+ end
15
+
16
+ def detach
17
+ resource.send(params[:attachment_name]).delete attachment_model
18
+
19
+ render json: {
20
+ success: true,
21
+ message: "#{attachment_class} attached.",
22
+ }
23
+ end
24
+
25
+ private
26
+ def attachment_class
27
+ App.get_model_class_by_name params[:attachment_name].pluralize 1
28
+ end
29
+
30
+ def attachment_model
31
+ attachment_class.safe_constantize.find params[:attachment_id]
32
+ end
33
+ end
34
+ end
@@ -3,13 +3,15 @@ require_dependency 'avo/application_controller'
3
3
  module Avo
4
4
  class ResourceOverviewController < ApplicationController
5
5
  def index
6
- resources = App.get_resources.map do |resource|
7
- {
8
- name: resource.name,
9
- url: resource.url,
10
- count: resource.model.count,
11
- }
12
- end
6
+ resources = App.get_resources
7
+ .select { |resource| AuthorizationService::authorize session_user, resource.model, Avo.configuration.authorization_methods.stringify_keys['index'] }
8
+ .map do |resource|
9
+ {
10
+ name: resource.name,
11
+ url: resource.url,
12
+ count: resource.model.count,
13
+ }
14
+ end
13
15
 
14
16
  render json: {
15
17
  resources: resources,
@@ -17,5 +19,10 @@ module Avo
17
19
  hide_docs: Avo.configuration.hide_documentation_link,
18
20
  }
19
21
  end
22
+
23
+ private
24
+ def session_user
25
+ current_user.present? ? current_user : nil
26
+ end
20
27
  end
21
28
  end
@@ -2,21 +2,26 @@ require_dependency 'avo/application_controller'
2
2
 
3
3
  module Avo
4
4
  class ResourcesController < ApplicationController
5
+ before_action :authorize_user
6
+
5
7
  def index
6
8
  params[:page] ||= 1
7
9
  params[:per_page] ||= Avo.configuration.per_page
8
10
  params[:sort_by] = params[:sort_by].present? ? params[:sort_by] : :created_at
9
11
  params[:sort_direction] = params[:sort_direction].present? ? params[:sort_direction] : :desc
10
- filters = get_filters
12
+
13
+ query = AuthorizationService.with_policy current_user, resource_model
11
14
 
12
15
  if params[:via_resource_name].present? and params[:via_resource_id].present? and params[:via_relationship].present?
13
- # get the reated resource (via_resource)
14
- related_resource = App.get_resource_by_name(params[:via_resource_name])
15
- related_model = related_resource.model
16
- # fetch the entries
17
- query = related_model.find(params[:via_resource_id]).public_send(params[:via_relationship])
16
+ # get the related resource (via_resource)
17
+ related_model = App.get_resource_by_name(params[:via_resource_name]).model
18
+
19
+ relation = related_model.find(params[:via_resource_id]).public_send(params[:via_relationship])
20
+ query = AuthorizationService.with_policy current_user, relation
21
+
18
22
  params[:per_page] = Avo.configuration.via_per_page
19
23
  elsif ['has_many', 'has_and_belongs_to_many'].include? params[:for_relation]
24
+ # has_many searchable query
20
25
  resources = resource_model.all.map do |model|
21
26
  {
22
27
  value: model.id,
@@ -27,22 +32,18 @@ module Avo
27
32
  return render json: {
28
33
  resources: resources
29
34
  }
30
- else
31
- query = resource_model
32
35
  end
33
36
 
34
37
  query = query.order("#{params[:sort_by]} #{params[:sort_direction]}")
35
38
 
36
- if filters.present?
37
- filters.each do |filter_class, filter_value|
38
- query = filter_class.safe_constantize.new.apply_query request, query, filter_value
39
- end
39
+ applied_filters.each do |filter_class, filter_value|
40
+ query = filter_class.safe_constantize.new.apply_query request, query, filter_value
40
41
  end
41
42
 
42
43
  # Eager load the attachments
43
44
  query = eager_load_files(query)
44
45
 
45
- # Eager lood the relations
46
+ # Eager load the relations
46
47
  if avo_resource.includes.present?
47
48
  query = query.includes(*avo_resource.includes)
48
49
  end
@@ -51,48 +52,21 @@ module Avo
51
52
 
52
53
  resources_with_fields = []
53
54
  resources.each do |resource|
54
- resources_with_fields << Avo::Resources::Resource.hydrate_resource(resource, avo_resource, :index)
55
+ resources_with_fields << Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :index, user: current_user)
55
56
  end
56
57
 
57
- meta = {
58
- per_page_steps: Avo.configuration.per_page_steps,
59
- available_view_types: avo_resource.available_view_types,
60
- default_view_type: avo_resource.default_view_type || Avo.configuration.default_view_type,
61
- }
62
-
63
58
  render json: {
64
59
  success: true,
65
- meta: meta,
60
+ meta: build_meta,
66
61
  resources: resources_with_fields,
67
62
  per_page: params[:per_page],
68
63
  total_pages: resources.total_pages,
69
64
  }
70
65
  end
71
66
 
72
- def search
73
- if params[:resource_name].present?
74
- resources = add_link_to_search_results search_resource(avo_resource)
75
- else
76
- resources = []
77
-
78
- resources_to_search_through = App.get_resources.select { |r| r.search.present? }
79
- resources_to_search_through.each do |resource_model|
80
- found_resources = add_link_to_search_results search_resource(resource_model)
81
- resources.push({
82
- label: resource_model.name,
83
- resources: found_resources
84
- })
85
- end
86
- end
87
-
88
- render json: {
89
- resources: resources
90
- }
91
- end
92
-
93
67
  def show
94
68
  render json: {
95
- resource: Avo::Resources::Resource.hydrate_resource(resource, avo_resource, @view || :show),
69
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: @view || :show, user: current_user),
96
70
  }
97
71
  end
98
72
 
@@ -120,7 +94,7 @@ module Avo
120
94
 
121
95
  render json: {
122
96
  success: true,
123
- resource: Avo::Resources::Resource.hydrate_resource(resource, avo_resource, :show),
97
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :show, user: current_user),
124
98
  message: 'Resource updated',
125
99
  }
126
100
  end
@@ -143,16 +117,14 @@ module Avo
143
117
 
144
118
  render json: {
145
119
  success: true,
146
- resource: Avo::Resources::Resource.hydrate_resource(resource, avo_resource, :create),
120
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource, resource: avo_resource, view: :create, user: current_user),
147
121
  message: 'Resource created',
148
122
  }
149
123
  end
150
124
 
151
- def fields
152
- resource = resource_model.new
153
-
125
+ def new
154
126
  render json: {
155
- resource: Avo::Resources::Resource.hydrate_resource(resource, avo_resource, :create),
127
+ resource: Avo::Resources::Resource.hydrate_resource(model: resource_model.new, resource: avo_resource, view: :create, user: current_user),
156
128
  }
157
129
  end
158
130
 
@@ -164,64 +136,7 @@ module Avo
164
136
  }
165
137
  end
166
138
 
167
- def filters
168
- avo_filters = avo_resource.get_filters
169
- filters = []
170
-
171
- avo_filters.each do |filter|
172
- filters.push(filter.new.render_response)
173
- end
174
-
175
- render json: {
176
- filters: filters,
177
- }
178
- end
179
-
180
- def attach
181
- attachment_class = App.get_model_class_by_name params[:attachment_name].pluralize 1
182
- attachment_model = attachment_class.safe_constantize.find params[:attachment_id]
183
- attached = resource.send(params[:attachment_name]) << attachment_model
184
-
185
- render json: {
186
- success: true,
187
- message: "#{attachment_class} attached.",
188
- }
189
- end
190
-
191
- def detach
192
- attachment_class = App.get_model_class_by_name params[:attachment_name].pluralize 1
193
- attachment_model = attachment_class.safe_constantize.find params[:attachment_id]
194
- attached = resource.send(params[:attachment_name]).delete attachment_model
195
-
196
- render json: {
197
- success: true,
198
- message: "#{attachment_class} attached.",
199
- }
200
- end
201
-
202
- def cast_nullable(params)
203
- fields = avo_resource.get_fields
204
-
205
- nullable_fields = fields.filter { |field| field.nullable }
206
- .map { |field| [field.id, field.null_values] }
207
- .to_h
208
-
209
- params.each do |key, value|
210
- nullable = nullable_fields[key.to_sym]
211
-
212
- if nullable.present? && value.in?(nullable)
213
- params[key] = nil
214
- end
215
- end
216
-
217
- params
218
- end
219
-
220
139
  private
221
- def resource
222
- eager_load_files(resource_model).find params[:id]
223
- end
224
-
225
140
  def permitted_params
226
141
  permitted = avo_resource.get_fields.select(&:updatable).map do |field|
227
142
  # If it's a relation
@@ -250,41 +165,6 @@ module Avo
250
165
  params.require(:resource).permit(permitted_params)
251
166
  end
252
167
 
253
- def search_resource(avo_resource)
254
- avo_resource.query_search(query: params[:q], via_resource_name: params[:via_resource_name], via_resource_id: params[:via_resource_id])
255
- end
256
-
257
- def add_link_to_search_results(resources)
258
- resources.map do |model|
259
- resource = model.as_json
260
- resource[:link] = "/resources/#{model.class.to_s.singularize.underscore}/#{model.id}"
261
-
262
- resource
263
- end
264
- end
265
-
266
- def eager_load_files(query)
267
- if avo_resource.attached_file_fields.present?
268
- avo_resource.attached_file_fields.map(&:id).map do |field|
269
- query = query.send :"with_attached_#{field}"
270
- end
271
- end
272
-
273
- query
274
- end
275
-
276
- def process_file_field(field, attachment)
277
- if attachment.is_a? ActionDispatch::Http::UploadedFile
278
- # New file has been attached
279
- field.attach attachment
280
- elsif attachment.blank?
281
- # File has been deleted
282
- field.purge
283
- elsif attachment.is_a? String
284
- # Field is unchanged
285
- end
286
- end
287
-
288
168
  def update_file_fields
289
169
  # Pick and attach file fields
290
170
  attached_file_fields = avo_resource.attached_file_fields
@@ -322,7 +202,19 @@ module Avo
322
202
  end
323
203
  end
324
204
 
325
- def get_filters
205
+ def process_file_field(field, attachment)
206
+ if attachment.is_a? ActionDispatch::Http::UploadedFile
207
+ # New file has been attached
208
+ field.attach attachment
209
+ elsif attachment.blank?
210
+ # File has been deleted
211
+ field.purge
212
+ elsif attachment.is_a? String
213
+ # Field is unchanged
214
+ end
215
+ end
216
+
217
+ def applied_filters
326
218
  if params[:filters].present?
327
219
  return JSON.parse(Base64.decode64(params[:filters]))
328
220
  end
@@ -339,5 +231,37 @@ module Avo
339
231
 
340
232
  filter_defaults
341
233
  end
234
+
235
+ def cast_nullable(params)
236
+ fields = avo_resource.get_fields
237
+
238
+ nullable_fields = fields.filter { |field| field.nullable }
239
+ .map { |field| [field.id, field.null_values] }
240
+ .to_h
241
+
242
+ params.each do |key, value|
243
+ nullable = nullable_fields[key.to_sym]
244
+
245
+ if nullable.present? && value.in?(nullable)
246
+ params[key] = nil
247
+ end
248
+ end
249
+
250
+ params
251
+ end
252
+
253
+ def build_meta
254
+ {
255
+ per_page_steps: Avo.configuration.per_page_steps,
256
+ available_view_types: avo_resource.available_view_types,
257
+ default_view_type: avo_resource.default_view_type || Avo.configuration.default_view_type,
258
+ authorization: {
259
+ create: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['create']),
260
+ update: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['update']),
261
+ show: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['show']),
262
+ destroy: AuthorizationService::authorize(current_user, avo_resource.model, Avo.configuration.authorization_methods.stringify_keys['destroy']),
263
+ },
264
+ }
265
+ end
342
266
  end
343
267
  end