the_role 0.9.9
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +104 -0
- data/Rakefile +1 -0
- data/app/assets/stylesheets/the_role/form.css +55 -0
- data/app/assets/stylesheets/the_role/headers.css.scss +13 -0
- data/app/assets/stylesheets/the_role/reset.css.scss +63 -0
- data/app/assets/stylesheets/the_role/style.css.scss +76 -0
- data/app/controllers/admin/role_section_controller.rb +37 -0
- data/app/controllers/admin/roles_controller.rb +106 -0
- data/app/views/admin/roles/_form.slim +26 -0
- data/app/views/admin/roles/edit.slim +37 -0
- data/app/views/admin/roles/index.slim +9 -0
- data/app/views/admin/roles/new.slim +12 -0
- data/app/views/layouts/the_role.slim +15 -0
- data/config/locales/ru.yml +42 -0
- data/config/routes.rb +18 -0
- data/db/migrate/20111025025129_create_roles.rb +17 -0
- data/lib/tasks/roles.rake +120 -0
- data/lib/the_role/engine.rb +12 -0
- data/lib/the_role/hash.rb +25 -0
- data/lib/the_role/the_class_exists.rb +8 -0
- data/lib/the_role/version.rb +3 -0
- data/lib/the_role.rb +107 -0
- data/the_role.gemspec +24 -0
- metadata +71 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
## TheRole
|
2
|
+
|
3
|
+
Gem for providing simple, but powerful and flexible role system for ROR3 applications.
|
4
|
+
Based on Hashes.
|
5
|
+
|
6
|
+
* Based on MVC semantik (easy to understand what's happening)
|
7
|
+
* Realtime dynamically management with simple interface
|
8
|
+
* Customizable
|
9
|
+
|
10
|
+
## Installing
|
11
|
+
|
12
|
+
Gemfile
|
13
|
+
|
14
|
+
``` ruby
|
15
|
+
gem 'the_role'
|
16
|
+
```
|
17
|
+
|
18
|
+
``` ruby
|
19
|
+
bundle
|
20
|
+
```
|
21
|
+
|
22
|
+
``` ruby
|
23
|
+
rake the_role_engine:install:migrations
|
24
|
+
>> Copied migration 20111028145956_create_roles.rb from the_role_engine
|
25
|
+
```
|
26
|
+
|
27
|
+
``` ruby
|
28
|
+
rake db:roles:create
|
29
|
+
>> Administrator, Moderator of pages, User, Demo
|
30
|
+
```
|
31
|
+
|
32
|
+
When gem initialize, **User**, **Role**, **ApplicationController** classes are extending with next methods:
|
33
|
+
|
34
|
+
## User
|
35
|
+
|
36
|
+
``` ruby
|
37
|
+
# will be include into User.rb automaticaly
|
38
|
+
belongs_to :role
|
39
|
+
attr_accessible :role
|
40
|
+
after_save { |user| user.instance_variable_set(:@the_role, nil) }
|
41
|
+
|
42
|
+
# methods
|
43
|
+
the_role
|
44
|
+
admin?
|
45
|
+
moderator?(section)
|
46
|
+
has_role?(section, policy)
|
47
|
+
owner?(obj)
|
48
|
+
|
49
|
+
# instance variables
|
50
|
+
@the_role
|
51
|
+
```
|
52
|
+
|
53
|
+
## Role
|
54
|
+
|
55
|
+
``` ruby
|
56
|
+
# will be include into Role.rb automaticaly
|
57
|
+
has_many :users
|
58
|
+
validates :name, :presence => {:message => I18n.translate('the_role.name_presence')}
|
59
|
+
validates :title, :presence => {:message => I18n.translate('the_role.title_presence')}
|
60
|
+
```
|
61
|
+
|
62
|
+
## ApplicationController
|
63
|
+
|
64
|
+
``` ruby
|
65
|
+
# private methods (should be define as before filters)
|
66
|
+
the_role_access_denied
|
67
|
+
the_role_object
|
68
|
+
the_role_require
|
69
|
+
the_owner_require
|
70
|
+
```
|
71
|
+
## Routes
|
72
|
+
|
73
|
+
method **the_role_access_denied** needs **root_path** for redirect
|
74
|
+
|
75
|
+
### Now try to use into console
|
76
|
+
|
77
|
+
``` ruby
|
78
|
+
rails g scaffold article title:string content:text user_id:integer
|
79
|
+
rails g scaffold page title:string content:text user_id:integer
|
80
|
+
rails c
|
81
|
+
>> User.new(:login => 'cosmo', :username => 'John Black').save
|
82
|
+
>> u = User.first
|
83
|
+
>> u.role = Role.first # admin
|
84
|
+
>> u.save
|
85
|
+
>> u.has_role? :x, :y
|
86
|
+
=> true
|
87
|
+
>> u.role = Role.last # demo
|
88
|
+
>> u.save
|
89
|
+
>> u.has_role? :pages, :show
|
90
|
+
=> true
|
91
|
+
>> u.has_role? :pages, :delete
|
92
|
+
=> flase
|
93
|
+
```
|
94
|
+
|
95
|
+
## Example
|
96
|
+
|
97
|
+
``` ruby
|
98
|
+
- if curent_user.has_role? :pages, :show
|
99
|
+
Page content
|
100
|
+
- else
|
101
|
+
Access denied
|
102
|
+
```
|
103
|
+
|
104
|
+
Copyright (c) 2011 [Ilya N. Zykin Github.com/the-teacher], released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
.form{
|
2
|
+
background:#EEE;
|
3
|
+
padding:5px;
|
4
|
+
margin:0 0 15px 0;
|
5
|
+
border:2px solid gray;
|
6
|
+
-moz-border-radius:5px;
|
7
|
+
}
|
8
|
+
.form label{
|
9
|
+
display:block;
|
10
|
+
}
|
11
|
+
.form .input{
|
12
|
+
border:1px solid #000;
|
13
|
+
padding:2px 0 2px 5px;
|
14
|
+
font-size:13pt;
|
15
|
+
color:DarkBlue;
|
16
|
+
}
|
17
|
+
.form .textarea{
|
18
|
+
font-size:13pt;
|
19
|
+
padding:2px;
|
20
|
+
}
|
21
|
+
.form .message_textarea{
|
22
|
+
font-size:13pt;
|
23
|
+
padding:2px;
|
24
|
+
border:1px solid black;
|
25
|
+
height: 200px;
|
26
|
+
}
|
27
|
+
.form .submit{
|
28
|
+
font-size:16pt;
|
29
|
+
}
|
30
|
+
.article_buttons{
|
31
|
+
margin:0 0 10px 0;
|
32
|
+
padding:0 0 5px 0;
|
33
|
+
border-bottom:1px dashed gray;
|
34
|
+
}
|
35
|
+
.article_buttons input{
|
36
|
+
margin-right:10px;
|
37
|
+
}
|
38
|
+
.submit_button{
|
39
|
+
margin-bottom:10px;
|
40
|
+
}
|
41
|
+
.moderation_buttons{
|
42
|
+
background:silver;
|
43
|
+
margin:3px 3px 10px 3px;
|
44
|
+
padding:5px;
|
45
|
+
border:2px solid blue;
|
46
|
+
}
|
47
|
+
.delete_button{
|
48
|
+
background: none repeat scroll 0 0 lightGrey;
|
49
|
+
border: 1px dashed gray;
|
50
|
+
padding: 5px 0;
|
51
|
+
text-align: right;
|
52
|
+
}
|
53
|
+
.delete_button input{
|
54
|
+
color:Crimson;
|
55
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
h1,h2,h3,h4,h5,h6{
|
2
|
+
font-family: Verdana, Arial;
|
3
|
+
color:#333;
|
4
|
+
font-weight:normal;
|
5
|
+
line-height:100%;
|
6
|
+
margin-bottom:15px;
|
7
|
+
}
|
8
|
+
h1{font-size:3em;}
|
9
|
+
h2{font-size:2.8em;}
|
10
|
+
h3{font-size:2.6em;}
|
11
|
+
h4{font-size:2.4em;}
|
12
|
+
h5{font-size:2.2em;}
|
13
|
+
h6{font-size:2em;}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/*18 aug 2011 */
|
2
|
+
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6,
|
3
|
+
p, img, font, pre, blockquote, i, b, u, s, strike, sub, sup, tt, big, small,
|
4
|
+
center, abbr, em, code, acronym, address, ins, del, strong, var, cite,
|
5
|
+
dfn, kbd, samp, dd, dl, dt, ol, ul, li, caption,
|
6
|
+
table, tbody, tfoot, thead, tr, th, td,
|
7
|
+
form, fieldset, legend, label,
|
8
|
+
article, aside, canvas, details, embed, figure, figcaption,
|
9
|
+
footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video{
|
10
|
+
margin:0;
|
11
|
+
padding:0;
|
12
|
+
border:0;
|
13
|
+
outline:0;
|
14
|
+
font-size:10px; /*zero-point*/
|
15
|
+
vertical-align:baseline;
|
16
|
+
background:transparent;
|
17
|
+
line-height:100%;
|
18
|
+
}
|
19
|
+
html, body, div, applet, object, iframe, img, p, pre, blockquote,
|
20
|
+
dd, dl, dt, ol, ul, li, caption, table, tbody, tfoot, thead, tr, th, td,
|
21
|
+
form, fieldset, legend, label{
|
22
|
+
font-weight:normal;
|
23
|
+
}
|
24
|
+
|
25
|
+
img, p, pre, blockquote, dd, dt, li, caption, legend, label{line-height:100%;}
|
26
|
+
table, tr, td{
|
27
|
+
vertical-align:top;
|
28
|
+
border-collapse:collapse;
|
29
|
+
border-spacing:0;
|
30
|
+
}
|
31
|
+
img{vertical-align:top;}
|
32
|
+
ol, ul{list-style:none; margin:0;}
|
33
|
+
li{list-style-position:outside;}
|
34
|
+
|
35
|
+
a{text-decoration:none;}
|
36
|
+
a:hover{text-decoration:none;}
|
37
|
+
|
38
|
+
sup, sub{font-size:85%; zoom:1;}
|
39
|
+
sup{vertical-align:40%;}
|
40
|
+
sub{vertical-align:-40%;}
|
41
|
+
:focus{outline:0;}
|
42
|
+
.overblock{overflow:hidden; zoom:1;}
|
43
|
+
.nobr{white-space:nowrap;}
|
44
|
+
.u{text-decoration:underline;}
|
45
|
+
noscript{color:red;}
|
46
|
+
/*basic LIST styles*/
|
47
|
+
.numered_list, .marked_list{margin-left:20px;}
|
48
|
+
.numered_list li, .marked_list li{
|
49
|
+
list-style-position: outside;
|
50
|
+
margin-left: 15px;
|
51
|
+
padding-left: 5px;
|
52
|
+
}
|
53
|
+
.numered_list li{list-style-type:decimal;}
|
54
|
+
.marked_list li{list-style-type:disc;}
|
55
|
+
/*Inherit*/
|
56
|
+
a, span, font, i, b, u, s, strike{ font-size: inherit; }
|
57
|
+
/*CUSTOM*/
|
58
|
+
img, p, pre, blockquote, dd, dt, caption, legend, label{
|
59
|
+
line-height:150%;
|
60
|
+
}
|
61
|
+
p, pre, blockquote{margin-bottom:15px;}
|
62
|
+
a{color:#8CA357;}
|
63
|
+
a:hover{text-decoration:underline;}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
.body{
|
2
|
+
width: 900px;
|
3
|
+
margin:auto;
|
4
|
+
font:Tahoma;
|
5
|
+
font-family:Tahoma,Trebuchet MS,Times New Roman;
|
6
|
+
}
|
7
|
+
img, p, pre, blockquote, dd, dt, caption, legend, label{
|
8
|
+
font-size: 2em;
|
9
|
+
}
|
10
|
+
ul.index{
|
11
|
+
p{
|
12
|
+
padding: 5px;
|
13
|
+
&:hover{
|
14
|
+
background: #DDD;
|
15
|
+
|
16
|
+
}
|
17
|
+
a.delete{
|
18
|
+
float: right;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}//ul.index
|
22
|
+
|
23
|
+
h4{
|
24
|
+
position: relative;
|
25
|
+
padding: 5px;
|
26
|
+
background: LightBlue;
|
27
|
+
.controls{
|
28
|
+
a{
|
29
|
+
color: blue;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
.controls{
|
35
|
+
position:absolute;
|
36
|
+
right:10px;
|
37
|
+
top:10%;
|
38
|
+
zoom:1;
|
39
|
+
padding-bottom:6px;
|
40
|
+
}
|
41
|
+
.controls a{
|
42
|
+
margin:0 10px;
|
43
|
+
font-size:10pt;
|
44
|
+
color:#CCC;
|
45
|
+
border:1px solid transparent;
|
46
|
+
padding:3px;
|
47
|
+
text-decoration:none;
|
48
|
+
}
|
49
|
+
.controls a:hover{
|
50
|
+
color:#999;
|
51
|
+
border:1px solid #999;
|
52
|
+
}
|
53
|
+
ul.rights{
|
54
|
+
margin:0 0 20px;
|
55
|
+
}
|
56
|
+
ul.rights li{
|
57
|
+
margin:0 0 5px 20px;
|
58
|
+
position:relative;
|
59
|
+
zoom:1;
|
60
|
+
border-bottom:1px solid #EEE;
|
61
|
+
padding: 5px 0;
|
62
|
+
font-size:9pt;
|
63
|
+
}
|
64
|
+
ul.rights li .controls{
|
65
|
+
top:10%;
|
66
|
+
right:5px;
|
67
|
+
padding:5px;
|
68
|
+
}
|
69
|
+
form.new_action{
|
70
|
+
padding:15px;
|
71
|
+
background:#EEE;
|
72
|
+
margin:0 0 50px 0;
|
73
|
+
}
|
74
|
+
form{
|
75
|
+
margin:0 0 50px 0;
|
76
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Admin::RoleSectionController < ApplicationController
|
2
|
+
# before_filter :login_required
|
3
|
+
before_filter :find_role, :only=>[:destroy, :delete_policy]
|
4
|
+
|
5
|
+
def destroy
|
6
|
+
section_name = params[:id]
|
7
|
+
role = TheRole.get(@role.the_role)
|
8
|
+
role.delete(section_name.to_sym)
|
9
|
+
|
10
|
+
if @role.update_attributes({:the_role => role.to_yaml})
|
11
|
+
flash[:notice] = t('the_role.section_deleted')
|
12
|
+
redirect_to edit_admin_role_path(@role)
|
13
|
+
else
|
14
|
+
render :action => :edit
|
15
|
+
end
|
16
|
+
end#destroy
|
17
|
+
|
18
|
+
def delete_policy
|
19
|
+
section_name = params[:id]
|
20
|
+
policy_name = params[:name]
|
21
|
+
role = TheRole.get(@role.the_role)
|
22
|
+
role[section_name.to_sym].delete(policy_name.to_sym)
|
23
|
+
|
24
|
+
if @role.update_attributes({:the_role => role.to_yaml})
|
25
|
+
flash[:notice] = t('the_role.section_policy_deleted')
|
26
|
+
redirect_to edit_admin_role_path(@role)
|
27
|
+
else
|
28
|
+
render :action => :edit
|
29
|
+
end
|
30
|
+
end#delete_policy
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def find_role
|
35
|
+
@role = Role.find(params[:role_id])
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'the_role'
|
2
|
+
|
3
|
+
class Admin::RolesController < ApplicationController
|
4
|
+
layout 'the_role'
|
5
|
+
# before_filter :login_required
|
6
|
+
# before_filter :role_require
|
7
|
+
before_filter :find_role, :only => [:show, :edit, :update, :destroy, :new_role_section, :new_role_policy]
|
8
|
+
|
9
|
+
def index
|
10
|
+
@roles = Role.all(:order => "created_at ASC")
|
11
|
+
end
|
12
|
+
|
13
|
+
def new
|
14
|
+
@role = Role.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def edit; end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@role = Role.new(params[:role])
|
21
|
+
|
22
|
+
if @role.save
|
23
|
+
flash[:notice] = t('the_role.role_created')
|
24
|
+
redirect_to edit_admin_role_path(@role)
|
25
|
+
else
|
26
|
+
render :action => :new
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
role = TheRole.get(@role.the_role).the_reset!
|
32
|
+
role.the_merge!(params[:role][:the_role])
|
33
|
+
|
34
|
+
if @role.update_attribute(:the_role, role.to_yaml)
|
35
|
+
flash[:notice] = t('the_role.role_updated')
|
36
|
+
redirect_to edit_admin_role_path(@role)
|
37
|
+
else
|
38
|
+
render :action => :edit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def new_role_section
|
43
|
+
# validate 1
|
44
|
+
if params[:section_name].blank?
|
45
|
+
flash[:error] = t('the_role.section_name_is_blank')
|
46
|
+
redirect_to edit_admin_role_path(@role) and return
|
47
|
+
end
|
48
|
+
|
49
|
+
# validate 2
|
50
|
+
section_name = params[:section_name]
|
51
|
+
unless section_name.match(TheRole::NAME_SYMBOLS)
|
52
|
+
flash[:error] = t('the_role.section_name_is_wrong')
|
53
|
+
redirect_to edit_admin_role_path(@role) and return
|
54
|
+
end
|
55
|
+
|
56
|
+
section_name.downcase!
|
57
|
+
role = TheRole.get(@role.the_role)
|
58
|
+
|
59
|
+
# validate 3
|
60
|
+
if role[section_name.to_sym]
|
61
|
+
flash[:error] = t('the_role.section_exists')
|
62
|
+
redirect_to edit_admin_role_path(@role) and return
|
63
|
+
end
|
64
|
+
|
65
|
+
role[section_name.to_sym] = Hash.new
|
66
|
+
|
67
|
+
if @role.update_attributes({:the_role => role.to_yaml})
|
68
|
+
flash[:notice] = t('the_role.section_created')
|
69
|
+
redirect_to edit_admin_role_path(@role)
|
70
|
+
else
|
71
|
+
render :action => :edit
|
72
|
+
end
|
73
|
+
end#new_role_section
|
74
|
+
|
75
|
+
def new_role_policy
|
76
|
+
params[:section_policy].downcase!
|
77
|
+
|
78
|
+
# validate 1
|
79
|
+
unless params[:section_policy].match(TheRole::NAME_SYMBOLS)
|
80
|
+
flash[:error] = t('the_role.section_policy_wrong_name')
|
81
|
+
redirect_to edit_admin_role_path(@role)
|
82
|
+
end
|
83
|
+
|
84
|
+
role = TheRole.get(@role.the_role)
|
85
|
+
role[params[:section_name].to_sym][params[:section_policy].to_sym] = true
|
86
|
+
|
87
|
+
if @role.update_attributes({:the_role => role.to_yaml})
|
88
|
+
flash[:notice] = t('the_role.section_policy_created')
|
89
|
+
redirect_to edit_admin_role_path(@role)
|
90
|
+
else
|
91
|
+
render :action => :edit
|
92
|
+
end
|
93
|
+
end#new_role_policy
|
94
|
+
|
95
|
+
def destroy
|
96
|
+
@role.destroy
|
97
|
+
redirect_to admin_roles_url
|
98
|
+
end
|
99
|
+
|
100
|
+
protected
|
101
|
+
|
102
|
+
def find_role
|
103
|
+
@role = Role.find(params[:id])
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
- role = TheRole.get(@role.the_role)
|
2
|
+
|
3
|
+
- if role.blank?
|
4
|
+
h3
|
5
|
+
= t('.empty')
|
6
|
+
- else
|
7
|
+
-role.each do |name, set|
|
8
|
+
h4
|
9
|
+
= name
|
10
|
+
span.controls
|
11
|
+
= link_to(t('.delete'), admin_role_section_url(@role, name), :method => :delete, :confirm => t('.destroy_section_confirm'))
|
12
|
+
|
13
|
+
- if set.is_a?(Hash)
|
14
|
+
ul.rights
|
15
|
+
- set.each do |n, v|
|
16
|
+
li
|
17
|
+
= check_box_tag "role[the_role][#{name}][#{n}]", true, v
|
18
|
+
= n
|
19
|
+
.controls
|
20
|
+
= link_to t('.delete'), delete_policy_admin_role_section_path(@role, name, :name => n), :method => :delete, :confirm => t('.delete_policy_confirm')
|
21
|
+
|
22
|
+
= f.submit button
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
- content_for :title do
|
2
|
+
= t('.title')
|
3
|
+
|
4
|
+
p= flash[:notice]
|
5
|
+
|
6
|
+
h1= t('.title')
|
7
|
+
|
8
|
+
p= link_to raw(t('.back')), admin_roles_path
|
9
|
+
|
10
|
+
h2
|
11
|
+
== t('.name')
|
12
|
+
= @role.title
|
13
|
+
|
14
|
+
= form_for :role, :url => {:action=> :update }, :html => {:method => :put, :class => :form } do |f|
|
15
|
+
= render :partial => 'form', :locals => {:f => f, :button => t('.update')}
|
16
|
+
|
17
|
+
h4= t('.create_section')
|
18
|
+
- role = TheRole.get(@role.the_role)
|
19
|
+
|
20
|
+
= form_tag(new_role_section_admin_role_path, :method => :post, :class => :new_action) do
|
21
|
+
= text_field_tag :section_name
|
22
|
+
= submit_tag t('.create_section')
|
23
|
+
|
24
|
+
h4= t('.create_access_policy')
|
25
|
+
|
26
|
+
- unless role.empty?
|
27
|
+
= form_tag(new_role_policy_admin_role_path(@role), :method => :post, :class => :new_action) do
|
28
|
+
= text_field_tag :section_policy
|
29
|
+
|
30
|
+
select name=:section_name
|
31
|
+
-role.each do |name, set|
|
32
|
+
option value=name
|
33
|
+
= name
|
34
|
+
|
35
|
+
input type=:submit value=t('.create_policy')
|
36
|
+
- else
|
37
|
+
p= t('.section_needs')
|
@@ -0,0 +1,12 @@
|
|
1
|
+
p= link_to raw(t('.back')), admin_roles_path
|
2
|
+
- @role.errors.each do |f, m|
|
3
|
+
p= m
|
4
|
+
|
5
|
+
.form
|
6
|
+
h5= t('.create')
|
7
|
+
= form_for(@role, :url => admin_roles_path) do |f|
|
8
|
+
label= t('.name')
|
9
|
+
p= f.text_field :name
|
10
|
+
label= t('.title')
|
11
|
+
p= f.text_field :title
|
12
|
+
= f.submit t('.new')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title= yield(:title)
|
5
|
+
= stylesheet_link_tag 'the_role/reset'
|
6
|
+
= stylesheet_link_tag 'the_role/style'
|
7
|
+
= stylesheet_link_tag 'the_role/headers'
|
8
|
+
= stylesheet_link_tag 'the_role/form'
|
9
|
+
|
10
|
+
= javascript_include_tag :jquery
|
11
|
+
= javascript_include_tag :jquery_ujs
|
12
|
+
= csrf_meta_tags
|
13
|
+
|
14
|
+
body
|
15
|
+
.body= yield
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
+
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
+
ru:
|
4
|
+
the_role:
|
5
|
+
name_presence: Установите имя роли
|
6
|
+
title_presence: Установите название роли
|
7
|
+
section_created: Правовая группа успешно создана
|
8
|
+
section_policy_created: В заданной группе успешно создана политика доступа
|
9
|
+
section_deleted: Политика доступа удалена
|
10
|
+
section_policy_deleted: Политика доступа удалена
|
11
|
+
section_name_is_wrong: Ошибочное название правовой группы
|
12
|
+
section_policy_wrong_name: Ошибочное название правовой политики
|
13
|
+
section_name_is_blank: Имя правовой группы оказалось пустым
|
14
|
+
section_exists: Правовая группа уже существует
|
15
|
+
role_created: Роль успешно создана
|
16
|
+
role_updated: Роль успешно обновлена
|
17
|
+
admin:
|
18
|
+
roles:
|
19
|
+
index:
|
20
|
+
list: Список ролей
|
21
|
+
delete: 'Удалить роль '
|
22
|
+
new: Создать новую роль
|
23
|
+
edit:
|
24
|
+
title: Редактирование роли
|
25
|
+
back: '← К списку ролей'
|
26
|
+
name: 'Название роли — '
|
27
|
+
create_section: Создать правовую группу
|
28
|
+
create_access_policy: Создать политику доступа
|
29
|
+
create_policy: Создать политику
|
30
|
+
section_needs: Создайте хотя бы одну правовую группу
|
31
|
+
update: Обновить
|
32
|
+
form:
|
33
|
+
destroy_section_confirm: Удалить правовую группу?
|
34
|
+
empty: Нет ни одной правовой группы
|
35
|
+
delete_policy_confirm: Удалить политику доступа?
|
36
|
+
delete: Удалить
|
37
|
+
new:
|
38
|
+
back: '← К списку ролей'
|
39
|
+
create: Создать новую роль
|
40
|
+
name: Имя роли (латиницей)
|
41
|
+
title: Название роли
|
42
|
+
new: Создать
|
data/config/routes.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
namespace :admin do
|
3
|
+
resources :roles do
|
4
|
+
member do
|
5
|
+
get :new
|
6
|
+
get :index
|
7
|
+
post :new_role_section
|
8
|
+
post :new_role_policy
|
9
|
+
end
|
10
|
+
resources :sections, :controller => :role_section do
|
11
|
+
member do
|
12
|
+
get :new_policy
|
13
|
+
delete :delete_policy
|
14
|
+
end
|
15
|
+
end#sections
|
16
|
+
end#policy
|
17
|
+
end#admin
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateRoles < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :roles do |t|
|
4
|
+
|
5
|
+
t.string :name
|
6
|
+
t.string :title
|
7
|
+
t.text :description
|
8
|
+
t.text :the_role, :null => false
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
drop_table :roles
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
namespace :db do
|
2
|
+
namespace :roles do
|
3
|
+
# rake db:roles:create
|
4
|
+
desc 'create roles'
|
5
|
+
task :create => :environment do
|
6
|
+
# ADMIN
|
7
|
+
role = {
|
8
|
+
:system => {
|
9
|
+
:administrator => true
|
10
|
+
}
|
11
|
+
}
|
12
|
+
Role.new(
|
13
|
+
:name => :administrator,
|
14
|
+
:title => 'Administrator',
|
15
|
+
:description => 'Role for administrator',
|
16
|
+
:the_role => role.to_yaml
|
17
|
+
).save!
|
18
|
+
puts 'Administrator'
|
19
|
+
|
20
|
+
# MODERATOR
|
21
|
+
role = {
|
22
|
+
:moderator => {
|
23
|
+
:pages => true
|
24
|
+
},
|
25
|
+
:markup => {
|
26
|
+
:html => true
|
27
|
+
}
|
28
|
+
}
|
29
|
+
Role.new(
|
30
|
+
:name => :user,
|
31
|
+
:title => 'Moderator of pages',
|
32
|
+
:description => "Moderator #1",
|
33
|
+
:the_role => role.to_yaml
|
34
|
+
).save!
|
35
|
+
puts 'Moderator of pages'
|
36
|
+
|
37
|
+
# USER
|
38
|
+
role = {
|
39
|
+
:users => {
|
40
|
+
:cabinet => true,
|
41
|
+
:update => true,
|
42
|
+
:avatar_upload => true
|
43
|
+
},
|
44
|
+
:profiles => {
|
45
|
+
:edit => true,
|
46
|
+
:update => true
|
47
|
+
},
|
48
|
+
:articles => {
|
49
|
+
:new => true,
|
50
|
+
:create => true,
|
51
|
+
:edit => true,
|
52
|
+
:update => true,
|
53
|
+
:destroy => true,
|
54
|
+
:tags => false
|
55
|
+
},
|
56
|
+
:pages => {
|
57
|
+
:new => true,
|
58
|
+
:create => true,
|
59
|
+
:edit => true,
|
60
|
+
:update => true,
|
61
|
+
:destroy => true,
|
62
|
+
:tags => true
|
63
|
+
},
|
64
|
+
:markup => {
|
65
|
+
:html => false
|
66
|
+
}
|
67
|
+
}
|
68
|
+
Role.new(
|
69
|
+
:name => :user,
|
70
|
+
:title => 'User',
|
71
|
+
:description => "Role for User",
|
72
|
+
:the_role => role.to_yaml
|
73
|
+
).save!
|
74
|
+
puts 'User'
|
75
|
+
|
76
|
+
# DEMO
|
77
|
+
role = {
|
78
|
+
:users => {
|
79
|
+
:cabinet => true,
|
80
|
+
:update => false,
|
81
|
+
:avatar_upload => false
|
82
|
+
},
|
83
|
+
:profiles => {
|
84
|
+
:edit => true,
|
85
|
+
:update => false
|
86
|
+
},
|
87
|
+
:articles => {
|
88
|
+
:new => true,
|
89
|
+
:show => true,
|
90
|
+
:create => false,
|
91
|
+
:edit => true,
|
92
|
+
:update => false,
|
93
|
+
:destroy => false,
|
94
|
+
:tags => false
|
95
|
+
},
|
96
|
+
:pages => {
|
97
|
+
:new => true,
|
98
|
+
:show => true,
|
99
|
+
:create => false,
|
100
|
+
:edit => true,
|
101
|
+
:update => false,
|
102
|
+
:destroy => false,
|
103
|
+
:tags => false
|
104
|
+
},
|
105
|
+
:markup => {
|
106
|
+
:html => false
|
107
|
+
}
|
108
|
+
}
|
109
|
+
Role.new(
|
110
|
+
:name => :user,
|
111
|
+
:title => 'Demo',
|
112
|
+
:description => "Demo user",
|
113
|
+
:the_role => role.to_yaml
|
114
|
+
).save!
|
115
|
+
puts 'Demo'
|
116
|
+
|
117
|
+
puts 'Roles created'
|
118
|
+
end#create
|
119
|
+
end#roles
|
120
|
+
end#db
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'the_role'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module TheRole
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
config.to_prepare do
|
7
|
+
Role.send :include, TheRole::RoleModel if the_class_exists? :Role
|
8
|
+
User.send :include, TheRole::UserModel if the_class_exists? :User
|
9
|
+
ApplicationController.send :include, TheRole::Requires if the_class_exists? :ApplicationController
|
10
|
+
end
|
11
|
+
end#Engine
|
12
|
+
end#TheRole
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Hash
|
2
|
+
def the_reset!(default_value= false)
|
3
|
+
base= self
|
4
|
+
base.each do |key, v|
|
5
|
+
if base[key.to_sym].is_a?(Hash)
|
6
|
+
base[key.to_sym]= base[key.to_sym].the_reset!(default_value)
|
7
|
+
else
|
8
|
+
base[key.to_sym]= default_value
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def the_merge!(hash= nil, default_value= true)
|
14
|
+
return self unless hash.is_a?(Hash)
|
15
|
+
base= self
|
16
|
+
hash.each do |key, v|
|
17
|
+
if base[key.to_sym].is_a?(Hash) && hash[key.to_sym].is_a?(Hash)
|
18
|
+
base[key.to_sym]= base[key.to_sym].the_merge!(hash[key.to_sym], default_value)
|
19
|
+
else
|
20
|
+
base[key.to_sym]= default_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
base.to_hash
|
24
|
+
end
|
25
|
+
end
|
data/lib/the_role.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require "the_role/version"
|
2
|
+
require "the_role/hash"
|
3
|
+
require "the_role/engine"
|
4
|
+
require "the_role/the_class_exists"
|
5
|
+
|
6
|
+
module TheRole
|
7
|
+
# include TheRole::Requires
|
8
|
+
# include TheRole::UserModel
|
9
|
+
# include TheRole::RoleModel
|
10
|
+
|
11
|
+
NAME_SYMBOLS = /^[a-zA-Z][a-zA-Z0-9_\-]*[a-zA-Z0-9]$/
|
12
|
+
|
13
|
+
# TheRole.get(@role.the_role)
|
14
|
+
def self.get str
|
15
|
+
hash = YAML::load(str)
|
16
|
+
hash ? hash : Hash.new
|
17
|
+
end
|
18
|
+
|
19
|
+
module UserModel
|
20
|
+
def self.included(base)
|
21
|
+
base.class_eval do
|
22
|
+
belongs_to :role
|
23
|
+
attr_accessible :role
|
24
|
+
# when user changed - @the_role should be reload
|
25
|
+
after_save { |user| user.instance_variable_set(:@the_role, nil) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def the_role
|
30
|
+
@the_role ||= self.role ? TheRole.get(self.role.the_role) : Hash.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def admin?
|
34
|
+
role = self.the_role[:system] ? self.the_role[:system][:administrator] : false
|
35
|
+
role && role.is_a?(TrueClass)
|
36
|
+
end
|
37
|
+
|
38
|
+
def moderator? section
|
39
|
+
role = self.the_role[:system] ? self.the_role[:moderator][section.to_sym] : false
|
40
|
+
role && role.is_a?(TrueClass)
|
41
|
+
end
|
42
|
+
|
43
|
+
# TRUE if user has role - administartor of system
|
44
|
+
# TRUE if user is moderator of this section (controller_name)
|
45
|
+
# FALSE when this section (or role) is nil
|
46
|
+
# return current value of role (TRUE|FALSE) if it exists
|
47
|
+
def has_role?(section, policy)
|
48
|
+
return true if self.admin?
|
49
|
+
return true if self.moderator? section
|
50
|
+
self.the_role[section.to_sym][policy.to_sym].is_a?(TrueClass) if self.the_role[section.to_sym] && self.the_role[section.to_sym][policy.to_sym]
|
51
|
+
end
|
52
|
+
|
53
|
+
# FALSE if object is nil
|
54
|
+
# If object is a USER - check for youself
|
55
|
+
# Check for owner field - :user_id
|
56
|
+
# Check for owner _object_ if owner field is not :user_id
|
57
|
+
def owner?(obj)
|
58
|
+
return false unless obj
|
59
|
+
return true if self.admin?
|
60
|
+
return true if self.moderator? obj.class.to_s.tableize # moderator? 'pages'
|
61
|
+
return self.id == obj.id if obj.is_a?(User)
|
62
|
+
return self.id == obj[:user_id] if obj[:user_id]
|
63
|
+
return self.id == obj[:user][:id] if obj[:user]
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end#UserModel
|
67
|
+
|
68
|
+
module RoleModel
|
69
|
+
def self.included(base)
|
70
|
+
base.class_eval do
|
71
|
+
has_many :users
|
72
|
+
validates :name, :presence => {:message => I18n.translate('the_role.name_presence')}
|
73
|
+
validates :title, :presence => {:message => I18n.translate('the_role.title_presence')}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end#RoleModel
|
77
|
+
|
78
|
+
# for application controller
|
79
|
+
# @the_role_object should be defined with before_filter
|
80
|
+
# @the_role_object = @page
|
81
|
+
module Requires
|
82
|
+
private
|
83
|
+
|
84
|
+
def the_role_access_denied
|
85
|
+
flash[:error] = t('the_role.access_denied')
|
86
|
+
redirect_to root_path
|
87
|
+
end
|
88
|
+
|
89
|
+
# before_filter :role_require
|
90
|
+
def the_role_require
|
91
|
+
the_role_access_denied unless current_user.has_role?(controller_name, action_name)
|
92
|
+
end
|
93
|
+
|
94
|
+
# before_filter :the_role_object
|
95
|
+
# define class variable for *the_owner_require* filter with Controller class name
|
96
|
+
# @the_role_object = @article
|
97
|
+
def the_role_object
|
98
|
+
variable_name = "@" + self.class.to_s.underscore.split('_').first.singularize
|
99
|
+
@the_role_object = self.instance_variable_get("@#{variable_name}")
|
100
|
+
end
|
101
|
+
|
102
|
+
# before_filter :owner_and_role_require
|
103
|
+
def the_owner_require
|
104
|
+
the_role_access_denied unless current_user.owner?(@the_role_object)
|
105
|
+
end
|
106
|
+
end#Requires
|
107
|
+
end#TheRole
|
data/the_role.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "the_role/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "the_role"
|
7
|
+
s.version = TheRole::VERSION
|
8
|
+
s.authors = ["Ilya N. Zykin"]
|
9
|
+
s.email = ["zykin-ilya@ya.ru"]
|
10
|
+
s.homepage = "https://github.com/the-teacher/the_role"
|
11
|
+
s.summary = %q{TheRole - simple, but powerful role system}
|
12
|
+
s.description = %q{TheRole - simple, but powerful role system for ROR applications}
|
13
|
+
|
14
|
+
s.rubyforge_project = "the_role"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: the_role
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.9
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ilya N. Zykin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-29 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: TheRole - simple, but powerful role system for ROR applications
|
15
|
+
email:
|
16
|
+
- zykin-ilya@ya.ru
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- MIT-LICENSE
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- app/assets/stylesheets/the_role/form.css
|
27
|
+
- app/assets/stylesheets/the_role/headers.css.scss
|
28
|
+
- app/assets/stylesheets/the_role/reset.css.scss
|
29
|
+
- app/assets/stylesheets/the_role/style.css.scss
|
30
|
+
- app/controllers/admin/role_section_controller.rb
|
31
|
+
- app/controllers/admin/roles_controller.rb
|
32
|
+
- app/views/admin/roles/_form.slim
|
33
|
+
- app/views/admin/roles/edit.slim
|
34
|
+
- app/views/admin/roles/index.slim
|
35
|
+
- app/views/admin/roles/new.slim
|
36
|
+
- app/views/layouts/the_role.slim
|
37
|
+
- config/locales/ru.yml
|
38
|
+
- config/routes.rb
|
39
|
+
- db/migrate/20111025025129_create_roles.rb
|
40
|
+
- lib/tasks/roles.rake
|
41
|
+
- lib/the_role.rb
|
42
|
+
- lib/the_role/engine.rb
|
43
|
+
- lib/the_role/hash.rb
|
44
|
+
- lib/the_role/the_class_exists.rb
|
45
|
+
- lib/the_role/version.rb
|
46
|
+
- the_role.gemspec
|
47
|
+
homepage: https://github.com/the-teacher/the_role
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project: the_role
|
67
|
+
rubygems_version: 1.8.6
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: TheRole - simple, but powerful role system
|
71
|
+
test_files: []
|