rails_omnibar 1.3.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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