the_role 1.5.1 → 1.6.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.
Files changed (45) hide show
  1. data/Bye_bye_CanCan_I_got_the_Role.png +0 -0
  2. data/README.md +82 -92
  3. data/app/assets/javascripts/admin_the_role.js +3 -0
  4. data/app/assets/javascripts/bootstrap-dropdown.js +100 -0
  5. data/app/assets/stylesheets/admin_the_role.css +7 -0
  6. data/app/assets/stylesheets/alerts.less +58 -0
  7. data/app/assets/stylesheets/button-groups.less +191 -0
  8. data/app/assets/stylesheets/buttons.less +191 -0
  9. data/app/assets/stylesheets/custom.scss +3 -0
  10. data/app/assets/stylesheets/dropdowns.less +143 -0
  11. data/app/assets/stylesheets/forms.less +583 -0
  12. data/app/assets/stylesheets/grid.less +5 -0
  13. data/app/assets/stylesheets/headers.scss +15 -0
  14. data/app/assets/stylesheets/layouts.less +17 -0
  15. data/app/assets/stylesheets/mix.scss +41 -0
  16. data/app/assets/stylesheets/mixins.less +646 -0
  17. data/app/assets/stylesheets/reset.css +117 -0
  18. data/app/assets/stylesheets/role_set.less +136 -0
  19. data/app/assets/stylesheets/scaffolding.less +29 -0
  20. data/app/assets/stylesheets/variables.less +206 -0
  21. data/app/assets/stylesheets/wells.less +27 -0
  22. data/app/controllers/admin/role_sections_controller.rb +40 -17
  23. data/app/controllers/admin/roles_controller.rb +8 -6
  24. data/app/views/admin/roles/_role.html.haml +53 -0
  25. data/app/views/admin/roles/_sidebar.html.haml +8 -0
  26. data/app/views/admin/roles/edit.html.haml +2 -42
  27. data/app/views/admin/roles/index.haml +2 -15
  28. data/app/views/admin/roles/new.html.haml +5 -4
  29. data/app/views/layouts/the_role.html.haml +24 -0
  30. data/config/routes.rb +5 -1
  31. data/lib/the_role/engine.rb +2 -2
  32. data/lib/the_role/hash.rb +50 -14
  33. data/lib/the_role/modules/base.rb +4 -4
  34. data/lib/the_role/modules/controller_requires.rb +4 -15
  35. data/lib/the_role/modules/role_model.rb +14 -13
  36. data/lib/the_role/param_helper.rb +15 -0
  37. data/lib/the_role/version.rb +1 -1
  38. data/lib/the_role.rb +13 -11
  39. data/pic.png +0 -0
  40. data/the_role.gemspec +5 -2
  41. metadata +58 -16
  42. data/app/assets/stylesheets/the_role/form.css +0 -57
  43. data/app/assets/stylesheets/the_role/headers.css.scss +0 -15
  44. data/app/assets/stylesheets/the_role/style.css.scss +0 -75
  45. data/lib/the_role/modules/param_helper.rb +0 -7
Binary file
data/README.md CHANGED
@@ -1,10 +1,14 @@
1
- # gem 'the_role'
1
+ # gem 'the_role' (alpha v0.1)
2
2
 
