tiny_admin 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71d42ca63e3a410de95780d584cdfb61dd94feb95b503f5f55379efabec9477e
4
- data.tar.gz: 96c4b375cb65327635199296d11f54335e6c5266dacce39a7316e0eb2844046c
3
+ metadata.gz: 748ac60bbfef74485795f95728033866510e728572d391b2a3f381fde88434f6
4
+ data.tar.gz: 59c0a78183a960e28cb1670d4484be18e368ec48cf622bd8034087192385b7dd
5
5
  SHA512:
6
- metadata.gz: d377537524247253a871e016d3d5e688e47ab07d40c6d33814c5dfc0be761e734d3de3c8c23d3e3981d3f949ce15d230312b4c71fb2d7d6f33aeb45cc352223f
7
- data.tar.gz: 4ddb16c2f1fbfefced95deb426cf369d28201866f800eee1f4b14895bd938233f6f67bf51d784a7edf340b48d7a75230a86b679db9ec71c07f18b726c23971a4
6
+ metadata.gz: 8ba6531f80fbaab695c59a309e7249f071a1f4491fd7800edb2562571beb352d3f4faff625876cf6dc87e9cdcbf8d12d002f343076446c8ad82653c8d488ce78
7
+ data.tar.gz: 162637202396ce2106c9ad9c2117a22becc3ad99c3a4e0f72f850624089cb110e2eda4ae39aa66e6c4897bb6c5ad0789003d10711c94ba74f28616afa3e5e82a
data/README.md CHANGED
@@ -19,7 +19,7 @@ Please ⭐ if you like it.
19
19
 
20
20
  ## Install
21
21
 
22
- - Add to your Gemfile: `gem 'tiny_admin', '~> 0.8'`
22
+ - Add to your Gemfile: `gem 'tiny_admin', '~> 0.10'`
23
23
  - Mount the app in a route (check some examples with: Hanami, Rails, Roda and standalone in [extra](extra))
24
24
  + in Rails, update _config/routes.rb_: `mount TinyAdmin::Router => '/admin'`
