admission 0.2.8 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +2 -1
- data/README.md +24 -2
- data/examples/rails5_feudalism/.gitignore +19 -0
- data/examples/rails5_feudalism/.ruby-version +1 -0
- data/examples/rails5_feudalism/Gemfile +52 -0
- data/examples/rails5_feudalism/README.md +17 -0
- data/examples/rails5_feudalism/Rakefile +6 -0
- data/examples/rails5_feudalism/app/assets/config/manifest.js +3 -0
- data/examples/rails5_feudalism/app/assets/images/.keep +0 -0
- data/examples/rails5_feudalism/app/assets/javascripts/application.js +15 -0
- data/examples/rails5_feudalism/app/assets/stylesheets/application.css +15 -0
- data/examples/rails5_feudalism/app/assets/stylesheets/scaffolds.scss +84 -0
- data/examples/rails5_feudalism/app/controllers/application_controller.rb +13 -0
- data/examples/rails5_feudalism/app/controllers/concerns/.keep +0 -0
- data/examples/rails5_feudalism/app/controllers/users_controller.rb +75 -0
- data/examples/rails5_feudalism/app/helpers/application_helper.rb +2 -0
- data/examples/rails5_feudalism/app/jobs/application_job.rb +2 -0
- data/examples/rails5_feudalism/app/models/application_record.rb +3 -0
- data/examples/rails5_feudalism/app/models/concerns/.keep +0 -0
- data/examples/rails5_feudalism/app/models/person.rb +11 -0
- data/examples/rails5_feudalism/app/models/possession.rb +7 -0
- data/examples/rails5_feudalism/app/models/trait.rb +7 -0
- data/examples/rails5_feudalism/app/models/user.rb +17 -0
- data/examples/rails5_feudalism/app/models/user_status.rb +140 -0
- data/examples/rails5_feudalism/app/views/admission/forbidden.html.erb +14 -0
- data/examples/rails5_feudalism/app/views/layouts/application.html.erb +15 -0
- data/examples/rails5_feudalism/app/views/users/_form.html.erb +19 -0
- data/examples/rails5_feudalism/app/views/users/_privilege_row.html.erb +24 -0
- data/examples/rails5_feudalism/app/views/users/_privileges_list.html.erb +51 -0
- data/examples/rails5_feudalism/app/views/users/edit.html.erb +6 -0
- data/examples/rails5_feudalism/app/views/users/index.html.erb +25 -0
- data/examples/rails5_feudalism/app/views/users/new.html.erb +5 -0
- data/examples/rails5_feudalism/app/views/users/show.html.erb +4 -0
- data/examples/rails5_feudalism/bin/bundle +3 -0
- data/examples/rails5_feudalism/bin/rails +9 -0
- data/examples/rails5_feudalism/bin/rake +9 -0
- data/examples/rails5_feudalism/bin/setup +38 -0
- data/examples/rails5_feudalism/bin/spring +17 -0
- data/examples/rails5_feudalism/bin/update +29 -0
- data/examples/rails5_feudalism/bin/yarn +11 -0
- data/examples/rails5_feudalism/config.ru +5 -0
- data/examples/rails5_feudalism/config/application.rb +28 -0
- data/examples/rails5_feudalism/config/boot.rb +3 -0
- data/examples/rails5_feudalism/config/database.yml +85 -0
- data/examples/rails5_feudalism/config/environment.rb +5 -0
- data/examples/rails5_feudalism/config/environments/development.rb +49 -0
- data/examples/rails5_feudalism/config/environments/production.rb +82 -0
- data/examples/rails5_feudalism/config/environments/test.rb +36 -0
- data/examples/rails5_feudalism/config/initializers/application_controller_renderer.rb +8 -0
- data/examples/rails5_feudalism/config/initializers/assets.rb +14 -0
- data/examples/rails5_feudalism/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails5_feudalism/config/initializers/cookies_serializer.rb +5 -0
- data/examples/rails5_feudalism/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/rails5_feudalism/config/initializers/inflections.rb +16 -0
- data/examples/rails5_feudalism/config/initializers/mime_types.rb +4 -0
- data/examples/rails5_feudalism/config/initializers/wrap_parameters.rb +14 -0
- data/examples/rails5_feudalism/config/locales/en.yml +33 -0
- data/examples/rails5_feudalism/config/puma.rb +56 -0
- data/examples/rails5_feudalism/config/routes.rb +8 -0
- data/examples/rails5_feudalism/config/secrets.yml +32 -0
- data/examples/rails5_feudalism/config/spring.rb +6 -0
- data/examples/rails5_feudalism/db/migrate/20171018085629_create_users.rb +9 -0
- data/examples/rails5_feudalism/db/migrate/20171019082044_create_people.rb +9 -0
- data/examples/rails5_feudalism/db/migrate/20171019082055_create_possessions.rb +9 -0
- data/examples/rails5_feudalism/db/migrate/20171019082059_create_traits.rb +9 -0
- data/examples/rails5_feudalism/db/schema.rb +49 -0
- data/examples/rails5_feudalism/db/seeds.rb +7 -0
- data/examples/rails5_feudalism/lib/assets/.keep +0 -0
- data/examples/rails5_feudalism/lib/tasks/.keep +0 -0
- data/examples/rails5_feudalism/log/.keep +0 -0
- data/examples/rails5_feudalism/package.json +7 -0
- data/examples/rails5_feudalism/public/404.html +67 -0
- data/examples/rails5_feudalism/public/422.html +67 -0
- data/examples/rails5_feudalism/public/500.html +66 -0
- data/examples/rails5_feudalism/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/rails5_feudalism/public/apple-touch-icon.png +0 -0
- data/examples/rails5_feudalism/public/favicon.ico +0 -0
- data/examples/rails5_feudalism/public/robots.txt +1 -0
- data/examples/rails5_feudalism/test/application_system_test_case.rb +5 -0
- data/examples/rails5_feudalism/test/controllers/.keep +0 -0
- data/examples/rails5_feudalism/test/fixtures/.keep +0 -0
- data/examples/rails5_feudalism/test/fixtures/files/.keep +0 -0
- data/examples/rails5_feudalism/test/fixtures/people.yml +36 -0
- data/examples/rails5_feudalism/test/fixtures/possessions.yml +0 -0
- data/examples/rails5_feudalism/test/fixtures/traits.yml +0 -0
- data/examples/rails5_feudalism/test/fixtures/users.yml +0 -0
- data/examples/rails5_feudalism/test/helpers/.keep +0 -0
- data/examples/rails5_feudalism/test/models/.keep +0 -0
- data/examples/rails5_feudalism/test/models/user_status/rules_test.rb +152 -0
- data/examples/rails5_feudalism/test/models/user_status/user_status_test.rb +50 -0
- data/examples/rails5_feudalism/test/system/.keep +0 -0
- data/examples/rails5_feudalism/test/test_helper.rb +9 -0
- data/examples/rails5_feudalism/tmp/.keep +0 -0
- data/examples/rails5_feudalism/vendor/.keep +0 -0
- data/examples/rails5_feudalism/yarn.lock +7 -0
- data/lib/admission.rb +2 -0
- data/lib/admission/admission.rb +8 -2
- data/lib/admission/arbitration.rb +5 -0
- data/lib/admission/denied.rb +4 -5
- data/lib/admission/index.rb +59 -0
- data/lib/admission/minitest.rb +41 -0
- data/lib/admission/privilege.rb +13 -3
- data/lib/admission/rails.rb +8 -94
- data/lib/admission/rails/action_admission.rb +73 -0
- data/lib/admission/rails/controller_addon.rb +40 -0
- data/lib/admission/rails/scope_not_defined.rb +21 -0
- data/lib/admission/rails/scope_resolver.rb +46 -0
- data/lib/admission/resource_arbitration.rb +14 -9
- data/lib/admission/status.rb +11 -2
- data/lib/admission/tests.rb +59 -0
- data/lib/admission/version.rb +1 -1
- data/spec/integration/action_arbitrating_spec.rb +1 -1
- data/spec/integration/resource_arbitrating_spec.rb +1 -1
- data/spec/rspec_config.rb +13 -13
- data/spec/spec_helper.rb +10 -2
- data/spec/test_context/index.rb +0 -2
- data/spec/unit/arbitration_spec.rb +33 -0
- data/spec/unit/index_spec.rb +144 -0
- data/spec/unit/privilege/order_definer_spec.rb +1 -1
- data/spec/unit/privilege_spec.rb +22 -5
- data/spec/unit/rails/action_admission_spec.rb +188 -0
- data/spec/unit/rails/controller_addon_spec.rb +68 -0
- data/spec/unit/rails/scope_resolver_spec.rb +72 -0
- data/spec/unit/resource_arbitration_spec.rb +36 -1
- data/spec/unit/status_spec.rb +1 -1
- metadata +108 -5
- data/spec/integration/_helper.rb +0 -2
- data/spec/unit/_helper.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27226e2614355243e1aba9de00267129fbef0f70
|
4
|
+
data.tar.gz: f88d58e66dd6c602dd6ba2fe0ae78d6d951c2a36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0771d53e94477f7e59def1e84f8652d9e825f4d0bcdacd50be7a52185c82a87b65f7d2465abfaab41df43c1abb114d5d7198199d0dcc10ff74cd80bfea5c63aa
|
7
|
+
data.tar.gz: f6755cb896151dbcd63c80d4d101dab2656b2a39e38011632dcd562bc1abcc9ca9a06f374ce6f7cef0266eb255cbb9aa96075dc0a2b9654ff24249ae5b8fb57b
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.6
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,2 +1,24 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Admission
|
2
|
+
A system to manage user privileges. Heavily inspired by cancan.
|
3
|
+
|
4
|
+
### Is it "cancancancan"?
|
5
|
+
Yes, sort of. It's built around the same premise: having an index of rules, which resolve into entitling allowance for an user to a named action. But in Cancan you have to create your own system of privileges. Admission on the other hand is meant for the cases where you need the user to have multiple privileges, while having clear rules to resolve precedences between them.
|
6
|
+
|
7
|
+
The other thing that always bugged me about cancan (and was proven problematic in production) is that users' ability rules are loaded every time again, for every instance of the user record. I tried to introduce some kind of caching - only ended up making this library.
|
8
|
+
|
9
|
+
## Is it any good?
|
10
|
+
[yes](https://news.ycombinator.com/item?id=3067434)
|
11
|
+
|
12
|
+
## write-me please
|
13
|
+
### status
|
14
|
+
* used in production for a rails app
|
15
|
+
* tests are only "ok"
|
16
|
+
* documentation non-existent
|
17
|
+
|
18
|
+
### to-do list
|
19
|
+
- [ ] reuse arbitration instance
|
20
|
+
- [x] Admission::Denied must be able to tell the requested action and scope
|
21
|
+
- [x] minitest helpers
|
22
|
+
- [ ] rspec helpers
|
23
|
+
- [ ] test guides
|
24
|
+
- [ ] rails example
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore all logfiles and tempfiles.
|
11
|
+
/log/*
|
12
|
+
/tmp/*
|
13
|
+
!/log/.keep
|
14
|
+
!/tmp/.keep
|
15
|
+
|
16
|
+
/node_modules
|
17
|
+
/yarn-error.log
|
18
|
+
|
19
|
+
.byebug_history
|
@@ -0,0 +1 @@
|
|
1
|
+
2.3.3
|
@@ -0,0 +1,52 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
git_source(:github) do |repo_name|
|
4
|
+
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
|
5
|
+
"https://github.com/#{repo_name}.git"
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
10
|
+
gem 'rails', '~> 5.1.4'
|
11
|
+
# Use postgresql as the database for Active Record
|
12
|
+
gem 'pg', '~> 0.18'
|
13
|
+
# Use Puma as the app server
|
14
|
+
gem 'puma', '~> 3.7'
|
15
|
+
# Use SCSS for stylesheets
|
16
|
+
gem 'sass-rails', '~> 5.0'
|
17
|
+
# Use Uglifier as compressor for JavaScript assets
|
18
|
+
gem 'uglifier', '>= 1.3.0'
|
19
|
+
# See https://github.com/rails/execjs#readme for more supported runtimes
|
20
|
+
# gem 'therubyracer', platforms: :ruby
|
21
|
+
|
22
|
+
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
23
|
+
gem 'jbuilder', '~> 2.5'
|
24
|
+
# Use ActiveModel has_secure_password
|
25
|
+
# gem 'bcrypt', '~> 3.1.7'
|
26
|
+
|
27
|
+
# Use Capistrano for deployment
|
28
|
+
# gem 'capistrano-rails', group: :development
|
29
|
+
|
30
|
+
group :development, :test do
|
31
|
+
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
32
|
+
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
|
33
|
+
# Adds support for Capybara system testing and selenium driver
|
34
|
+
gem 'capybara', '~> 2.13'
|
35
|
+
gem 'selenium-webdriver'
|
36
|
+
end
|
37
|
+
|
38
|
+
group :development do
|
39
|
+
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
|
40
|
+
gem 'web-console', '>= 3.3.0'
|
41
|
+
gem 'listen', '>= 3.0.5', '< 3.2'
|
42
|
+
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
43
|
+
gem 'spring'
|
44
|
+
gem 'spring-watcher-listen', '~> 2.0.0'
|
45
|
+
end
|
46
|
+
|
47
|
+
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
48
|
+
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
49
|
+
|
50
|
+
|
51
|
+
########################################################################################################################
|
52
|
+
gem 'admission', path: File.expand_path('../../..', __FILE__)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Admission example: Rails app mimicking the mess of feudalism rules
|
2
|
+
|
3
|
+
## Goal
|
4
|
+
Show how to integrate Admission::ResourceArbitration into a rails app, that uses a complex case of privileges system. Each user (person) can have multiple privileges from multiple areas (countries), resulting in situations where one can do something in one area, but not in the other; where a privilege disallow doing a thing only in a single particular area. European feudalism has these wild and complex rules of inheritance, which is perfect to demonstrate how Admission's privileges one-way inheritance system deals with not that truly one-way real-world privilege inheritance system (you could've became a king -a sovereign- over a man to whom you're a vassal, resulting of insolvable situation: who's the lord to whom?).
|
5
|
+
|
6
|
+
## Integration to Rails
|
7
|
+
Admission is not meant to be only-rails privilege system. I'd like to include some helpers into the library though. This example then, is actually just a sandbox for me to find out the smoothest integration (controllers helpers, ActiveRecord to save privileges and more).
|
8
|
+
|
9
|
+
## to-do list
|
10
|
+
- [x] user privileges persistence
|
11
|
+
- [x] privileges system (popes, other christian patriarchs, emperors, kings, lords, ...)
|
12
|
+
- [ ] controller use of `#request!` and `Admission::Denied` handling
|
13
|
+
- [ ] god mode: status modification and transient admission plug-off
|
14
|
+
- [ ] nested resources allowance
|
15
|
+
- [ ] controllers helper for resources
|
16
|
+
- [ ] view usage of `#can?`
|
17
|
+
- [ ] model methods and attributes allowance (params permitting?)
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
|
5
|
+
// vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require rails-ujs
|
14
|
+
//= require jquery
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
|
6
|
+
* vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,84 @@
|
|
1
|
+
body {
|
2
|
+
background-color: #fff;
|
3
|
+
color: #333;
|
4
|
+
margin: 33px;
|
5
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
6
|
+
font-size: 13px;
|
7
|
+
line-height: 18px;
|
8
|
+
}
|
9
|
+
|
10
|
+
p, ol, ul, td {
|
11
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
12
|
+
font-size: 13px;
|
13
|
+
line-height: 18px;
|
14
|
+
}
|
15
|
+
|
16
|
+
pre {
|
17
|
+
background-color: #eee;
|
18
|
+
padding: 10px;
|
19
|
+
font-size: 11px;
|
20
|
+
}
|
21
|
+
|
22
|
+
a {
|
23
|
+
color: #000;
|
24
|
+
|
25
|
+
&:visited {
|
26
|
+
color: #666;
|
27
|
+
}
|
28
|
+
|
29
|
+
&:hover {
|
30
|
+
color: #fff;
|
31
|
+
background-color: #000;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
th {
|
36
|
+
padding-bottom: 5px;
|
37
|
+
}
|
38
|
+
|
39
|
+
td {
|
40
|
+
padding: 0 5px 7px;
|
41
|
+
}
|
42
|
+
|
43
|
+
div {
|
44
|
+
&.field, &.actions {
|
45
|
+
margin-bottom: 10px;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
#notice {
|
50
|
+
color: green;
|
51
|
+
}
|
52
|
+
|
53
|
+
.field_with_errors {
|
54
|
+
padding: 2px;
|
55
|
+
background-color: red;
|
56
|
+
display: table;
|
57
|
+
}
|
58
|
+
|
59
|
+
#error_explanation {
|
60
|
+
width: 450px;
|
61
|
+
border: 2px solid red;
|
62
|
+
padding: 7px 7px 0;
|
63
|
+
margin-bottom: 20px;
|
64
|
+
background-color: #f0f0f0;
|
65
|
+
|
66
|
+
h2 {
|
67
|
+
text-align: left;
|
68
|
+
font-weight: bold;
|
69
|
+
padding: 5px 5px 5px 15px;
|
70
|
+
font-size: 12px;
|
71
|
+
margin: -7px -7px 0;
|
72
|
+
background-color: #c00;
|
73
|
+
color: #fff;
|
74
|
+
}
|
75
|
+
|
76
|
+
ul li {
|
77
|
+
font-size: 12px;
|
78
|
+
list-style: square;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
label {
|
83
|
+
display: block;
|
84
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ApplicationController < ActionController::Base
|
2
|
+
protect_from_forgery with: :exception
|
3
|
+
|
4
|
+
require 'admission/rails'
|
5
|
+
include Admission::Rails::ControllerAddon
|
6
|
+
Admission::Rails.log_access = true
|
7
|
+
|
8
|
+
def request_admission! action, scope
|
9
|
+
@requested_admission = {action: action, scope: scope}
|
10
|
+
puts "ADMISSION: #{action} over #{scope}"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
|
3
|
+
before_action :set_user, only: %i[show edit update destroy]
|
4
|
+
before_action :prepare_privilege_params!, only: %i[create update]
|
5
|
+
|
6
|
+
def index
|
7
|
+
@users = User.all
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
end
|
12
|
+
|
13
|
+
def new
|
14
|
+
@user = User.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def edit
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
@user = User.new(user_params)
|
22
|
+
|
23
|
+
if @user.save
|
24
|
+
redirect_to @user, notice: 'User was successfully created.'
|
25
|
+
else
|
26
|
+
render :new
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
if @user.update(user_params)
|
32
|
+
redirect_to @user, notice: 'User was successfully updated.'
|
33
|
+
else
|
34
|
+
render :edit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy
|
39
|
+
@user.destroy
|
40
|
+
redirect_to users_url, notice: 'User was successfully destroyed.'
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
# Use callbacks to share common setup or constraints between actions.
|
45
|
+
def set_user
|
46
|
+
@user = User.find(params[:id])
|
47
|
+
end
|
48
|
+
|
49
|
+
# Never trust parameters from the scary internet, only allow the white list through.
|
50
|
+
def user_params
|
51
|
+
params.fetch(:user, {}).permit privileges: {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def prepare_privilege_params!
|
55
|
+
return unless params[:user]
|
56
|
+
|
57
|
+
privileges = params[:user][:privileges]
|
58
|
+
unless privileges
|
59
|
+
params[:user][:privileges] = nil
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
countries = (privileges[:country].presence || [])
|
64
|
+
names = privileges[:name].presence || []
|
65
|
+
|
66
|
+
list = countries.zip(names).map do |country, name|
|
67
|
+
name, level = name.split '-'
|
68
|
+
UserStatus.privilege_for_country name, level.presence, country
|
69
|
+
end
|
70
|
+
|
71
|
+
params[:user][:privileges] = UserStatus.dump_privileges list.compact
|
72
|
+
params[:user][:privileges].permit!
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Person < ApplicationRecord
|
2
|
+
COUNTRIES = %w[Moravia Bohemia Silesia].freeze
|
3
|
+
|
4
|
+
has_one :user, dependent: :destroy
|
5
|
+
has_many :possessions, dependent: :destroy
|
6
|
+
has_many :traits, dependent: :destroy
|
7
|
+
|
8
|
+
validates_presence_of :name
|
9
|
+
validates_inclusion_of :country, in: COUNTRIES
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class User < ApplicationRecord
|
2
|
+
|
3
|
+
belongs_to :person
|
4
|
+
|
5
|
+
validates_presence_of :person
|
6
|
+
|
7
|
+
scope :with_privilege, -> (names) {
|
8
|
+
names = [names] unless names.is_a? Array
|
9
|
+
names = names.map{|name| "'#{name}'"}.join ','
|
10
|
+
where.not(privileges: nil).where("\"users\".\"privileges\"->'_all' ?| ARRAY[#{names}]")
|
11
|
+
}
|
12
|
+
|
13
|
+
def status
|
14
|
+
@status ||= UserStatus.for_user(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|