3
- ## Bye bye CanCan, I got The Role!
3
+ | Bye bye CanCan, I got The Role! | Description |
4
+ |:------------- |:-------------|
5
+ | ![Bye bye CanCan, I got The Role!](https://github.com/the-teacher/the_role/raw/master/Bye_bye_CanCan_I_got_the_Role.png) | TheRole is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access. All permissions are defined in with 2-level-hash, and store in database with JSON.<br><br>TheRole - Semantic, lightweight role system with an administrative interface.<br><br>Role is a two-level hash, consisting of the **sections** and nested **rules**.<br><br>**Section** may be associated with **controller** name.<br><br>**Rule** may be associated with **action** name.<br><br>Section can have many rules.<br><br>Rule can have **true** or **false** value<br><br>**Sections** and nested **Rules** provide **ACL** (**Access Control List**)<br><br>Role **stored in the database as JSON** string.<br><br>Using of hashes, makes role system extremely easy to configure and use.<br> |
4
6
 
5
- Semantic, lightweight role system with an administrative interface
7
+ ### GUI
6
8
 
7
- ![TheSortableTree](https://github.com/the-teacher/the_role/raw/master/pic.png)
9
+ | TheRole management web interface |
10
+ |:-------------:|
11
+ |![TheRole](https://github.com/the-teacher/the_role/raw/master/pic.png)|
8
12
 
9
13
  ## What does it mean semantic?
10
14
 
@@ -14,73 +18,55 @@ Look at hash. If you can understand access rules - this role system is semantica
14
18
 
15
19
  ``` ruby
16
20
  role = {
17
- :pages => {
18
- :index => true,
19
- :show => true,
20
- :new => false,
21
- :edit => false,
22
- :update => false,
23
- :destroy => false
21
+ 'pages' => {
22
+ 'index' => true,
23
+ 'show' => true,
24
+ 'new' => false,
25
+ 'edit' => false,
26
+ 'update' => false,
27
+ 'destroy' => false
24
28
  },
25
- :articles => {
26
- :index => true,
27
- :show => true
28
- }
29
- :twitter => {
30
- :button => true,
31
- :follow => false
29
+ 'articles' => {
30
+ 'index' => true,
31
+ 'show' => true
32
+ },
33
+ 'twitter' => {
34
+ 'button' => true,
35
+ 'follow' => false
32
36
  }
33
37
  }
34
38
  ```
35
39
 
36
- ### How it works
37
-
38
- Role - is a two-level hash, consisting of the sections and rules.
39
-
40
- **Section** may be associated with the name of a **controller**.
41
-
42
- **Rule** may be associated with the name of **action** in the controller.
43
-
44
- Section may contain a set of rules.
45
-
46
- **Rule in Section** can be set to **true** and **false**, this provide **ACL** (**Access Control List**)
47
-
48
- Role hash **stored in the database as YAML** string.
49
- Using of hashes, makes it extremely easy to configure access rules in the role.
50
-
51
40
  ### Virtual sections and rules
52
41
 
53
- Usually, we use real names of controllers as names of sections, and we use names of real actions in controllers as names of section's rules.
54
-
55
- Like this:
42
+ Usually, we use real names of controllers and actions for names of sections and rules:
56
43
 
57
44
  ``` ruby
58
45
  current_user.has_role?(:pages, :show)
59
46
  ```
60
47
 
61
- But you can also create virtual sections and rules:
62
-
48
+ But, also, you can use virtual names of sections, and virtual names of section's rules.
63
49
 
64
50
  ``` ruby
65
51
  current_user.has_role?(:twitter, :button)
66
52
  current_user.has_role?(:facebook, :like)
67
53
  ```
68
54
 
69
- These sections and the rules are not associated with real controllers and actions.
70
55
  And you can use them as well as other access rules.
71
56
 
72
- ### Install and use
57
+ # Install
73
58
 
74
59
  ``` ruby
75
60
  gem 'the_role'
76
61
  ```
77
62
 
78
63
  ``` ruby
79
- bundle install
64
+ bundle
80
65
  ```
81
66
 
82
- Add **role_id:integer** to User Model Migration
67
+ ### Migrate
83
68
 
69
+ Add **role_id:integer** to User Model Migration
84
70
 
85
71
  ``` ruby
86
72
  rake the_role_engine:install:migrations
@@ -95,18 +81,16 @@ rails g model role --migration=false
95
81
  rake db:create && rake db:migrate
96
82
  ```
97
83
 
98
- Creating roles for test (**not required**)
84
+ ### Fake roles for test (not required)
85
+
86
+ Creating roles for test
99
87
 
100
88
  ``` ruby
101
89
  rake db:roles:test
102
90
  >> Administrator, Moderator of pages, User, Demo
103
91
  ```
104
92
 
105
- Define aliases method for correctly work TheRole's controllers
106
-
107
- **authenticate_user!** or any other method from your auth system
108
-
109
- **access_denied** or any other method for processing access denied situation
93
+ ### Change your ApplicationController
110
94
 
111
95
  **Example for Devise2**
112
96
 
@@ -118,55 +102,48 @@ class ApplicationController < ActionController::Base
118
102
  render :text => 'access_denied: requires an role' and return
119
103
  end
120
104
 
121
- # define aliases for correctly work of TheRole admin panel
122
- # *authenticate_user!* - method from Devise2
123
- # *access_denied* - define it before alias_method
124
- # before_filter :role_object_finder, :only => [:edit, :update, :rebuild, :destroy]
125
- alias_method :role_login_required, :authenticate_user!
126
- alias_method :role_access_denied, :access_denied
105
+ alias_method :login_required, :authenticate_user!
106
+ alias_method :role_access_denied, :access_denied
127
107
 
128
108
  end
129
109
  ```
130
110
 
131
- Using with any controller
132
-
133
- ``` ruby
134
- class PagesController < ApplicationController
135
- # Devise2 and TheRole before_filters
136
- before_filter :role_login_required, :except => [:index, :show]
137
- before_filter :role_require, :except => [:index, :show]
138
-
139
- before_filter :find_page, :only => [:edit, :update, :destroy]
140
- before_filter :owner_require, :only => [:edit, :update, :destroy]
111
+ Define aliases method for correctly work TheRole's controllers
141
112
 
142
- end
143
- ```
113
+ **authenticate_user!** or any other method from your auth system
144
114
 
145
- ### WARNING! IT'S IMPORTANT
115
+ **access_denied** or any other method for processing access denied situation
146
116
 
147
- When you checking **owner_require** - you should before this to define variable **@object_for_ownership_checking** in finder method.
148
117
 
149
- For example:
118
+ ### Using with any controller
150
119
 
151
120
  ``` ruby
152
121
  class PagesController < ApplicationController
153
- before_filter :find_page, :only => [:edit, :update, :destroy]
154
- before_filter :owner_require, :only => [:edit, :update, :destroy]
155
-
122
+ # Devise2 and TheRole before_filters
123
+ before_filter :login_required, :except => [:index, :show]
124
+ before_filter :role_required, :except => [:index, :show]
125
+
126
+ before_filter :find_page, :only => [:edit, :update, :destroy]
127
+ before_filter :owner_required, :only => [:edit, :update, :destroy]
128
+
156
129
  private
157
130
 
158
131
  def find_page
159
132
  @page = Page.find params[:id]
160
- @object_for_ownership_checking = @page
133
+ @ownership_checking_object = @page
161
134
  end
162
135
  end
163
136
  ```
164
137
 
165
- ### Who is the Administrator?
138
+ **owner_required** method require **@ownership_checking_object** variable, with cheked object.
139
+
140
+ ### Who is Administrator?
166
141
 
167
- Administrator - a user who can access any section and the rules of your application.
168
- The administrator is the owner of any objects in your application.
169
- Administrator - a user in the role-hash of which there is a section **system** and rule **administrator**.
142
+ Administrator it's a user who can access any section and the rules of your application.
143
+
144
+ Administrator is the owner of any objects in your application.
145
+
146
+ Administrator it's a user, which has virtual section **system** and rule **administrator** in the role-hash.
170
147
 
171
148
 
172
149
  ``` ruby
@@ -177,13 +154,15 @@ admin_role_fragment = {
177
154
  }
178
155
  ```
179
156
 
180
- ### Who is the Moderator?
157
+ ### Who is Moderator?
158
+
159
+ Moderator it's a user, which has access to any actions of some section(s).
181
160
 
182
- Moderator - a user who can access any actions of sections.
183
- Moderator is the owner of any objects of this class.
184
- Moderator - user which has in a section **moderator** rule with name of real or virtual section (controller).
161
+ Moderator is's owner of any objects of some class.
185
162
 
186
- There is role hash of Moderator of Pages (controller) and Twitter (virtual section)
163
+ Moderator it's a user, which has a virtual section **moderator**, with **section name** as rule name.
164
+
165
+ There is Moderator of Pages (controller) and Twitter (virtual section)
187
166
 
188
167
  ``` ruby
189
168
  moderator_role_fragment = {
@@ -195,9 +174,17 @@ moderator_role_fragment = {
195
174
  }
196
175
  ```
197
176
 
198
- ### User methods
177
+ ### Who is Owner?
178
+
179
+ Administrator is owner of any object in system.
180
+
181
+ Moderator of pages is owner of any page.
199
182
 
200
- Has a user an access to **action** of **section**?
183
+ User is owner of object, when **Object#user_id == User#id**.
184
+
185
+ # User Model methods
186
+
187
+ Has a user an access to **rule** of **section** (action of controller)?
201
188
 
202
189
  ``` ruby
203
190
  current_user.has_role?(:pages, :show) => true | false
@@ -227,22 +214,25 @@ current_user.owner?(@blog) => true | false
227
214
  current_user.owner?(@article) => true | false
228
215
  ```
229
216
 
230
- ### Role methods
217
+ # Base Role methods
231
218
 
232
219
  ``` ruby
233
- # Find a Role by name
234
- @role.find_by_name(:user)
220
+ # User's role
221
+ @role = current_user.role
235
222
  ```
236
223
 
237
224
  ``` ruby
238
- # User Model like methods
225
+ # Find a Role by name
226
+ @role = Role.find_by_name(:user)
227
+ ```
239
228
 
229
+ ``` ruby
240
230
  @role.has?(:pages, :show) => true | false
241
231
  @role.moderator?(:pages) => true | false
242
232
  @role.admin? => true | false
243
233
  ```
244
234
 
245
- ## CRUD API
235
+ # CRUD API (for console users)
246
236
 
247
237
  #### CREATE
248
238
 
@@ -261,10 +251,10 @@ current_user.owner?(@article) => true | false
261
251
  ``` ruby
262
252
  @role.to_hash => Hash
263
253
 
264
- # YAML string
265
- @role.to_yaml => String
254
+ # JSON string
255
+ @role.to_json => String
266
256
 
267
- # YAML string
257
+ # JSON string
268
258
  @role.to_s => String
269
259
  ```
270
260
 
@@ -0,0 +1,3 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
3
+ //= require bootstrap-dropdown
@@ -0,0 +1,100 @@
1
+ /* ============================================================
2
+ * bootstrap-dropdown.js v2.0.4
3
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
4
+ * ============================================================
5
+ * Copyright 2012 Twitter, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ============================================================ */
19
+
20
+
21
+ !function ($) {
22
+
23
+ "use strict"; // jshint ;_;
24
+
25
+
26
+ /* DROPDOWN CLASS DEFINITION
27
+ * ========================= */
28
+
29
+ var toggle = '[data-toggle="dropdown"]'
30
+ , Dropdown = function (element) {
31
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
32
+ $('html').on('click.dropdown.data-api', function () {
33
+ $el.parent().removeClass('open')
34
+ })
35
+ }
36
+
37
+ Dropdown.prototype = {
38
+
39
+ constructor: Dropdown
40
+
41
+ , toggle: function (e) {
42
+ var $this = $(this)
43
+ , $parent
44
+ , selector
45
+ , isActive
46
+
47
+ if ($this.is('.disabled, :disabled')) return
48
+
49
+ selector = $this.attr('data-target')
50
+
51
+ if (!selector) {
52
+ selector = $this.attr('href')
53
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
54
+ }
55
+
56
+ $parent = $(selector)
57
+ $parent.length || ($parent = $this.parent())
58
+
59
+ isActive = $parent.hasClass('open')
60
+
61
+ clearMenus()
62
+
63
+ if (!isActive) $parent.toggleClass('open')
64
+
65
+ return false
66
+ }
67
+
68
+ }
69
+
70
+ function clearMenus() {
71
+ $(toggle).parent().removeClass('open')
72
+ }
73
+
74
+
75
+ /* DROPDOWN PLUGIN DEFINITION
76
+ * ========================== */
77
+
78
+ $.fn.dropdown = function (option) {
79
+ return this.each(function () {
80
+ var $this = $(this)
81
+ , data = $this.data('dropdown')
82
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
83
+ if (typeof option == 'string') data[option].call($this)
84
+ })
85
+ }
86
+
87
+ $.fn.dropdown.Constructor = Dropdown
88
+
89
+
90
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
91
+ * =================================== */
92
+
93
+ $(function () {
94
+ $('html').on('click.dropdown.data-api', clearMenus)
95
+ $('body')
96
+ .on('click.dropdown', '.dropdown form', function (e) { e.stopPropagation() })
97
+ .on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
98
+ })
99
+
100
+ }(window.jQuery);
@@ -0,0 +1,7 @@
1
+ /*
2
+ *= require 'mix'
3
+ *= require 'reset'
4
+ *= require 'custom'
5
+ *= require 'headers'
6
+ *= require 'role_set'
7
+ */
@@ -0,0 +1,58 @@
1
+ // ALERT STYLES
2
+ // ------------
3
+
4
+ // Base alert styles
5
+ .alert {
6
+ padding: 8px 35px 8px 14px;
7
+ margin-bottom: @baseLineHeight;
8
+ text-shadow: 0 1px 0 rgba(255,255,255,.5);
9
+ background-color: @warningBackground;
10
+ border: 1px solid @warningBorder;
11
+ .border-radius(4px);
12
+ color: @warningText;
13
+ }
14
+ .alert-heading {
15
+ color: inherit;
16
+ }
17
+
18
+ // Adjust close link position
19
+ .alert .close {
20
+ position: relative;
21
+ top: -2px;
22
+ right: -21px;
23
+ line-height: 18px;
24
+ }
25
+
26
+ // Alternate styles
27
+ // ----------------
28
+
29
+ .alert-success {
30
+ background-color: @successBackground;
31
+ border-color: @successBorder;
32
+ color: @successText;
33
+ }
34
+ .alert-danger,
35
+ .alert-error {
36
+ background-color: @errorBackground;
37
+ border-color: @errorBorder;
38
+ color: @errorText;
39
+ }
40
+ .alert-info {
41
+ background-color: @infoBackground;
42
+ border-color: @infoBorder;
43
+ color: @infoText;
44
+ }
45
+
46
+ // Block alerts
47
+ // ------------------------
48
+ .alert-block {
49
+ padding-top: 14px;
50
+ padding-bottom: 14px;
51
+ }
52
+ .alert-block > p,
53
+ .alert-block > ul {
54
+ margin-bottom: 0;
55
+ }
56
+ .alert-block p + p {
57
+ margin-top: 5px;
58
+ }
@@ -0,0 +1,191 @@
1
+ // BUTTON GROUPS
2
+ // -------------
3
+
4
+
5
+ // Make the div behave like a button
6
+ .btn-group {
7
+ position: relative;
8
+ .clearfix(); // clears the floated buttons
9
+ .ie7-restore-left-whitespace();
10
+ }
11
+
12
+ // Space out series of button groups
13
+ .btn-group + .btn-group {
14
+ margin-left: 5px;
15
+ }
16
+
17
+ // Optional: Group multiple button groups together for a toolbar
18
+ .btn-toolbar {
19
+ margin-top: @baseLineHeight / 2;
20
+ margin-bottom: @baseLineHeight / 2;
21
+ .btn-group {
22
+ display: inline-block;
23
+ .ie7-inline-block();
24
+ }
25
+ }
26
+
27
+ // Float them, remove border radius, then re-add to first and last elements
28
+ .btn-group > .btn {
29
+ position: relative;
30
+ float: left;
31
+ margin-left: -1px;
32
+ .border-radius(0);
33
+ }
34
+ // Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
35
+ .btn-group > .btn:first-child {
36
+ margin-left: 0;
37
+ -webkit-border-top-left-radius: 4px;
38
+ -moz-border-radius-topleft: 4px;
39
+ border-top-left-radius: 4px;
40
+ -webkit-border-bottom-left-radius: 4px;
41
+ -moz-border-radius-bottomleft: 4px;
42
+ border-bottom-left-radius: 4px;
43
+ }
44
+ // Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
45
+ .btn-group > .btn:last-child,
46
+ .btn-group > .dropdown-toggle {
47
+ -webkit-border-top-right-radius: 4px;
48
+ -moz-border-radius-topright: 4px;
49
+ border-top-right-radius: 4px;
50
+ -webkit-border-bottom-right-radius: 4px;
51
+ -moz-border-radius-bottomright: 4px;
52
+ border-bottom-right-radius: 4px;
53
+ }
54
+ // Reset corners for large buttons
55
+ .btn-group > .btn.large:first-child {
56
+ margin-left: 0;
57
+ -webkit-border-top-left-radius: 6px;
58
+ -moz-border-radius-topleft: 6px;
59
+ border-top-left-radius: 6px;
60
+ -webkit-border-bottom-left-radius: 6px;
61
+ -moz-border-radius-bottomleft: 6px;
62
+ border-bottom-left-radius: 6px;
63
+ }
64
+ .btn-group > .btn.large:last-child,
65
+ .btn-group > .large.dropdown-toggle {
66
+ -webkit-border-top-right-radius: 6px;
67
+ -moz-border-radius-topright: 6px;
68
+ border-top-right-radius: 6px;
69
+ -webkit-border-bottom-right-radius: 6px;
70
+ -moz-border-radius-bottomright: 6px;
71
+ border-bottom-right-radius: 6px;
72
+ }
73
+
74
+ // On hover/focus/active, bring the proper btn to front
75
+ .btn-group > .btn:hover,
76
+ .btn-group > .btn:focus,
77
+ .btn-group > .btn:active,
78
+ .btn-group > .btn.active {
79
+ z-index: 2;
80
+ }
81
+
82
+ // On active and open, don't show outline
83
+ .btn-group .dropdown-toggle:active,
84
+ .btn-group.open .dropdown-toggle {
85
+ outline: 0;
86
+ }
87
+
88
+
89
+
90
+ // Split button dropdowns
91
+ // ----------------------
92
+
93
+ // Give the line between buttons some depth
94
+ .btn-group > .dropdown-toggle {
95
+ padding-left: 8px;
96
+ padding-right: 8px;
97
+ .box-shadow(~"inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)");
98
+ *padding-top: 4px;
99
+ *padding-bottom: 4px;
100
+ }
101
+ .btn-group > .btn-mini.dropdown-toggle {
102
+ padding-left: 5px;
103
+ padding-right: 5px;
104
+ }
105
+ .btn-group > .btn-small.dropdown-toggle {
106
+ *padding-top: 4px;
107
+ *padding-bottom: 4px;
108
+ }
109
+ .btn-group > .btn-large.dropdown-toggle {
110
+ padding-left: 12px;
111
+ padding-right: 12px;
112
+ }
113
+
114
+ .btn-group.open {
115
+
116
+ // The clickable button for toggling the menu
117
+ // Remove the gradient and set the same inset shadow as the :active state
118
+ .dropdown-toggle {
119
+ background-image: none;
120
+ .box-shadow(~"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)");
121
+ }
122
+
123
+ // Keep the hover's background when dropdown is open
124
+ .btn.dropdown-toggle {
125
+ background-color: @btnBackgroundHighlight;
126
+ }
127
+ .btn-primary.dropdown-toggle {
128
+ background-color: @btnPrimaryBackgroundHighlight;
129
+ }
130
+ .btn-warning.dropdown-toggle {
131
+ background-color: @btnWarningBackgroundHighlight;
132
+ }
133
+ .btn-danger.dropdown-toggle {
134
+ background-color: @btnDangerBackgroundHighlight;
135
+ }
136
+ .btn-success.dropdown-toggle {
137
+ background-color: @btnSuccessBackgroundHighlight;
138
+ }
139
+ .btn-info.dropdown-toggle {
140
+ background-color: @btnInfoBackgroundHighlight;
141
+ }
142
+ .btn-inverse.dropdown-toggle {
143
+ background-color: @btnInverseBackgroundHighlight;
144
+ }
145
+ }
146
+
147
+
148
+ // Reposition the caret
149
+ .btn .caret {
150
+ margin-top: 7px;
151
+ margin-left: 0;
152
+ }
153
+ .btn:hover .caret,
154
+ .open.btn-group .caret {
155
+ .opacity(100);
156
+ }
157
+ // Carets in other button sizes
158
+ .btn-mini .caret {
159
+ margin-top: 5px;
160
+ }
161
+ .btn-small .caret {
162
+ margin-top: 6px;
163
+ }
164
+ .btn-large .caret {
165
+ margin-top: 6px;
166
+ border-left-width: 5px;
167
+ border-right-width: 5px;
168
+ border-top-width: 5px;
169
+ }
170
+ // Upside down carets for .dropup
171
+ .dropup .btn-large .caret {
172
+ border-bottom: 5px solid @black;
173
+ border-top: 0;
174
+ }
175
+
176
+
177
+
178
+ // Account for other colors
179
+ .btn-primary,
180
+ .btn-warning,
181
+ .btn-danger,
182
+ .btn-info,
183
+ .btn-success,
184
+ .btn-inverse {
185
+ .caret {
186
+ border-top-color: @white;
187
+ border-bottom-color: @white;
188
+ .opacity(75);
189
+ }
190
+ }
191
+