flipper-ui 0.22.2 → 0.23.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: b17af1c2cd05d9026a457941c46e7c497460e4289bd8446b90d2f0342e53f34c
4
- data.tar.gz: 4adae31beca41aebaae69c9c3a0efe51bb024d0acc54eadf3982ddfff4a16748
3
+ metadata.gz: 3a6e8757e6a2726e4cf55323286a04caf186af13c6841a4e8b82b813b3c69f2f
4
+ data.tar.gz: 9ea49e24c52b723f7385da8c90dcae9daf96bef269f0b0e6066df1bc11065411
5
5
  SHA512:
6
- metadata.gz: a8e0d113cb89d77c9e8cd0ec83d8deb7a26f3f6e00452aa81ab6a308843dfe45e069b0e1303374ece24e4a5bd79718958e160249db9195ea22249bab2df66a5d
7
- data.tar.gz: cc5f6567f690c2bd48b762083046b19e868f4885384885667f20d808cd09f0533df5d3df5239e4a21cc649babbe231e494af984b5c1261b4ef9358b68581784a
6
+ metadata.gz: c7e435cc10e1b05c2282c022d977666479de870dc14cad3914e19e17acb6eacaf644fe37bf751f2931fb26525079a07b00b374f4815afdd10ab0e4192448ad27
7
+ data.tar.gz: a3a8fa7a1be586667573b98ee311a157f23591ee4f7bad15b1638aa25a1ec6444f75c909f90cd331d9cd17d8ba8869367755c299a9798e6eedef8583c2833dc7
data/flipper-ui.gemspec CHANGED
@@ -24,4 +24,5 @@ Gem::Specification.new do |gem|
24
24
  gem.add_dependency 'rack-protection', '>= 1.5.3', '< 2.2.0'
25
25
  gem.add_dependency 'flipper', "~> #{Flipper::VERSION}"
26
26
  gem.add_dependency 'erubi', '>= 1.0.0', '< 2.0.0'
27
+ gem.add_dependency 'sanitize', '< 7'
27
28
  end
@@ -3,6 +3,7 @@ require 'flipper/ui/configuration'
3
3
  require 'flipper/ui/error'
4
4
  require 'erubi'
5
5
  require 'json'
6
+ require 'sanitize'
6
7
 
7
8
  module Flipper
8
9
  module UI
@@ -28,20 +29,20 @@ module Flipper
28
29
 
29
30
  SOURCES = {
30
31
  bootstrap_css: {
31
- src: "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css".freeze,
32
- hash: "sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm".freeze
32
+ src: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css'.freeze,
33
+ hash: 'sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l'.freeze
33
34
  }.freeze,
34
35
  jquery_js: {
35
- src: "https://code.jquery.com/jquery-3.2.1.slim.min.js".freeze,
36
- hash: "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN".freeze
36
+ src: 'https://code.jquery.com/jquery-3.6.0.slim.js'.freeze,
37
+ hash: 'sha256-HwWONEZrpuoh951cQD1ov2HUK5zA5DwJ1DNUXaM6FsY='.freeze
37
38
  }.freeze,
38
39
  popper_js: {
39
- src: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js".freeze,
40
- hash: "sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q".freeze
40
+ src: 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js'.freeze,
41
+ hash: 'sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q'.freeze
41
42
  }.freeze,
42
43
  bootstrap_js: {
43
- src: "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js".freeze,
44
- hash: "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl".freeze
44
+ src: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js'.freeze,
45
+ hash: 'sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF'.freeze
45
46
  }.freeze
46
47
  }.freeze
47
48
  SCRIPT_SRCS = SOURCES.values_at(:jquery_js, :popper_js, :bootstrap_js).map { |s| s[:src] }
@@ -238,6 +239,7 @@ module Flipper
238
239
  def view(name)
239
240
  path = views_path.join("#{name}.erb")
240
241
  raise "Template does not exist: #{path}" unless path.exist?
242
+
241
243
  eval(Erubi::Engine.new(path.read, escape: true).src)
242
244
  end
243
245
 
@@ -9,7 +9,7 @@
9
9
  <div class="col">
10
10
  <div class="card">
11
11
  <div class="card-body">
12
- <%= @feature.description %>
12
+ <%== Sanitize.fragment(@feature.description, Sanitize::Config::BASIC) %>
13
13
  </div>
14
14
  </div>
15
15
  </div>
@@ -47,7 +47,7 @@
47
47
  <div class="text-truncate" style="font-weight: 500"><%= feature.key %></div>
48
48
  <% if Flipper::UI.configuration.show_feature_description_in_list? && Flipper::UI::Util.present?(feature.description) %>
49
49
  <div class="text-muted font-weight-light" style="line-height: 1.4; white-space: initial; padding: 8px 0">
50
- <%= feature.description %>
50
+ <%== Sanitize.fragment(feature.description, Sanitize::Config::BASIC) %>
51
51
  </div>
52
52
  <% end %>
53
53
  <div class="text-muted text-truncate">
@@ -13,7 +13,7 @@
13
13
  <div class="container mw-600">
