monarchy 1.1.5 → 2.0.0.pre.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +26 -0
- data/.gitignore +6 -6
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -3
- data/Gemfile.lock +54 -53
- data/README.md +1 -0
- data/app/models/monarchy/hierarchy.rb +0 -1
- data/docs/acts_as_hierarchy.md +45 -0
- data/docs/acts_as_resource.md +103 -0
- data/docs/acts_as_user.md +52 -0
- data/docs/configuration.md +54 -0
- data/docs/installation.md +30 -0
- data/docs/usage.md +22 -0
- data/dummy/.rspec +2 -0
- data/dummy/README.rdoc +28 -0
- data/dummy/Rakefile +7 -0
- data/dummy/app/assets/images/.keep +0 -0
- data/dummy/app/assets/javascripts/application.js +13 -0
- data/dummy/app/assets/stylesheets/application.css +15 -0
- data/dummy/app/controllers/application_controller.rb +6 -0
- data/dummy/app/controllers/concerns/.keep +0 -0
- data/dummy/app/helpers/application_helper.rb +3 -0
- data/dummy/app/mailers/.keep +0 -0
- data/dummy/app/models/.keep +0 -0
- data/dummy/app/models/concerns/.keep +0 -0
- data/dummy/app/models/member.rb +4 -0
- data/dummy/app/models/memo.rb +5 -0
- data/dummy/app/models/project.rb +12 -0
- data/dummy/app/models/resource.rb +4 -0
- data/dummy/app/models/role.rb +4 -0
- data/dummy/app/models/status.rb +5 -0
- data/dummy/app/models/task.rb +5 -0
- data/dummy/app/models/user.rb +4 -0
- data/dummy/app/views/layouts/application.html.erb +14 -0
- data/dummy/bin/bundle +4 -0
- data/dummy/bin/rails +5 -0
- data/dummy/bin/rake +5 -0
- data/dummy/bin/setup +30 -0
- data/dummy/config/application.rb +25 -0
- data/dummy/config/boot.rb +6 -0
- data/dummy/config/database.yml +10 -0
- data/dummy/config/environment.rb +6 -0
- data/dummy/config/environments/development.rb +42 -0
- data/dummy/config/environments/production.rb +80 -0
- data/dummy/config/environments/test.rb +43 -0
- data/dummy/config/initializers/assets.rb +12 -0
- data/dummy/config/initializers/backtrace_silencers.rb +8 -0
- data/dummy/config/initializers/cookies_serializer.rb +4 -0
- data/dummy/config/initializers/filter_parameter_logging.rb +5 -0
- data/dummy/config/initializers/inflections.rb +17 -0
- data/dummy/config/initializers/mime_types.rb +5 -0
- data/dummy/config/initializers/monarchy.rb +46 -0
- data/dummy/config/initializers/session_store.rb +4 -0
- data/dummy/config/initializers/wrap_parameters.rb +15 -0
- data/dummy/config/locales/en.yml +23 -0
- data/dummy/config/routes.rb +57 -0
- data/dummy/config/secrets.yml +22 -0
- data/dummy/config.ru +5 -0
- data/dummy/db/migrate/20160220215254_monarchy_create_users.rb +7 -0
- data/dummy/db/migrate/20160221132205_monarchy_create_hierarchies.rb +22 -0
- data/dummy/db/migrate/20160221133215_monarchy_create_memberships.rb +38 -0
- data/dummy/db/migrate/20160221142305_create_memo_resource.rb +8 -0
- data/dummy/db/migrate/20160221142309_create_project_resource.rb +8 -0
- data/dummy/db/migrate/20160221154113_create_resource_resource.rb +8 -0
- data/dummy/db/migrate/20160306124820_add_memo_to_resource.rb +6 -0
- data/dummy/db/migrate/20160502212213_parent_as_setup.rb +7 -0
- data/dummy/db/migrate/20160815163909_task_model.rb +10 -0
- data/dummy/db/migrate/20160818205534_status.rb +9 -0
- data/dummy/db/schema.rb +111 -0
- data/dummy/lib/assets/.keep +0 -0
- data/dummy/public/404.html +67 -0
- data/dummy/public/422.html +67 -0
- data/dummy/public/500.html +66 -0
- data/dummy/public/favicon.ico +0 -0
- data/dummy/spec +1 -0
- data/lib/generators/templates/config.rb +44 -7
- data/lib/monarchy/acts_as_hierarchy.rb +12 -11
- data/lib/monarchy/acts_as_member.rb +8 -17
- data/lib/monarchy/acts_as_resource.rb +35 -22
- data/lib/monarchy/acts_as_user.rb +51 -39
- data/lib/monarchy/exceptions.rb +135 -0
- data/lib/monarchy/tasks.rb +1 -1
- data/lib/monarchy/validators.rb +83 -0
- data/lib/monarchy/version.rb +1 -1
- data/lib/monarchy.rb +21 -8
- data/monarchy.gemspec +4 -4
- metadata +85 -13
@@ -0,0 +1,22 @@
|
|
1
|
+
class MonarchyCreateHierarchies < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :monarchy_hierarchies do |t|
|
4
|
+
t.integer :parent_id
|
5
|
+
t.integer :resource_id, null: false
|
6
|
+
t.string :resource_type, null: false
|
7
|
+
t.timestamps null: false
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :monarchy_hierarchy_hierarchies, id: false do |t|
|
11
|
+
t.integer :ancestor_id, null: false
|
12
|
+
t.integer :descendant_id, null: false
|
13
|
+
t.integer :generations, null: false
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :monarchy_hierarchy_hierarchies, [:ancestor_id, :descendant_id, :generations],
|
17
|
+
unique: true,
|
18
|
+
name: 'hierarchy_anc_desc_idx'
|
19
|
+
|
20
|
+
add_index :monarchy_hierarchy_hierarchies, [:descendant_id], name: 'hierarchy_desc_idx'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class MonarchyCreateMemberships < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :monarchy_members do |t|
|
4
|
+
t.belongs_to :user
|
5
|
+
t.belongs_to :hierarchy
|
6
|
+
t.timestamps null: false
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :monarchy_roles do |t|
|
10
|
+
t.string :name, null: false
|
11
|
+
t.integer :level, default: 0, null: false
|
12
|
+
t.integer :inherited_role_id
|
13
|
+
t.boolean :inherited, default: false, null: false
|
14
|
+
t.timestamps null: false
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table :monarchy_members_roles do |t|
|
18
|
+
t.belongs_to :role
|
19
|
+
t.belongs_to :member
|
20
|
+
t.timestamps null: false
|
21
|
+
end
|
22
|
+
|
23
|
+
add_index :monarchy_hierarchies, :parent_id
|
24
|
+
add_index :monarchy_hierarchies, :resource_id
|
25
|
+
|
26
|
+
add_index :monarchy_members, :hierarchy_id
|
27
|
+
add_index :monarchy_members, :user_id
|
28
|
+
|
29
|
+
add_index :monarchy_roles, :level
|
30
|
+
add_index :monarchy_roles, :inherited
|
31
|
+
add_index :monarchy_roles, :inherited_role_id
|
32
|
+
add_index :monarchy_roles, :name, unique: true
|
33
|
+
|
34
|
+
add_index :monarchy_members_roles, [:role_id, :member_id], unique: true
|
35
|
+
add_index :monarchy_members_roles, :member_id
|
36
|
+
add_index :monarchy_members_roles, :role_id
|
37
|
+
end
|
38
|
+
end
|
data/dummy/db/schema.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(version: 20160818205534) do
|
15
|
+
|
16
|
+
create_table "memos", force: :cascade do |t|
|
17
|
+
t.string "name"
|
18
|
+
t.datetime "created_at", null: false
|
19
|
+
t.datetime "updated_at", null: false
|
20
|
+
t.integer "project_id"
|
21
|
+
end
|
22
|
+
|
23
|
+
create_table "monarchy_hierarchies", force: :cascade do |t|
|
24
|
+
t.integer "parent_id"
|
25
|
+
t.integer "resource_id", null: false
|
26
|
+
t.string "resource_type", null: false
|
27
|
+
t.datetime "created_at", null: false
|
28
|
+
t.datetime "updated_at", null: false
|
29
|
+
end
|
30
|
+
|
31
|
+
add_index "monarchy_hierarchies", ["parent_id"], name: "index_monarchy_hierarchies_on_parent_id"
|
32
|
+
add_index "monarchy_hierarchies", ["resource_id"], name: "index_monarchy_hierarchies_on_resource_id"
|
33
|
+
|
34
|
+
create_table "monarchy_hierarchy_hierarchies", id: false, force: :cascade do |t|
|
35
|
+
t.integer "ancestor_id", null: false
|
36
|
+
t.integer "descendant_id", null: false
|
37
|
+
t.integer "generations", null: false
|
38
|
+
end
|
39
|
+
|
40
|
+
add_index "monarchy_hierarchy_hierarchies", ["ancestor_id", "descendant_id", "generations"], name: "hierarchy_anc_desc_idx", unique: true
|
41
|
+
add_index "monarchy_hierarchy_hierarchies", ["descendant_id"], name: "hierarchy_desc_idx"
|
42
|
+
|
43
|
+
create_table "monarchy_members", force: :cascade do |t|
|
44
|
+
t.integer "user_id"
|
45
|
+
t.integer "hierarchy_id"
|
46
|
+
t.datetime "created_at", null: false
|
47
|
+
t.datetime "updated_at", null: false
|
48
|
+
end
|
49
|
+
|
50
|
+
add_index "monarchy_members", ["hierarchy_id"], name: "index_monarchy_members_on_hierarchy_id"
|
51
|
+
add_index "monarchy_members", ["user_id"], name: "index_monarchy_members_on_user_id"
|
52
|
+
|
53
|
+
create_table "monarchy_members_roles", force: :cascade do |t|
|
54
|
+
t.integer "role_id"
|
55
|
+
t.integer "member_id"
|
56
|
+
t.datetime "created_at", null: false
|
57
|
+
t.datetime "updated_at", null: false
|
58
|
+
end
|
59
|
+
|
60
|
+
add_index "monarchy_members_roles", ["member_id"], name: "index_monarchy_members_roles_on_member_id"
|
61
|
+
add_index "monarchy_members_roles", ["role_id", "member_id"], name: "index_monarchy_members_roles_on_role_id_and_member_id", unique: true
|
62
|
+
add_index "monarchy_members_roles", ["role_id"], name: "index_monarchy_members_roles_on_role_id"
|
63
|
+
|
64
|
+
create_table "monarchy_roles", force: :cascade do |t|
|
65
|
+
t.string "name", null: false
|
66
|
+
t.integer "level", default: 0, null: false
|
67
|
+
t.integer "inherited_role_id"
|
68
|
+
t.boolean "inherited", default: false, null: false
|
69
|
+
t.datetime "created_at", null: false
|
70
|
+
t.datetime "updated_at", null: false
|
71
|
+
end
|
72
|
+
|
73
|
+
add_index "monarchy_roles", ["inherited"], name: "index_monarchy_roles_on_inherited"
|
74
|
+
add_index "monarchy_roles", ["inherited_role_id"], name: "index_monarchy_roles_on_inherited_role_id"
|
75
|
+
add_index "monarchy_roles", ["level"], name: "index_monarchy_roles_on_level"
|
76
|
+
add_index "monarchy_roles", ["name"], name: "index_monarchy_roles_on_name", unique: true
|
77
|
+
|
78
|
+
create_table "projects", force: :cascade do |t|
|
79
|
+
t.string "name"
|
80
|
+
t.datetime "created_at", null: false
|
81
|
+
t.datetime "updated_at", null: false
|
82
|
+
t.integer "resource_id"
|
83
|
+
end
|
84
|
+
|
85
|
+
create_table "resources", force: :cascade do |t|
|
86
|
+
t.string "name"
|
87
|
+
t.datetime "created_at", null: false
|
88
|
+
t.datetime "updated_at", null: false
|
89
|
+
end
|
90
|
+
|
91
|
+
create_table "statuses", force: :cascade do |t|
|
92
|
+
t.string "name"
|
93
|
+
t.integer "project_id"
|
94
|
+
t.datetime "created_at", null: false
|
95
|
+
t.datetime "updated_at", null: false
|
96
|
+
end
|
97
|
+
|
98
|
+
create_table "tasks", force: :cascade do |t|
|
99
|
+
t.string "name"
|
100
|
+
t.integer "resource_id"
|
101
|
+
t.string "resource_type"
|
102
|
+
t.datetime "created_at", null: false
|
103
|
+
t.datetime "updated_at", null: false
|
104
|
+
end
|
105
|
+
|
106
|
+
create_table "users", force: :cascade do |t|
|
107
|
+
t.datetime "created_at", null: false
|
108
|
+
t.datetime "updated_at", null: false
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
File without changes
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/404.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
62
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
63
|
+
</div>
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
65
|
+
</div>
|
66
|
+
</body>
|
67
|
+
</html>
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/422.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>The change you wanted was rejected.</h1>
|
62
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
63
|
+
</div>
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
65
|
+
</div>
|
66
|
+
</body>
|
67
|
+
</html>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/500.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>We're sorry, but something went wrong.</h1>
|
62
|
+
</div>
|
63
|
+
<p>If you are the application owner check the logs for more information.</p>
|
64
|
+
</div>
|
65
|
+
</body>
|
66
|
+
</html>
|
File without changes
|
data/dummy/spec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
dummy/../spec
|
@@ -1,11 +1,48 @@
|
|
1
1
|
Monarchy.configure do |config|
|
2
|
-
|
3
|
-
config.default_role.level = 0
|
4
|
-
config.default_role.inherited = false
|
2
|
+
# REQUIRED SETTINGS
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
#
|
4
|
+
# You have to define which role will be the default one (read only) during inheritance.
|
5
|
+
# Example role: :guest
|
6
|
+
# Real case on resources:
|
7
|
+
# project: (you have no roles)
|
8
|
+
# section: (you have no roles)
|
9
|
+
# task: (you have a member role here)
|
10
|
+
# When you ask for user.roles_for(project) you will get a default role (:guest)
|
11
|
+
# in case when member role has inherited flag set to true
|
12
|
+
# Remember to create that role before setting it up eg:
|
13
|
+
# Monarchy::Role.create(name: :guest, inherited: false, level: 0)
|
14
|
+
config.inherited_default_role = nil # symbol
|
9
15
|
|
10
|
-
#
|
16
|
+
# You have to define user class name or an actor class which respond to acts_as_user in your model.
|
17
|
+
# Example of model:
|
18
|
+
# class User < ActiveRecord::Base
|
19
|
+
# acts_as_user
|
20
|
+
# end
|
21
|
+
config.user_class_name = '' # string
|
22
|
+
|
23
|
+
|
24
|
+
# OPTIONAL SETTINGS
|
25
|
+
|
26
|
+
# If you want to override Member or Role class you have add correct actors to class definition
|
27
|
+
# Available: acts_as_member, acts_as_role, acts_as_hierarchy
|
28
|
+
# Example:
|
29
|
+
# class Member < ActiveRecord::Base
|
30
|
+
# acts_as_member
|
31
|
+
# end
|
32
|
+
config.role_class_name = 'Monarchy::Role' # string
|
33
|
+
config.member_class_name = 'Monarchy::Member' # string
|
34
|
+
config.hierarchy_class_name = 'Monarchy::Hierarchy' # string
|
35
|
+
|
36
|
+
|
37
|
+
# If this option is setup to true all members bellow the destroying one, will be deleted.
|
38
|
+
config.members_access_revoke = false # boolean
|
39
|
+
|
40
|
+
# Set the revoke strategy using during '#revoke_role!' method
|
41
|
+
# Available: :revoke_member, :revoke_access
|
42
|
+
# Default: :revoke_member
|
43
|
+
# Info:
|
44
|
+
# :revoke_member - after revoking the last role from user's member remove the member
|
45
|
+
# :revoke_access - after revoking the last role from user's member
|
46
|
+
# remove the member, and all members bellow which belongs to the user
|
47
|
+
config.revoke_strategy = :revoke_member # symbol
|
11
48
|
end
|
@@ -6,10 +6,13 @@ module Monarchy
|
|
6
6
|
module ClassMethods
|
7
7
|
def acts_as_hierarchy
|
8
8
|
extend Monarchy::ActsAsHierarchy::SupportMethods
|
9
|
+
self.table_name = 'monarchy_hierarchies'
|
9
10
|
has_closure_tree dependent: :destroy
|
10
11
|
|
11
12
|
has_many :members, class_name: "::#{Monarchy.member_class}", dependent: :destroy
|
13
|
+
has_many :users, through: :members, class_name: "::#{Monarchy.user_class}"
|
12
14
|
belongs_to :resource, polymorphic: true
|
15
|
+
|
13
16
|
include_scopes
|
14
17
|
|
15
18
|
validates :resource_type, presence: true
|
@@ -21,21 +24,23 @@ module Monarchy
|
|
21
24
|
private
|
22
25
|
|
23
26
|
def include_scopes
|
24
|
-
scope :in, (lambda do |
|
25
|
-
|
27
|
+
scope :in, (lambda do |hierarchy, descendants = true|
|
28
|
+
Monarchy::Validators.hierarchy(hierarchy)
|
29
|
+
where(id: descendants ? hierarchy.descendants : hierarchy.children)
|
26
30
|
end)
|
27
31
|
|
28
32
|
scope :accessible_for, (lambda do |user|
|
29
|
-
|
33
|
+
Monarchy::Validators.user(user)
|
34
|
+
where(id: accessible_roots(user).union(accessible_leaves(user)))
|
30
35
|
end)
|
31
36
|
end
|
32
37
|
|
33
38
|
def accessible_roots(user)
|
34
|
-
joins('INNER JOIN "monarchy_hierarchy_hierarchies" ON '\
|
39
|
+
unscoped.joins('INNER JOIN "monarchy_hierarchy_hierarchies" ON '\
|
35
40
|
'"monarchy_hierarchies"."id" = "monarchy_hierarchy_hierarchies"."ancestor_id"')
|
36
|
-
|
41
|
+
.joins('INNER JOIN "monarchy_members" ON '\
|
37
42
|
'"monarchy_members"."hierarchy_id" = "monarchy_hierarchy_hierarchies"."descendant_id"')
|
38
|
-
|
43
|
+
.where(monarchy_members: { user_id: user.id }).distinct
|
39
44
|
end
|
40
45
|
|
41
46
|
def accessible_leaves(user)
|
@@ -48,16 +53,12 @@ module Monarchy
|
|
48
53
|
)
|
49
54
|
end
|
50
55
|
|
51
|
-
def default_role_name
|
52
|
-
Monarchy.configuration.default_role.name
|
53
|
-
end
|
54
|
-
|
55
56
|
def descendant_leaves_for_user(user)
|
56
57
|
descendant_leaves.joins(members: [:roles]).where(monarchy_members: { user_id: user.id })
|
57
58
|
end
|
58
59
|
|
59
60
|
def descendant_leaves
|
60
|
-
joins('INNER JOIN "monarchy_hierarchy_hierarchies" ON "monarchy_hierarchies"."id" =' \
|
61
|
+
unscoped.joins('INNER JOIN "monarchy_hierarchy_hierarchies" ON "monarchy_hierarchies"."id" =' \
|
61
62
|
'"monarchy_hierarchy_hierarchies"."descendant_id"')
|
62
63
|
end
|
63
64
|
end
|
@@ -23,13 +23,13 @@ module Monarchy
|
|
23
23
|
module SupportMethods
|
24
24
|
def include_scopes
|
25
25
|
scope :accessible_for, (lambda do |user|
|
26
|
-
|
26
|
+
Monarchy::Validators.user(user)
|
27
|
+
where(hierarchy: Monarchy.hierarchy_class.accessible_for(user))
|
27
28
|
end)
|
28
29
|
end
|
29
30
|
|
30
31
|
def include_callbacks
|
31
|
-
|
32
|
-
after_destroy :revoke_access, if: :member_force_revoke?
|
32
|
+
after_destroy :revoke_access, if: :members_access_revoke?
|
33
33
|
end
|
34
34
|
|
35
35
|
def include_validators
|
@@ -43,33 +43,24 @@ module Monarchy
|
|
43
43
|
has_many :roles, -> { order(level: :desc) }, through: :members_roles, class_name: "::#{Monarchy.role_class}"
|
44
44
|
|
45
45
|
belongs_to :user, class_name: "::#{Monarchy.user_class}"
|
46
|
-
belongs_to :hierarchy, class_name:
|
46
|
+
belongs_to :hierarchy, class_name: "::#{Monarchy.hierarchy_class}"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
module InstanceMethods
|
51
51
|
def resource=(resource)
|
52
|
+
Monarchy::Validators.resource(resource)
|
52
53
|
self.hierarchy = resource.hierarchy unless hierarchy
|
53
54
|
end
|
54
55
|
|
55
56
|
private
|
56
57
|
|
57
58
|
def revoke_access
|
58
|
-
user.revoke_access(resource, resource.hierarchy.
|
59
|
+
user.revoke_access(resource, resource.hierarchy.descendants)
|
59
60
|
end
|
60
61
|
|
61
|
-
def
|
62
|
-
Monarchy.configuration.
|
63
|
-
end
|
64
|
-
|
65
|
-
def set_default_role
|
66
|
-
roles = self.roles
|
67
|
-
roles << Monarchy.role_class.find_or_create_by(
|
68
|
-
name: Monarchy.configuration.default_role.name,
|
69
|
-
inherited: Monarchy.configuration.default_role.inherited,
|
70
|
-
level: Monarchy.configuration.default_role.level
|
71
|
-
)
|
72
|
-
self.roles = roles.uniq
|
62
|
+
def members_access_revoke?
|
63
|
+
Monarchy.configuration.members_access_revoke
|
73
64
|
end
|
74
65
|
|
75
66
|
def hierarchy_or_resource
|