thecore_auth_commons 2.2.2 → 2.3.0
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 +13 -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 +1 -1
- 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 +1 -0
- data/lib/thecore_auth_commons/version.rb +1 -1
- metadata +12 -5
- data/config/locales/devise.en.yml +0 -65
- data/config/locales/en.devise.custom.yml +0 -19
- data/config/locales/it.devise.custom.yml +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 502bc9400ed04c0c637b9298e1997c8f310535d76edb06324bf495b044e32267
|
4
|
+
data.tar.gz: bc1d951e09c235f4907a6f67bf287fdb3d4703f47b4b32c4662e0d2b2b95c337
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cad4cd8fb0864c65afb9b14dfcafe7f89209f8607d608de029ed8128f470f42c57c6dcdee1aa0bc2706e4f42a83119ce7c3e87dd50e47fdea316b90ae4a3729
|
7
|
+
data.tar.gz: 9de160e2037cae69e75dd41a520b6bad75ab7445136a337328288dd3bcd3e1e15cbd91e0bfd080a7232908f57958cf658df298068052bb9cb0164d267fbf87ab
|
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 unless user.blank?
|
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
@@ -23,17 +23,25 @@ class User < ApplicationRecord
|
|
23
23
|
# Don't want admin == false if the current user is the only admin
|
24
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
|
25
25
|
end
|
26
|
-
|
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
|
+
|
27
31
|
def display_name
|
28
32
|
email
|
29
33
|
end
|
30
|
-
|
34
|
+
|
31
35
|
def has_role? role
|
32
|
-
roles.include? role
|
36
|
+
roles.include? role.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def authenticate password
|
40
|
+
self&.valid_password?(password) ? self : nil
|
33
41
|
end
|
34
|
-
|
42
|
+
|
35
43
|
protected
|
36
|
-
|
44
|
+
|
37
45
|
def check_password_and_confirmation_equal
|
38
46
|
errors.add(:password, I18n.t("validation.errors.password_and_confirm_must_be_the_same")) unless password == password_confirmation
|
39
47
|
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.
|
@@ -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.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriele Tassoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -98,14 +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/
|
107
|
-
- config/locales/
|
108
|
-
- config/locales/it.
|
111
|
+
- config/locales/en.activerecord.yml
|
112
|
+
- config/locales/it.activerecord.yml
|
113
|
+
- config/locales/it.permissions.yml
|
109
114
|
- config/routes.rb
|
110
115
|
- db/migrate/20200306143408_create_users.rb
|
111
116
|
- db/migrate/20200306151046_add_admin_field_to_user.rb
|
@@ -114,6 +119,8 @@ files:
|
|
114
119
|
- db/migrate/20200306152816_create_role_users.rb
|
115
120
|
- db/migrate/20200306153125_add_lock_version_to_user.rb
|
116
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
|
117
124
|
- lib/abilities/thecore_auth_commons.rb
|
118
125
|
- lib/tasks/thecore_auth_commons_tasks.rake
|
119
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:"
|
@@ -1,19 +0,0 @@
|
|
1
|
-
en:
|
2
|
-
devise:
|
3
|
-
failure:
|
4
|
-
user:
|
5
|
-
invalid: Incorrect login credentials.
|
6
|
-
not_found_in_database: Incorrect login credentials.
|
7
|
-
mailer:
|
8
|
-
password_changed_instructions:
|
9
|
-
greeting: Welcome %{recipient}!
|
10
|
-
instruction: We sent you this email to inform about password change.
|
11
|
-
instruction_2: If you didn't changed password, we ask you to contact our customer service, please.
|
12
|
-
shared:
|
13
|
-
links:
|
14
|
-
sign_out: Log out
|
15
|
-
descriptions:
|
16
|
-
current_password_needed: (we need your current password to confirm your changes)
|
17
|
-
leave_blank: (leave blank if you don't want to change it)
|
18
|
-
validations:
|
19
|
-
minimum_length: "%{length} characters minimum"
|
@@ -1,19 +0,0 @@
|
|
1
|
-
it:
|
2
|
-
devise:
|
3
|
-
failure:
|
4
|
-
user:
|
5
|
-
invalid: Credenziali di accesso errate.
|
6
|
-
not_found_in_database: Credenziali di accesso errate.
|
7
|
-
mailer:
|
8
|
-
password_changed_instructions:
|
9
|
-
greeting: Benvenuto %{recipient}!
|
10
|
-
instruction: Le abbiamo inviato questa email per notificarle il fatto che la sua password è stata cambiata.
|
11
|
-
instruction_2: Se non è stato lei a richiedere la modifica della password, la preghiamo di contattare il servizio clienti.
|
12
|
-
shared:
|
13
|
-
links:
|
14
|
-
sign_out: Esci
|
15
|
-
descriptions:
|
16
|
-
current_password_needed: (è necessario inserire la password corrente per autorizzare la modifica)
|
17
|
-
leave_blank: (lasciare vuota se non la si vuole modificare)
|
18
|
-
validations:
|
19
|
-
minimum_length: la lunghezza minima è di %{length} caratteri
|