From 8d4ad7033373c0374e595102d4ae4d39805c5cf7 Mon Sep 17 00:00:00 2001 From: pabois <pierreandre.boissinot@noesya.coop> Date: Mon, 11 Oct 2021 10:55:08 +0200 Subject: [PATCH] roles --- app/models/user.rb | 3 +-- app/models/user/with_authentication.rb | 17 ++++++++++++++-- app/models/user/with_roles.rb | 27 ++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 app/models/user/with_roles.rb diff --git a/app/models/user.rb b/app/models/user.rb index 82621af0c..12c38e59d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -54,8 +54,7 @@ # class User < ApplicationRecord include WithAuthentication - - enum role: { visitor: 0, admin: 20, superadmin: 30 } + include WithRoles belongs_to :university belongs_to :language diff --git a/app/models/user/with_authentication.rb b/app/models/user/with_authentication.rb index 1ff79412d..1ddf9a019 100644 --- a/app/models/user/with_authentication.rb +++ b/app/models/user/with_authentication.rb @@ -3,15 +3,24 @@ module User::WithAuthentication included do devise :database_authenticatable, :registerable, :recoverable, :rememberable, - :timeoutable, :validatable, :confirmable, :trackable, :lockable, :two_factor_authenticatable + :timeoutable, :confirmable, :trackable, :lockable, :two_factor_authenticatable + # note : i do not use :validatable because of the non-uniqueness of the email. :validatable is replaced by the validation sequences below + has_one_time_password(encrypted: true) - validates_presence_of :first_name, :last_name, :email validates :role, presence: true + + validates_presence_of :first_name, :last_name, :email + validates_uniqueness_of :email, scope: :university_id, allow_blank: true, if: :will_save_change_to_email? + validates_format_of :email, with: Devise::email_regexp, allow_blank: true, if: :will_save_change_to_email? + validates_presence_of :password, if: :password_required? + validates_confirmation_of :password, if: :password_required? validate :password_complexity validates :mobile_phone, format: { with: /\A\+[0-9]+\z/ }, allow_blank: true + + before_validation :adjust_mobile_phone, :sanitize_fields def self.find_for_authentication(warden_conditions) @@ -64,6 +73,10 @@ module User::WithAuthentication self.mobile_phone = full_sanitizer.sanitize(self.mobile_phone)&.gsub('=', '') end + def password_required? + !persisted? || !password.nil? || !password_confirmation.nil? + end + def password_complexity # Regexp extracted from https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a return if password.blank? || password =~ /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#{Rails.application.config.allowed_special_chars}]).{#{Devise.password_length.first},#{Devise.password_length.last}}$/ diff --git a/app/models/user/with_roles.rb b/app/models/user/with_roles.rb new file mode 100644 index 000000000..992305e06 --- /dev/null +++ b/app/models/user/with_roles.rb @@ -0,0 +1,27 @@ +module User::WithRoles + extend ActiveSupport::Concern + + included do + attr_accessor :modified_by + + enum role: { visitor: 0, admin: 20, superadmin: 30 } + + scope :for_role, -> (role) { where(role: role) } + + before_validation :check_modifier_role + + def roles_managed + User.roles.map do |role_name, role_id| + next if role_id > User.roles[role] + role_name + end.compact + end + + protected + + def check_modifier_role + errors.add(:role, 'cannot be set to this role') if modified_by && !modified_by.roles_managed.include?(self.role) + end + + end +end -- GitLab