14
14
  <%- unless Flipper::UI.configuration.banner_text.nil? -%>
15
15
  <div class="alert alert-<%= Flipper::UI.configuration.banner_class %> text-center font-weight-bold">
16
- <%= Flipper::UI.configuration.banner_text %>
16
+ <%== Sanitize.fragment(Flipper::UI.configuration.banner_text, Sanitize::Config::BASIC) %>
17
17
  </div>
18
18
  <%- end -%>
19
19
 
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = '0.22.2'.freeze
2
+ VERSION = '0.23.0'.freeze
3
3
  end
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Action do
4
2
  describe 'request methods' do
5
3
  let(:action_subclass) do
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::ActorsGate do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::AddFeature do
4
2
  describe 'GET /features/new with feature_creation_enabled set to true' do
5
3
  before do
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::BooleanGate do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::Feature do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::Features do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::File do
4
2
  describe 'GET /images/logo.png' do
5
3
  before do
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::GroupsGate do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::Home do
4
2
  describe 'GET /' do
5
3
  before do
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Configuration do
4
2
  let(:configuration) { described_class.new }
5
3
 
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI::Decorators::Feature do
4
2
  let(:source) { {} }
5
3
  let(:adapter) { Flipper::Adapters::Memory.new(source) }
@@ -1,4 +1,3 @@
1
- require 'helper'
2
1
  require 'flipper/ui/decorators/gate'
3
2
 
4
3
  RSpec.describe Flipper::UI::Decorators::Gate do
@@ -1,4 +1,3 @@
1
- require 'helper'
2
1
  require 'flipper/ui/util'
3
2
 
4
3
  RSpec.describe Flipper::UI::Util do
@@ -1,5 +1,3 @@
1
- require 'helper'
2
-
3
1
  RSpec.describe Flipper::UI do
4
2
  let(:token) do
5
3
  if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.2
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-06 00:00:00.000000000 Z
11
+ date: 2021-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -56,14 +56,14 @@ dependencies:
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: 0.22.2
59
+ version: 0.23.0
60
60
  type: :runtime
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: 0.22.2
66
+ version: 0.23.0
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: erubi
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +84,20 @@ dependencies:
84
84
  - - "<"
85
85
  - !ruby/object:Gem::Version
86
86
  version: 2.0.0
87
+ - !ruby/object:Gem::Dependency
88
+ name: sanitize
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "<"
92
+ - !ruby/object:Gem::Version
93
+ version: '7'
94
+ type: :runtime
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "<"
99
+ - !ruby/object:Gem::Version
100
+ version: '7'
87
101
  description:
88
102
  email:
89
103
  - nunemaker@gmail.com
@@ -91,11 +105,6 @@ executables: []
91
105
  extensions: []
92
106
  extra_rdoc_files: []
93
107
  files:
94
- - docs/ui/README.md
95
- - docs/ui/images/banner.png
96
- - docs/ui/images/description.png
97
- - docs/ui/images/feature.png
98
- - docs/ui/images/features.png
99
108
  - examples/ui/authorization.ru
100
109
  - examples/ui/basic.ru
101
110
  - flipper-ui.gemspec
@@ -169,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
178
  - !ruby/object:Gem::Version
170
179
  version: '0'
171
180
  requirements: []
172
- rubygems_version: 3.0.3
181
+ rubygems_version: 3.1.2
173
182
  signing_key:
174
183
  specification_version: 4
175
184
  summary: UI for the Flipper gem
