rails_omnibar 1.3.2 → 1.5.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: '0139344a382442752e03ba6b2ef807dd0850891de4ddf01db635e5b7d17861d9'
4
- data.tar.gz: 38a8b18c48acf9ccde4eac6561815b52c78985ef17f06b80e93eb61af9f6f5c8
3
+ metadata.gz: 21f584d48006f4dd826813762553d863b7519ff09687c31be568479088314255
4
+ data.tar.gz: f8341d39b57397f66f334e417fe2920453494eeec017bf304426e4929e7b4488
5
5
  SHA512:
6
- metadata.gz: b5ae396c06d0b9fab16f4f28cbe9a12079e57bebda679be68f9d92607528b6f634fdf21c4f4cf299f6fe8174ff1fe5933c6c9d1c1df7b80b8c83675ab74f45e1
7
- data.tar.gz: 2ba107efc3bae38d13aece39d8d1060305c46de4a2252df5ae41f1b26643972f5efd3e9d0c5206fa147ebf72b08946388c1c8ccc93cc098e6d6e8dbf6bca416b
6
+ metadata.gz: aa03433d73eb577524f195e3ce9491c2e832c5ccd8995df017fef33b1652d98ca56e76bab0586c3286b3e8c764d0cbbc228bc004b943b83d93a90b5a75cc3c0b
7
+ data.tar.gz: 8c3192eafac7ea537f5c8924943eb742002ef4bf4bf2388986468ad595c43324c4bbf1b042a80f58cf8cc7f67981ee123485dcf150c7f740788a46750a4649ac
@@ -8,7 +8,7 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- ruby: [ '2.7', '3.0', 'ruby-head' ]
11
+ ruby: [ '3.0', 'ruby-head' ]
12
12
 
13
13
  steps:
14
14
  - uses: actions/checkout@v3
data/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.5.0] - 2024-01-25
8
+
9
+ ### Added
10
+
11
+ - `RailsOmnibar::add_webadmin_items`
12
+
13
+ ## [1.4.0] - 2023-01-31
14
+
15
+ ### Added
16
+
17
+ - `RailsOmnibar::auth=` for fine-grained authorization
18
+ - `RailsOmnibar::html_url` for rendering in SPAs
19
+
20
+ ### Fixed
21
+
22
+ - double execution of commands / queries
23
+
7
24
  ## [1.3.2] - 2023-01-27
8
25
 
9
26
  ### Fixed
data/Gemfile CHANGED
@@ -2,3 +2,17 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in rails_omnibar.gemspec
4
4
  gemspec
5
+
6
+ group :development, :test do
7
+ gem 'activeadmin', '~> 3.0' # to test activeadmin integration
8
+ gem 'capybara', '~> 3.0'
9
+ gem 'csv' # needed for activeadmin, standalone on Ruby >= 3.4
10
+ gem 'devise', '~> 4.8' # to test auth feature
11
+ gem 'factory_bot_rails', '~> 6.0'
12
+ gem 'puma', '~> 6.0'
13
+ gem 'rake', '~> 13.0'
14
+ gem 'rspec-rails', '~> 5.0'
15
+ gem 'sqlite3', '>= 1.3.6'
16
+ gem 'sprockets-rails', '~> 3.4' # for activeadmin
17
+ gem 'webdrivers', '~> 5.0'
18
+ end
data/README.md CHANGED
@@ -15,17 +15,11 @@ Add `rails_omnibar` to your bundle and add the following line to your `config/ro
15
15
  mount RailsOmnibar::Engine => '/rails_omnibar'
16
16
  ```
17
17
 