25
25
  - Configure the dashboard using `TinyAdmin.configure` and/or `TinyAdmin.configure_from_file` with a YAML config file (see [configuration](#configuration) below):
@@ -43,6 +43,12 @@ Plugins available:
43
43
 
44
44
  - **NoAuth**: no authentication.
45
45
 
46
+ ### Authorization
47
+
48
+ Plugins available:
49
+
50
+ - **Authorization**: base class to provide an authorization per action, the host application should inherit from it and override the class method `allowed?`.
51
+
46
52
  ### Repository
47
53
 
48
54
  Plugin available:
@@ -134,6 +140,10 @@ authentication:
134
140
  password: 'f1891cea80fc05e433c943254c6bdabc159577a02a7395dfebbfbc4f7661d4af56f2d372131a45936de40160007368a56ef216a30cb202c66d3145fd24380906'
135
141
  ```
136
142
 
143
+ `authorization_class` (String): a plugin class to use;
144
+
145
+ > 📚 [Wiki Authentication page](https://github.com/blocknotes/tiny_admin/wiki/Authorization) available
146
+
137
147
  `sections` (Array of hashes): define the admin sections, properties:
138
148
 
139
149
  - `slug` (String): section reference identifier;
@@ -218,6 +228,8 @@ model: Post
218
228
 
219
229
  #### Resource index options
220
230
 
231
+ > 📚 [Wiki Resource index page](https://github.com/blocknotes/tiny_admin/wiki/Resource-index) available
232
+
221
233
  The Index hash supports the following options:
222
234
 
223
235
  - `attributes` (Array): fields to expose in the resource list page;
@@ -257,6 +269,8 @@ Example:
257
269
 
258
270
  #### Resource show options
259
271
 
272
+ > 📚 [Wiki Resource show page](https://github.com/blocknotes/tiny_admin/wiki/Resource-show) available
273
+
260
274
  The Show hash supports the following options:
261
275
 
262
276
  - `attributes` (Array): fields to expose in the resource details page.
@@ -58,12 +58,13 @@ module TinyAdmin
58
58
  end
59
59
  end
60
60
 
61
- def setup_pagination(page, pagination_component_class, total_count:)
61
+ def setup_pagination(page, pagination_component, total_count:)
62
62
  @pages = (total_count / pagination.to_f).ceil
63
- return if pages <= 1 || !pagination_component_class
63
+ return if pages <= 1 || !pagination_component
64
64
 
65
- page.pagination_component = pagination_component_class.new
66
- page.pagination_component.update_attributes(current: current_page, pages: pages, query_string: query_string)
65
+ attributes = { current: current_page, pages: pages, query_string: query_string, total_count: total_count }
66
+ page.pagination_component = pagination_component.new
67
+ page.pagination_component.update_attributes(attributes)
67
68
  end
68
69
  end
69
70
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TinyAdmin
4
+ module Plugins
5
+ class Authorization
6
+ class << self
7
+ def allowed?(_user, _action, _param = nil)
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -53,36 +53,45 @@ module TinyAdmin
53
53
  render(inline: page.call)
54
54
  end
55
55
 
56
- def root_route(router)
57
- if TinyAdmin.settings.root[:redirect]
58
- router.redirect route_for(TinyAdmin.settings.root[:redirect])
56
+ def root_route(req)
57
+ if authorization.allowed?(current_user, :root)
58
+ if TinyAdmin.settings.root[:redirect]
59
+ req.redirect route_for(TinyAdmin.settings.root[:redirect])
60
+ else
61
+ page_class = to_class(TinyAdmin.settings.root[:page])
62
+ attributes = TinyAdmin.settings.root.slice(:content, :title, :widgets)
63
+ render_page prepare_page(page_class, attributes: attributes, params: request.params)
64
+ end
59
65
  else
60
- page_class = to_class(TinyAdmin.settings.root[:page])
61
- render_page prepare_page(page_class, attributes: TinyAdmin.settings.root.slice(:content, :title, :widgets))
66
+ render_page prepare_page(TinyAdmin.settings.page_not_allowed)
62
67
  end
63
68
  end
64
69
 
65
- def setup_page_route(router, slug, page_data)
66
- router.get slug do
67
- attributes = page_data.slice(:content, :title, :widgets)
68
- render_page prepare_page(page_data[:class], slug: slug, attributes: attributes)
70
+ def setup_page_route(req, slug, page_data)
71
+ req.get slug do
72
+ if authorization.allowed?(current_user, :page, slug)
73
+ attributes = page_data.slice(:content, :title, :widgets)
74
+ render_page prepare_page(page_data[:class], slug: slug, attributes: attributes, params: request.params)
75
+ else
76
+ render_page prepare_page(TinyAdmin.settings.page_not_allowed)
77
+ end
69
78
  end
70
79
  end
71
80
 
72
- def setup_resource_routes(router, slug, options:)
73
- router.on slug do
74
- setup_collection_routes(router, slug, options: options)
75
- setup_member_routes(router, slug, options: options)
81
+ def setup_resource_routes(req, slug, options:)
82
+ req.on slug do
83
+ setup_collection_routes(req, slug, options: options)
84
+ setup_member_routes(req, slug, options: options)
76
85
  end
77
86
  end
78
87
 
79
- def setup_collection_routes(router, slug, options:)
88
+ def setup_collection_routes(req, slug, options:)
80
89
  repository = options[:repository].new(options[:model])
81
90
  action_options = options[:index] || {}
82
91
 
83
92
  # Custom actions
84
93
  custom_actions = setup_custom_actions(
85
- router,
94
+ req,
86
95
  options[:collection_actions],
87
96
  options: action_options,
88
97
  repository: repository,
@@ -91,28 +100,32 @@ module TinyAdmin
91
100
 
92
101
  # Index
93
102
  if options[:only].include?(:index) || options[:only].include?('index')
94
- router.is do
95
- context = Context.new(
96
- actions: custom_actions,
97
- repository: repository,
98
- request: request,
99
- router: router,
100
- slug: slug
101
- )
102
- index_action = TinyAdmin::Actions::Index.new
103
- render_page index_action.call(app: self, context: context, options: action_options)
103
+ req.is do
104
+ if authorization.allowed?(current_user, :resource_index, slug)
105
+ context = Context.new(
106
+ actions: custom_actions,
107
+ repository: repository,
108
+ request: request,
109
+ router: req,
110
+ slug: slug
111
+ )
112
+ index_action = TinyAdmin::Actions::Index.new
113
+ render_page index_action.call(app: self, context: context, options: action_options)
114
+ else
115
+ render_page prepare_page(TinyAdmin.settings.page_not_allowed)
116
+ end
104
117
  end
105
118
  end
106
119
  end
107
120
 
108
- def setup_member_routes(router, slug, options:)
121
+ def setup_member_routes(req, slug, options:)
109
122
  repository = options[:repository].new(options[:model])
110
123
  action_options = (options[:show] || {}).merge(record_not_found_page: TinyAdmin.settings.record_not_found)
111
124
 
112
- router.on String do |reference|
125
+ req.on String do |reference|
113
126
  # Custom actions
114
127
  custom_actions = setup_custom_actions(
115
- router,
128
+ req,
116
129
  options[:member_actions],
117
130
  options: action_options,
118
131
  repository: repository,
@@ -122,42 +135,54 @@ module TinyAdmin
122
135
 
123
136
  # Show
124
137
  if options[:only].include?(:show) || options[:only].include?('show')
125
- router.is do
126
- context = Context.new(
127
- actions: custom_actions,
128
- reference: reference,
129
- repository: repository,
130
- request: request,
131
- router: router,
132
- slug: slug
133
- )
134
- show_action = TinyAdmin::Actions::Show.new
135
- render_page show_action.call(app: self, context: context, options: action_options)
138
+ req.is do
139
+ if authorization.allowed?(current_user, :resource_show, slug)
140
+ context = Context.new(
141
+ actions: custom_actions,
142
+ reference: reference,
143
+ repository: repository,
144
+ request: request,
145
+ router: req,
146
+ slug: slug
147
+ )
148
+ show_action = TinyAdmin::Actions::Show.new
149
+ render_page show_action.call(app: self, context: context, options: action_options)
150
+ else
151
+ render_page prepare_page(TinyAdmin.settings.page_not_allowed)
152
+ end
136
153
  end
137
154
  end
138
155
  end
139
156
  end
140
157
 
141
- def setup_custom_actions(router, custom_actions, options:, repository:, slug:, reference: nil)
158
+ def setup_custom_actions(req, custom_actions = nil, options:, repository:, slug:, reference: nil)
142
159
  (custom_actions || []).each_with_object({}) do |custom_action, result|
143
160
  action_slug, action = custom_action.first
144
161
  action_class = to_class(action)
145
162
 
146
- router.get action_slug.to_s do
147
- context = Context.new(
148
- actions: {},
149
- reference: reference,
150
- repository: repository,
151
- request: request,
152
- router: router,
153
- slug: slug
154
- )
155
- custom_action = action_class.new
156
- render_page custom_action.call(app: self, context: context, options: options)
163
+ req.get action_slug.to_s do
164
+ if authorization.allowed?(current_user, :custom_action, action_slug.to_s)
165
+ context = Context.new(
166
+ actions: {},
167
+ reference: reference,
168
+ repository: repository,
169
+ request: request,
170
+ router: req,
171
+ slug: slug
172
+ )
173
+ custom_action = action_class.new
174
+ render_page custom_action.call(app: self, context: context, options: options)
175
+ else
176
+ render_page prepare_page(TinyAdmin.settings.page_not_allowed)
177
+ end
157
178
  end
158
179
 
159
180
  result[action_slug.to_s] = action_class
160
181
  end
161
182
  end
183
+
184
+ def authorization
185
+ TinyAdmin.settings.authorization_class
186
+ end
162
187
  end
163
188
  end
@@ -7,6 +7,7 @@ module TinyAdmin
7
7
  DEFAULTS = {
8
8
  %i[authentication plugin] => Plugins::NoAuth,
9
9
  %i[authentication login] => Views::Pages::SimpleAuthLogin,
10
+ %i[authorization_class] => Plugins::Authorization,
10
11
  %i[components field_value] => Views::Components::FieldValue,
11
12
  %i[components flash] => Views::Components::Flash,
12
13
  %i[components head] => Views::Components::Head,
@@ -14,6 +15,7 @@ module TinyAdmin
14
15
  %i[components pagination] => Views::Components::Pagination,
15
16
  %i[content_page] => Views::Pages::Content,
16
17
  %i[helper_class] => Support,
18
+ %i[page_not_allowed] => Views::Pages::PageNotAllowed,
17
19
  %i[page_not_found] => Views::Pages::PageNotFound,
18
20
  %i[record_not_found] => Views::Pages::RecordNotFound,
19
21
  %i[repository] => Plugins::ActiveRecordRepository,
@@ -25,10 +27,12 @@ module TinyAdmin
25
27
 
26
28
  OPTIONS = %i[
27
29
  authentication
30
+ authorization_class
28
31
  components
29
32
  content_page
30
33
  extra_styles
31
34
  helper_class
35
+ page_not_allowed
32
36
  page_not_found
33
37
  record_not_found
34
38
  repository
@@ -14,7 +14,7 @@ module TinyAdmin
14
14
  list.join('&')
15
15
  end
16
16
 
17
- def prepare_page(page_class, slug: nil, attributes: nil, options: nil)
17
+ def prepare_page(page_class, slug: nil, attributes: nil, options: nil, params: nil)
18
18
  page_class.new.tap do |page|
19
19
  page.options = options
20
20
  page.head_component = TinyAdmin.settings.components[:head]&.new
@@ -27,9 +27,11 @@ module TinyAdmin
27
27
  items: options&.include?(:no_menu) ? [] : TinyAdmin.settings.store&.navbar
28
28
  )
29
29
  attrs = attributes || {}
30
+ attrs[:params] = params if params
30
31
  attrs[:widgets] = attrs[:widgets].map { to_class(_1) } if attrs[:widgets]
31
32
  page.update_attributes(attrs) unless attrs.empty?
32
33
  yield(page) if block_given?
34
+ page.setup if page.respond_to?(:setup)
33
35
  end
34
36
  end
35
37
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TinyAdmin
4
- VERSION = '0.8.0'
4
+ VERSION = '0.10.0'
5
5
  end
@@ -4,7 +4,14 @@ module TinyAdmin
4
4
  module Views
5
5
  module Actions
6
6
  class Index < DefaultLayout
7
- attr_accessor :actions, :fields, :filters, :links, :pagination_component, :prepare_record, :records, :slug
7
+ attr_accessor :actions,
8
+ :fields,
9
+ :filters,
10
+ :links,
11
+ :pagination_component,
12
+ :prepare_record,
13
+ :records,
14
+ :slug
8
15
 
9
16
  def template
10
17
  super do
@@ -28,6 +35,8 @@ module TinyAdmin
28
35
 
29
36
  table_body
30
37
  }
38
+
39
+ render pagination_component if pagination_component
31
40
  }
32
41
 
33
42
  if filters&.any?
@@ -39,8 +48,6 @@ module TinyAdmin
39
48
  end
40
49
  }
41
50
 
42
- render pagination_component if pagination_component
43
-
44
51
  render TinyAdmin::Views::Components::Widgets.new(widgets)
45
52
  }
46
53
  end
@@ -4,7 +4,12 @@ module TinyAdmin
4
4
  module Views
5
5
  module Actions
6
6
  class Show < DefaultLayout
7
- attr_accessor :actions, :fields, :prepare_record, :record, :reference, :slug
7
+ attr_accessor :actions,
8
+ :fields,
9
+ :prepare_record,
10
+ :record,
11
+ :reference,
12
+ :slug
8
13
 
9
14
  def template
10
15
  super do
@@ -5,7 +5,7 @@ module TinyAdmin
5
5
  class BasicLayout < Phlex::HTML
6
6
  include Utils
7
7
 
8
- attr_accessor :content, :widgets
8
+ attr_accessor :content, :params, :widgets
9
9
 
10
10
  def label_for(value, options: [])
11
11
  TinyAdmin.settings.helper_class.label_for(value, options: options)
@@ -4,23 +4,31 @@ module TinyAdmin
4
4
  module Views
5
5
  module Components
6
6
  class Pagination < BasicComponent
7
- attr_accessor :current, :pages, :query_string
7
+ attr_accessor :current, :pages, :query_string, :total_count
8
8
 
9
9
  def template
10
- div(class: 'pagination-div') {
11
- nav('aria-label' => 'Pagination') {
12
- ul(class: 'pagination justify-content-center') {
13
- if pages <= 10
14
- pages_range(1..pages)
15
- elsif current <= 4 || current >= pages - 3
16
- pages_range(1..(current <= 4 ? current + 2 : 4), with_dots: true)
17
- pages_range((current > pages - 4 ? current - 2 : pages - 2)..pages)
18
- else
19
- pages_range(1..1, with_dots: true)
20
- pages_range(current - 2..current + 2, with_dots: true)
21
- pages_range(pages..pages)
22
- end
10
+ div(class: 'container') {
11
+ div(class: 'row') {
12
+ div(class: 'col total-count') {
13
+ "#{total_count} items"
23
14
  }
15
+ div(class: 'col col-6 text-center pagination-div') {
16
+ nav(class: 'd-inline-block', 'aria-label': 'Pagination') {
17
+ ul(class: 'pagination') {
18
+ if pages <= 10
19
+ pages_range(1..pages)
20
+ elsif current <= 4 || current >= pages - 3
21
+ pages_range(1..(current <= 4 ? current + 2 : 4), with_dots: true)
22
+ pages_range((current > pages - 4 ? current - 2 : pages - 2)..pages)
23
+ else
24
+ pages_range(1..1, with_dots: true)
25
+ pages_range(current - 2..current + 2, with_dots: true)
26
+ pages_range(pages..pages)
27
+ end
28
+ }
29
+ }
30
+ }
31
+ div(class: 'col')
24
32
  }
25
33
  }
26
34
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TinyAdmin
4
+ module Views
5
+ module Pages
6
+ class PageNotAllowed < DefaultLayout
7
+ def template
8
+ super do
9
+ div(class: 'page_not_allowed') {
10
+ h1(class: 'title') { title }
11
+ }
12
+ end
13
+ end
14
+
15
+ def title
16
+ 'Page not allowed'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiny_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-10 00:00:00.000000000 Z
11
+ date: 2023-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex
@@ -83,6 +83,7 @@ files:
83
83
  - lib/tiny_admin/context.rb
84
84
  - lib/tiny_admin/field.rb
85
85
  - lib/tiny_admin/plugins/active_record_repository.rb
86
+ - lib/tiny_admin/plugins/authorization.rb
86
87
  - lib/tiny_admin/plugins/base_repository.rb
87
88
  - lib/tiny_admin/plugins/no_auth.rb
88
89
  - lib/tiny_admin/plugins/simple_auth.rb
@@ -107,6 +108,7 @@ files:
107
108
  - lib/tiny_admin/views/components/widgets.rb
108
109
  - lib/tiny_admin/views/default_layout.rb
109
110
  - lib/tiny_admin/views/pages/content.rb
111
+ - lib/tiny_admin/views/pages/page_not_allowed.rb
110
112
  - lib/tiny_admin/views/pages/page_not_found.rb
111
113
  - lib/tiny_admin/views/pages/record_not_found.rb
112
114
  - lib/tiny_admin/views/pages/root.rb
@@ -134,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
136
  - !ruby/object:Gem::Version
135
137
  version: '0'
136
138
  requirements: []
137
- rubygems_version: 3.3.26
139
+ rubygems_version: 3.4.10
138
140
  signing_key:
139
141
  specification_version: 4
140
142
  summary: Tiny Admin