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