18
- You can pick any path.
18
+ You can pick any path. See [Authorization](#authorization) for limiting access to the engine.
19
19
 
20
- To limit access, do something like this:
20
+ ## Configuration
21
21
 
22
- ```ruby
23
- authenticate :user, ->(user){ user.superadmin? } do
24
- mount RailsOmnibar::Engine => '/rails_omnibar'
25
- end
26
- ```
27
-
28
- ### Configuration
22
+ ### Basic Usage
29
23
 
30
24
  ```ruby
31
25
  # app/lib/omnibar.rb
@@ -52,6 +46,7 @@ Omnibar = RailsOmnibar.configure do |c|
52
46
  next unless name = route.name[/^backoffice_(.+)/, 1]
53
47
 
54
48
  # items can have icons
49
+ # arrows, cloud, cog, dev, document, home, question, search, sparkle, user, wallet, x
55
50
  c.add_item(title: name.humanize, url: route.format({}), icon: :cog)
56
51
  end
57
52
 
@@ -97,61 +92,130 @@ Render it somewhere. E.g. `app/views/layouts/application.html.erb`:
97
92
  <%= Omnibar.render %>
98
93
  ```
99
94
 
95
+ If you have a fully decoupled frontend, use `Omnibar.html_url` instead, fetch the omnibar HTML from there, and inject it.
96
+
97
+ ### Authorization
98
+
99
+ You can limit access to commands (e.g. search commands). This will not limit access to plain items.
100
+
101
+ #### Option 1: globally limit engine access
102
+
103
+ ```ruby
104
+ authenticate :user, ->(user){ user.superadmin? } do
105
+ mount RailsOmnibar::Engine => '/rails_omnibar'
106
+ end
107
+ ```
108
+
109
+ #### Option 2: use `RailsOmnibar::auth=`
110
+
111
+ This is useful for fine-grained authorization, e.g. if there is more than one omnibar or multiple permission levels.
112
+
113
+ ```ruby
114
+ # the auth proc is executed in the controller context by default,
115
+ # but can also take the controller and omnibar as arguments
116
+ MyOmnibar.auth = ->{ user_signed_in? }
117
+ MyOmnibar.auth = ->(controller, omnibar:) do
118
+ controller.user_signed_in? && omnibar.is_a?(NormalUserOmnibar)
119
+ end
120
+ ```
121
+
100
122
  ### Using multiple different omnibars
101
123
 
102
124
  ```ruby
103
- UserOmnibar = Class.new(RailsOmnibar).configure { ... }
104
- AdminOmnibar = Class.new(RailsOmnibar).configure { ... }
125
+ BaseOmnibar = Class.new(RailsOmnibar)
126
+ BaseOmnibar.configure do |c|
127
+ c.add_item(
128
+ title: 'Log in',
129
+ url: Rails.application.routes.url_helpers.log_in_url
130
+ )
131
+ end
132
+
133
+ UserOmnibar = Class.new(RailsOmnibar)
134
+ UserOmnibar.configure do |c|
135
+ c.auth = ->{ user_signed_in? }
136
+ c.add_item(
137
+ title: 'Log out',
138
+ url: Rails.application.routes.url_helpers.log_out_url
139
+ )
140
+ end
141
+ ```
142
+
143
+ Then, in some layout:
105
144
 
106
- UserOmnibar.render
107
- AdminOmnibar.render
145
+ ```erb
146
+ <%= (user_signed_in? ? UserOmnibar : BaseOmnibar).render %>
108
147
  ```
109
148
 
110
149
  ### Other options and usage patterns
111
150
 
151
+ #### Adding multiple items at once
152
+
112
153
  ```ruby
113
- # Add multiple items
114
154
  MyOmnibar.add_items(
115
155
  *MyRecord.all.map { |rec| { title: rec.title, url: url_for(rec) } }
116
156
  )
157
+ ```
158
+
159
+ #### Adding all ActiveAdmin or RailsAdmin index routes as searchable items
160
+
161
+ Simply call `::add_webadmin_items` and use the `modal` mode.
117
162
 
118
- # Add ActiveAdmin index routes as searchable items
119
- Admin::UsersController # trigger autoloading (use your own AA namespace)
120
- ActiveAdmin.application.namespaces.first.resources.each do |res|
121
- index = res.route_collection_path rescue next
122
- title = res.menu_item&.label.presence || next
123
- MyOmnibar.add_item(title: title, url: index)
163
+ ```ruby
164
+ MyOmnibar.configure do |c|
165
+ c.add_webadmin_items
166
+ c.modal = true
124
167
  end
168
+ ```
125
169
 
126
- # Render in ActiveAdmin (`MyOmnibar.modal = true` recommended)
170
+ ##### To render in ActiveAdmin
171
+
172
+ ```ruby
127
173
  module AddOmnibar
128
174
  def build_page(...)
129
175
  within(super) { text_node(MyOmnibar.render) }
130
176
  end
131
177
  end
132
178
  ActiveAdmin::Views::Pages::Base.prepend(AddOmnibar)
179
+ ```
180
+
181
+ ##### To render in RailsAdmin
182
+
183
+ Add `MyOmnibar.render` to `app/views/layouts/rails_admin/application.*`.
133
184
 
134
- # Add all index routes as searchable items
185
+ #### Adding all index routes as searchable items
186
+
187
+ ```ruby
135
188
  Rails.application.routes.routes.each do |route|
136
189
  next unless route.defaults.values_at(:action, :format) == ['index', nil]
137
190
  MyOmnibar.add_item(title: route.name.humanize, url: route.format({}))
138
191
  end
192
+ ```
193
+
194
+ #### Custom record lookup and rendering
139
195
 
140
- # Custom record lookup and rendering
196
+ ```ruby
141
197
  MyOmnibar.add_record_search(
142
198
  pattern: /^U(\d+)/,
143
199
  example: 'U123',
144
200
  model: User,
145
- finder: ->(id) { User.find_by(admin: true, id: id) },
146
- itemizer: ->(user) { { title: "Admin #{user.name}", url: admin_url(user), icon: :user } }
201
+ finder: ->(id) { User.find_by(admin: true, id: id) },
202
+ itemizer: ->(user) do
203
+ { title: "Admin #{user.name}", url: admin_url(user), icon: :user }
204
+ end
147
205
  )
206
+ ```
148
207
 
149
- # Custom search, plus mapping to multiple results
208
+ #### Custom search, plus mapping to multiple results
209
+
210
+ ```ruby
150
211
  MyOmnibar.add_search(
151
212
  description: 'Google',
152
213
  pattern: /^g (.+)/,
153
214
  example: 'g kittens',
154
- finder: ->(value) { GoogleSearch.fetch(value) },
215
+ # omnibar: and controller: keyword args are provided to command procs
216
+ finder: ->(value, omnibar:) do
217
+ Google.search(value, limit: omnibar.max_results)
218
+ end,
155
219
  itemizer: ->(res) do
156
220
  [
157
221
  { title: res.title, url: res.url },
@@ -159,14 +223,21 @@ MyOmnibar.add_search(
159
223
  ]
160
224
  end,
161
225
  )
226
+ ```
227
+
228
+ #### Completely custom command
162
229
 
163
- # Completely custom command
230
+ ```ruby
164
231
  MyOmnibar.add_command(
165
232
  description: 'Get count of a DB table',
166
233
  pattern: /COUNT (.+)/i,
167
234
  example: 'COUNT users',
168
- resolver: ->(value, _omnibar) do
169
- { title: value.classify.constantize.count.to_s }
235
+ resolver: ->(value, controller:) do
236
+ if controller.current_user.client?
237
+ { title: (value.classify.constantize.count * 2).to_s }
238
+ else
239
+ { title: value.classify.constantize.count.to_s }
240
+ end
170
241
  rescue => e
171
242
  { title: e.message }
172
243
  end,
data/Rakefile CHANGED
@@ -16,14 +16,12 @@ task :generate_spec_app do
16
16
  sh 'rm -rf spec/dummy'
17
17
  sh *%w[
18
18
  rails new spec/dummy
19
- --template=spec/app_template.rb
19
+ --template=spec/templates/app_template.rb
20
20
  --skip-action-cable
21
21
  --skip-action-mailbox
22
- --skip-action-mailer
23
22
  --skip-action-text
24
23
  --skip-active-job
25
24
  --skip-active-storage
26
- --skip-asset-pipeline
27
25
  --skip-bootsnap
28
26
  --skip-bundle
29
27
  --skip-git
@@ -33,7 +31,6 @@ task :generate_spec_app do
33
31
  --skip-keeps
34
32
  --skip-listen
35
33
  --skip-spring
36
- --skip-sprockets
37
34
  --skip-system-test
38
35
  --skip-test
39
36
  --skip-turbolinks
@@ -1,2 +1,5 @@
1
1
  class RailsOmnibar::BaseController < ActionController::API
2
+ def omnibar
3
+ @omnibar ||= params.fetch('omnibar_class').constantize
4
+ end
2
5
  end
@@ -0,0 +1,5 @@
1
+ class RailsOmnibar::HtmlController < RailsOmnibar::BaseController
2
+ def show
3
+ render html: omnibar.render
4
+ end
5
+ end
@@ -1,7 +1,7 @@
1
1
  class RailsOmnibar::QueriesController < RailsOmnibar::BaseController
2
2
  def show
3
- omnibar = params['omnibar_class'].constantize
4
- res = omnibar.handle(params[:q])
5
- render json: omnibar.handle(params[:q])
3
+ return head :forbidden unless omnibar.authorize(self)
4
+
5
+ render json: omnibar.handle(params[:q], self)
6
6
  end
7
7
  end
data/config/routes.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  RailsOmnibar::Engine.routes.draw do
2
2
  resource :js, only: :show, defaults: { format: :js }
3
+ resource :html, only: :show
3
4
  resource :query, only: :show
4
5
  end