thecore_auth_commons 2.2.0 → 2.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/ability.rb +5 -1
- data/app/models/action.rb +3 -0
- data/app/models/permission.rb +20 -0
- data/app/models/permission_role.rb +4 -0
- data/app/models/predicate.rb +3 -0
- data/app/models/role.rb +3 -1
- data/app/models/target.rb +3 -0
- data/app/models/user.rb +16 -5
- data/config/initializers/after_initialize_thecore_auth_commons.rb +1 -1
- data/config/locales/en.activerecord.yml +11 -0
- data/config/locales/it.activerecord.yml +36 -0
- data/config/locales/it.permissions.yml +10 -0
- data/db/migrate/20200306143408_create_users.rb +7 -7
- data/db/migrate/20200306151541_add_first_admin_user.rb +39 -0
- data/db/migrate/20200516215346_add_locked_to_user.rb +5 -0
- data/db/migrate/20200518082821_create_permissions.rb +48 -0
- data/lib/thecore_auth_commons.rb +3 -2
- data/lib/thecore_auth_commons/version.rb +1 -1
- metadata +12 -3
- data/config/locales/devise.en.yml +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac4e91fe3af44efcbd1803f1e86a3c94657a8c6a93a814a2ab4ffe15807eebcc
|
4
|
+
data.tar.gz: fb0c2d42d24bf3a69022ede32fa4ed93c601976e3df880313a2cd99ff6d72727
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a90d799e33bffeed7d09b5ef3cc7c94eff71981fb6239740b6d95c757c9b4605315067dc76d755ab5c6bb66c7774fed14189d2cc457ab941b568802a38faee9
|
7
|
+
data.tar.gz: 79f182bce1831a7958c777eb6aeac0ea13c7801d902f6e87cbba22ed2acceef0133647880f3df6ffe812b6c18e7dc921b3a25c173d756c96375764b64150cbef
|
data/app/models/ability.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'abilities/thecore_auth_commons'
|
3
2
|
|
4
3
|
class Ability
|
5
4
|
include CanCan::Ability
|
@@ -41,5 +40,10 @@ class Ability
|
|
41
40
|
self.merge const.new(user) if const.is_a? Class
|
42
41
|
end
|
43
42
|
end
|
43
|
+
# Overrides from the database defined permissions
|
44
|
+
::Permission.joins(roles: :users).where(users: {id: user.id}).order(:id).each do |permission|
|
45
|
+
# E.g. can :manage, :all
|
46
|
+
self.send(permission.predicate.name.to_sym, permission.action.name.to_sym, (permission.target.name.classify.constantize rescue permission.target.name.to_sym))
|
47
|
+
end
|
44
48
|
end
|
45
49
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Permission < ApplicationRecord
|
2
|
+
# REFERENCES
|
3
|
+
has_many :permission_roles, dependent: :destroy, inverse_of: :permission
|
4
|
+
has_many :roles, through: :permission_roles, inverse_of: :permissions
|
5
|
+
belongs_to :predicate, inverse_of: :permissions
|
6
|
+
belongs_to :action, inverse_of: :permissions
|
7
|
+
belongs_to :target, inverse_of: :permissions
|
8
|
+
|
9
|
+
# VALIDATIONS
|
10
|
+
validates :predicate_id, presence: true, uniqueness: {scope: [:action_id, :target_id]}
|
11
|
+
validates :action_id, presence: true
|
12
|
+
validates :target_id, presence: true
|
13
|
+
|
14
|
+
def display_name
|
15
|
+
p = (I18n.t "permissions.predicates.#{predicate.name}", default: predicate.name.titleize rescue nil)
|
16
|
+
a = (I18n.t "permissions.actions.#{action.name}", default: action.name.titleize rescue nil)
|
17
|
+
m = (I18n.t "activerecord.models.#{target.name}", default: target.name.titleize rescue nil)
|
18
|
+
[ p, a, m ].join(" ")
|
19
|
+
end
|
20
|
+
end
|
data/app/models/role.rb
CHANGED
@@ -4,8 +4,10 @@ class Role < ApplicationRecord
|
|
4
4
|
# REFERENCES
|
5
5
|
has_many :role_users, dependent: :destroy, inverse_of: :role
|
6
6
|
has_many :users, through: :role_users, inverse_of: :roles
|
7
|
+
has_many :permission_roles, dependent: :destroy, inverse_of: :role
|
8
|
+
has_many :permissions, through: :permission_roles, inverse_of: :roles
|
7
9
|
|
8
10
|
def display_name
|
9
|
-
I18n.t name.parameterize.underscore, default: name.titleize
|
11
|
+
(I18n.t name.parameterize.underscore, default: name.titleize rescue nil)
|
10
12
|
end
|
11
13
|
end
|
data/app/models/user.rb
CHANGED
@@ -2,6 +2,8 @@ class User < ApplicationRecord
|
|
2
2
|
# Include default devise modules. Others available are:
|
3
3
|
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
4
4
|
devise :database_authenticatable
|
5
|
+
devise :trackable
|
6
|
+
devise :validatable
|
5
7
|
# TODO: If it works, these must be added to another gem one which deal
|
6
8
|
# more with sessions
|
7
9
|
# devise :database_authenticatable
|
@@ -21,17 +23,26 @@ class User < ApplicationRecord
|
|
21
23
|
# Don't want admin == false if the current user is the only admin
|
22
24
|
record.errors.add(attr, I18n.t("validation.errors.cannot_unadmin_last_admin")) if record.admin_changed? && record.admin_was == true && User.where(admin: true).count == 1
|
23
25
|
end
|
24
|
-
|
26
|
+
validates_each :locked do |record, attr, value|
|
27
|
+
# Don't want locked == true if the current user is the only admin
|
28
|
+
record.errors.add(attr, I18n.t("validation.errors.cannot_lock_last_admin")) if record.locked_changed? && record.locked_was == false && User.where(locked: false).count == 1
|
29
|
+
end
|
30
|
+
|
25
31
|
def display_name
|
26
32
|
email
|
27
33
|
end
|
28
|
-
|
34
|
+
|
29
35
|
def has_role? role
|
30
|
-
roles.include? role
|
36
|
+
roles.include? role.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def authenticate password
|
40
|
+
puts "PASSWORD: #{password}"
|
41
|
+
self&.valid_password?(password) ? self : nil
|
31
42
|
end
|
32
|
-
|
43
|
+
|
33
44
|
protected
|
34
|
-
|
45
|
+
|
35
46
|
def check_password_and_confirmation_equal
|
36
47
|
errors.add(:password, I18n.t("validation.errors.password_and_confirm_must_be_the_same")) unless password == password_confirmation
|
37
48
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'thecore_auth_commons_actioncontroller_concerns'
|
2
2
|
|
3
|
+
# App Config
|
3
4
|
Rails.application.configure do
|
4
5
|
config.after_initialize do
|
5
6
|
# In development be sure to load all the namespaces
|
6
7
|
# in order to have working reflection and meta-programming.
|
7
|
-
#
|
8
8
|
if Rails.env.development?
|
9
9
|
Rails.configuration.eager_load_namespaces.each(&:eager_load!) if Rails.version.to_i == 5 #Rails 5
|
10
10
|
Zeitwerk::Loader.eager_load_all if Rails.version.to_i >= 6 #Rails 6
|
@@ -0,0 +1,36 @@
|
|
1
|
+
it:
|
2
|
+
activerecord:
|
3
|
+
models:
|
4
|
+
user:
|
5
|
+
one: Utente
|
6
|
+
other: Utenti
|
7
|
+
role:
|
8
|
+
one: Ruolo
|
9
|
+
other: Ruoli
|
10
|
+
permission:
|
11
|
+
one: Permesso
|
12
|
+
other: Permessi
|
13
|
+
attributes:
|
14
|
+
user:
|
15
|
+
email: E-Mail
|
16
|
+
username: Nome Utente
|
17
|
+
code: Codice
|
18
|
+
roles: Ruoli
|
19
|
+
admin: Amministratore?
|
20
|
+
created_at: Data di Creazione
|
21
|
+
locked: Bloccato?
|
22
|
+
third_party: Ente Terzo?
|
23
|
+
password: Password
|
24
|
+
password_confirmation: Conferma Password
|
25
|
+
role:
|
26
|
+
users: Utenti
|
27
|
+
name: Nome
|
28
|
+
permissions: Permessi
|
29
|
+
permission:
|
30
|
+
predicate: Predicato
|
31
|
+
action: Azione
|
32
|
+
model: Modello
|
33
|
+
descriptions:
|
34
|
+
user: In questa sezione dell'applicazione potete cercare nella lista degli utenti in diversi modi usando i filtri o ordinare la lista secondo diversi campi.
|
35
|
+
role: In questa sezione si possono creare dei ruoli da usare nell'RBAC gestito dai file abilities, per definire le autorizzazioni CRUD e non solo.
|
36
|
+
permission: Il predicato definisce se è un permesso di poter fare o non fare, l'azione è il tipo definisce cosa si possa fare o non fare, mentre il modello definisce su chi.
|
@@ -14,12 +14,12 @@ class CreateUsers < ActiveRecord::Migration[6.0]
|
|
14
14
|
## Rememberable
|
15
15
|
# t.datetime :remember_created_at
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
# Trackable
|
18
|
+
t.integer :sign_in_count, default: 0, null: false
|
19
|
+
t.datetime :current_sign_in_at
|
20
|
+
t.datetime :last_sign_in_at
|
21
|
+
t.string :current_sign_in_ip
|
22
|
+
t.string :last_sign_in_ip
|
23
23
|
|
24
24
|
## Confirmable
|
25
25
|
# t.string :confirmation_token
|
@@ -34,7 +34,7 @@ class CreateUsers < ActiveRecord::Migration[6.0]
|
|
34
34
|
|
35
35
|
|
36
36
|
# Uncomment below if timestamps were not included in your original model.
|
37
|
-
|
37
|
+
t.timestamps null: false
|
38
38
|
end
|
39
39
|
|
40
40
|
add_index :users, :email, unique: true
|
@@ -1,4 +1,43 @@
|
|
1
1
|
class AddFirstAdminUser < ActiveRecord::Migration[6.0]
|
2
|
+
class User < ApplicationRecord
|
3
|
+
# Include default devise modules. Others available are:
|
4
|
+
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
5
|
+
devise :database_authenticatable, :trackable, :validatable
|
6
|
+
# TODO: If it works, these must be added to another gem one which deal
|
7
|
+
# more with sessions
|
8
|
+
# devise :database_authenticatable
|
9
|
+
# devise :rememberable
|
10
|
+
# devise :trackable
|
11
|
+
# devise :validatable
|
12
|
+
# devise :timeoutable, timeout_in: 30.minutes
|
13
|
+
# REFERENCES
|
14
|
+
has_many :role_users, dependent: :destroy, inverse_of: :user
|
15
|
+
has_many :roles, through: :role_users, inverse_of: :users
|
16
|
+
# VALIDATIONS
|
17
|
+
validates :email, uniqueness: { case_sensitive: false }, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
|
18
|
+
validates :password, presence: true, on: :create
|
19
|
+
validates :password_confirmation, presence: true, on: :create
|
20
|
+
validate :check_password_and_confirmation_equal
|
21
|
+
validates_each :admin do |record, attr, value|
|
22
|
+
# Don't want admin == false if the current user is the only admin
|
23
|
+
record.errors.add(attr, I18n.t("validation.errors.cannot_unadmin_last_admin")) if record.admin_changed? && record.admin_was == true && User.where(admin: true).count == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def display_name
|
27
|
+
email
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_role? role
|
31
|
+
roles.include? role
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def check_password_and_confirmation_equal
|
37
|
+
errors.add(:password, I18n.t("validation.errors.password_and_confirm_must_be_the_same")) unless password == password_confirmation
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
2
41
|
def up
|
3
42
|
email = "admin@example.com"
|
4
43
|
User.reset_column_information
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class CreatePermissions < ActiveRecord::Migration[6.0]
|
2
|
+
def change
|
3
|
+
@values = {
|
4
|
+
predicates: %i[can cannot],
|
5
|
+
actions: %i[manage create read update destroy],
|
6
|
+
targets: ApplicationRecord.subclasses.map {|d| d.to_s.underscore}.to_a.unshift(:all)
|
7
|
+
}
|
8
|
+
|
9
|
+
def create_and_fill table
|
10
|
+
create_table table do |t|
|
11
|
+
t.string :name
|
12
|
+
t.bigint :lock_version
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
add_index table, :name, unique: true
|
17
|
+
model = table.to_s.classify.constantize
|
18
|
+
model.reset_column_information
|
19
|
+
model.upsert_all @values[table].map { |p| {name: p, created_at: Time.now, updated_at: Time.now} }, unique_by: [:name]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Predicates
|
23
|
+
create_and_fill :predicates
|
24
|
+
|
25
|
+
# Actions
|
26
|
+
create_and_fill :actions
|
27
|
+
|
28
|
+
# Targets
|
29
|
+
create_and_fill :targets
|
30
|
+
|
31
|
+
create_table :permissions do |t|
|
32
|
+
t.references :predicate, null: false, foreign_key: true
|
33
|
+
t.references :action, null: false, foreign_key: true
|
34
|
+
t.references :target, null: false, foreign_key: true
|
35
|
+
t.bigint :lock_version
|
36
|
+
|
37
|
+
t.timestamps
|
38
|
+
end
|
39
|
+
# Association table
|
40
|
+
create_table :permission_roles do |t|
|
41
|
+
t.references :role, null: false, foreign_key: true
|
42
|
+
t.references :permission, null: false, foreign_key: true
|
43
|
+
t.bigint :lock_version
|
44
|
+
|
45
|
+
t.timestamps
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/thecore_auth_commons.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thecore_auth_commons
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriele Tassoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -98,12 +98,19 @@ files:
|
|
98
98
|
- README.md
|
99
99
|
- Rakefile
|
100
100
|
- app/models/ability.rb
|
101
|
+
- app/models/action.rb
|
102
|
+
- app/models/permission.rb
|
103
|
+
- app/models/permission_role.rb
|
104
|
+
- app/models/predicate.rb
|
101
105
|
- app/models/role.rb
|
102
106
|
- app/models/role_user.rb
|
107
|
+
- app/models/target.rb
|
103
108
|
- app/models/user.rb
|
104
109
|
- config/initializers/after_initialize_thecore_auth_commons.rb
|
105
110
|
- config/initializers/devise.rb
|
106
|
-
- config/locales/
|
111
|
+
- config/locales/en.activerecord.yml
|
112
|
+
- config/locales/it.activerecord.yml
|
113
|
+
- config/locales/it.permissions.yml
|
107
114
|
- config/routes.rb
|
108
115
|
- db/migrate/20200306143408_create_users.rb
|
109
116
|
- db/migrate/20200306151046_add_admin_field_to_user.rb
|
@@ -112,6 +119,8 @@ files:
|
|
112
119
|
- db/migrate/20200306152816_create_role_users.rb
|
113
120
|
- db/migrate/20200306153125_add_lock_version_to_user.rb
|
114
121
|
- db/migrate/20200306153136_add_lock_version_to_role.rb
|
122
|
+
- db/migrate/20200516215346_add_locked_to_user.rb
|
123
|
+
- db/migrate/20200518082821_create_permissions.rb
|
115
124
|
- lib/abilities/thecore_auth_commons.rb
|
116
125
|
- lib/tasks/thecore_auth_commons_tasks.rake
|
117
126
|
- lib/thecore_auth_commons.rb
|
@@ -1,65 +0,0 @@
|
|
1
|
-
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
|
2
|
-
|
3
|
-
en:
|
4
|
-
devise:
|
5
|
-
confirmations:
|
6
|
-
confirmed: "Your email address has been successfully confirmed."
|
7
|
-
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
|
8
|
-
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
|
9
|
-
failure:
|
10
|
-
already_authenticated: "You are already signed in."
|
11
|
-
inactive: "Your account is not activated yet."
|
12
|
-
invalid: "Invalid %{authentication_keys} or password."
|
13
|
-
locked: "Your account is locked."
|
14
|
-
last_attempt: "You have one more attempt before your account is locked."
|
15
|
-
not_found_in_database: "Invalid %{authentication_keys} or password."
|
16
|
-
timeout: "Your session expired. Please sign in again to continue."
|
17
|
-
unauthenticated: "You need to sign in or sign up before continuing."
|
18
|
-
unconfirmed: "You have to confirm your email address before continuing."
|
19
|
-
mailer:
|
20
|
-
confirmation_instructions:
|
21
|
-
subject: "Confirmation instructions"
|
22
|
-
reset_password_instructions:
|
23
|
-
subject: "Reset password instructions"
|
24
|
-
unlock_instructions:
|
25
|
-
subject: "Unlock instructions"
|
26
|
-
email_changed:
|
27
|
-
subject: "Email Changed"
|
28
|
-
password_change:
|
29
|
-
subject: "Password Changed"
|
30
|
-
omniauth_callbacks:
|
31
|
-
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
|
32
|
-
success: "Successfully authenticated from %{kind} account."
|
33
|
-
passwords:
|
34
|
-
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
35
|
-
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
|
36
|
-
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
37
|
-
updated: "Your password has been changed successfully. You are now signed in."
|
38
|
-
updated_not_active: "Your password has been changed successfully."
|
39
|
-
registrations:
|
40
|
-
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
|
41
|
-
signed_up: "Welcome! You have signed up successfully."
|
42
|
-
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
|
43
|
-
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
|
44
|
-
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
|
45
|
-
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
|
46
|
-
updated: "Your account has been updated successfully."
|
47
|
-
updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again"
|
48
|
-
sessions:
|
49
|
-
signed_in: "Signed in successfully."
|
50
|
-
signed_out: "Signed out successfully."
|
51
|
-
already_signed_out: "Signed out successfully."
|
52
|
-
unlocks:
|
53
|
-
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
|
54
|
-
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
|
55
|
-
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
|
56
|
-
errors:
|
57
|
-
messages:
|
58
|
-
already_confirmed: "was already confirmed, please try signing in"
|
59
|
-
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
|
60
|
-
expired: "has expired, please request a new one"
|
61
|
-
not_found: "not found"
|
62
|
-
not_locked: "was not locked"
|
63
|
-
not_saved:
|
64
|
-
one: "1 error prohibited this %{resource} from being saved:"
|
65
|
-
other: "%{count} errors prohibited this %{resource} from being saved:"
|