data/docs/ui/README.md DELETED
@@ -1,190 +0,0 @@
1
- # Flipper::UI
2
-
3
- UI for the [Flipper](https://github.com/jnunemaker/flipper) gem.
4
-
5
- ## Screenshots
6
-
7
- Viewing list of features:
8
-
9
- ![features](images/features.png)
10
-
11
- Viewing an individual feature:
12
-
13
- ![feature](images/feature.png)
14
-
15
- ## Installation
16
-
17
- Add this line to your application's Gemfile:
18
-
19
- gem 'flipper-ui'
20
-
21
- And then execute:
22
-
23
- $ bundle
24
-
25
- Or install it yourself as:
26
-
27
- $ gem install flipper-ui
28
-
29
- ## Usage
30
-
31
- ### Rails
32
-
33
- Given that you've already initialized `Flipper` as per the [flipper](https://github.com/jnunemaker/flipper) readme, you can mount `Flipper::UI` to a route of your choice:
34
-
35
- ```ruby
36
- # config/routes.rb
37
- YourRailsApp::Application.routes.draw do
38
- mount Flipper::UI.app(Flipper) => '/flipper'
39
- end
40
- ```
41
-
42
- If you'd like to lazy load flipper, you can instead pass a block to initialize it:
43
-
44
- ```ruby
45
- # config/routes.rb
46
- YourRailsApp::Application.routes.draw do
47
- flipper_block = lambda {
48
- # some flipper initialization here, for example:
49
- adapter = Flipper::Adapters::Memory.new
50
- Flipper.new(adapter)
51
- }
52
- mount Flipper::UI.app(flipper_block) => '/flipper'
53
- end
54
- ```
55
-
56
- #### Security
57
-
58
- You almost certainly want to limit access when using Flipper::UI in production.
59
-
60
- ##### Basic Authentication via Rack
61
- The `Flipper::UI.app` method yields a builder instance prior to any predefined middleware. You can insert the `Rack::Auth::Basic` middleware, that'll prompt for a username and password when visiting the defined (i.e., `/flipper`) route.
62
-
63
- ```ruby
64
- # config/routes.rb
65
-
66
- flipper_app = Flipper::UI.app(Flipper.instance) do |builder|
67
- builder.use Rack::Auth::Basic do |username, password|
68
- # Verify credentials
69
- end
70
- end
71
- mount flipper_app, at: '/flipper'
72
- ```
73
-
74
- ##### Route Constraints
75
- It is possible to use [routes constraints](http://guides.rubyonrails.org/routing.html#request-based-constraints) to limit access to routes:
76
-
77
- ```ruby
78
- # config/routes.rb
79
-
80
- flipper_constraint = lambda { |request| request.remote_ip == '127.0.0.1' }
81
- constraints flipper_constraint do
82
- mount Flipper::UI.app(flipper) => '/flipper'
83
- end
84
- ```
85
-
86
- Another example is to use the `current_user` when using a gem-based authentication system (i.e., [warden](https://github.com/hassox/warden) or [devise](https://github.com/plataformatec/devise)):
87
-
88
- ```ruby
89
- # initializers/admin_access.rb
90
-
91
- class CanAccessFlipperUI
92
- def self.matches?(request)
93
- current_user = request.env['warden'].user
94
- current_user.present? && current_user.respond_to?(:admin?) && current_user.admin?
95
- end
96
- end
97
-
98
- # config/routes.rb
99
-
100
- constraints CanAccessFlipperUI do
101
- mount Flipper::UI.app(Flipper) => '/flipper'
102
- end
103
- ```
104
-
105
- ### Standalone
106
-
107
- Minimal example for Rack:
108
-
109
- ```ruby
110
- # config.ru
111
-
112
- require 'flipper/ui'
113
-
114
- adapter = Flipper::Adapters::Memory.new
115
- flipper = Flipper.new(adapter)
116
-
117
- run Flipper::UI.app(flipper) { |builder|
118
- builder.use Rack::Session::Cookie, secret: "something long and random"
119
- }
120
- ```
121
-
122
- The key is that you need to have sessions setup. Rails does this for you, so this step isn't necessary, but for standalone rack, you'll need it. Without sessions setup, you will receive a Runtime error like:
123
-
124
- ```
125
- RuntimeError: you need to set up a session middleware *before* Rack::Protection::RemoteToken.
126
- ```
127
-
128
- See [examples/ui/basic.ru](https://github.com/jnunemaker/flipper/blob/master/examples/ui/basic.ru) for a more full example
129
-
130
- ### Configuration
131
-
132
- Flipper UI can be customized via `configure`, which yields a configuration instance.
133
-
134
- #### Description
135
-
136
- We can associate a `description` for each `feature` by providing a descriptions source:
137
-
138
- ```ruby
139
- Flipper::UI.configure do |config|
140
- config.descriptions_source = ->(keys) do
141
- # descriptions loaded from YAML file or database (postgres, mysql, etc)
142
- # return has to be hash of {String key => String description}
143
- end
144
-
145
- # Defaults to false. Set to true to show feature descriptions on the list
146
- # page as well as the view page.
147
- # config.show_feature_description_in_list = true
148
- end
149
- ```
150
-
151
- Descriptions show up in the UI like so:
152
-
153
- ![description](images/description.png)
154
-
155
- #### Banner
156
-
157
- Flipper UI can display a banner across the top of the page. The `banner_text` and `banner_class` can be configured by using the `Flipper::UI.configure` block as seen below.
158
-
159
- ```ruby
160
- Flipper::UI.configure do |config|
161
- config.banner_text = 'Production Environment'
162
- config.banner_class = 'danger'
163
- end
164
- ```
165
-
166
- By default the `environment` is set to an empty string so no banner will show. If you wish to customize the look of the banner, you can set `banner_class` to one of the bootstrap color classes: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, or `dark`. The default `banner_class` is `danger`.
167
-
168
- The above configuration results in:
169
-
170
- ![banner](images/banner.png)
171
-
172
- #### Fun mode
173
-
174
- By default, Flipper UI displays a videoclip when there are no flags. The `fun` mode can be configured by using the `Flipper::UI.configure` block as seen below.
175
-
176
- ```ruby
177
- Flipper::UI.configure do |config|
178
- config.fun = false
179
- end
180
- ```
181
-
182
- ## Contributing
183
-
184
- 1. Fork it
185
- 2. Create your feature branch (`git checkout -b my-new-feature`)
186
- 3. **Fire up the app** (`script/server`)
187
- 4. Run the tests `bundle exec rake`
188
- 5. Commit your changes (`git commit -am 'Added some feature'`)
189
- 6. Push to the branch (`git push origin my-new-feature`)
190
- 7. Create new Pull Request
Binary file
Binary file
Binary file
Binary file