app/models/concerns/enju_seed/enju_user.rb
module EnjuSeed
module EnjuUser
extend ActiveSupport::Concern
included do
scope :administrators, -> { joins(:role).where('roles.name = ?', 'Administrator') }
scope :librarians, -> { joins(:role).where('roles.name = ? OR roles.name = ?', 'Administrator', 'Librarian') }
scope :suspended, -> { where.not(locked_at: nil) }
has_one :profile, dependent: :nullify
if defined?(EnjuBiblio)
has_many :import_requests, dependent: :restrict_with_exception
has_many :picture_files, as: :picture_attachable, dependent: :destroy
end
has_one :user_has_role, dependent: :destroy
has_one :role, through: :user_has_role
accepts_nested_attributes_for :user_has_role
validates :username, presence: true, uniqueness: true, format: {
with: /\A[0-9A-Za-z][0-9A-Za-z_\-]*[0-9A-Za-z]\z/
}
validates :email, format: Devise::email_regexp, allow_blank: true, uniqueness: true
validates :expired_at, date: true, allow_blank: true
with_options if: :password_required? do |v|
v.validates_presence_of :password
v.validates_confirmation_of :password
v.validates_length_of :password, allow_blank: true,
within: Devise::password_length
end
before_validation :set_lock_information
before_destroy :check_role_before_destroy
before_save :check_expiration
after_create :set_confirmation
extend FriendlyId
friendly_id :username
strip_attributes only: :username
strip_attributes only: :email, allow_empty: true
attr_accessor :password_not_verified,
:update_own_account, :auto_generated_password,
:locked, :current_password #, :agent_id
paginates_per 10
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
# 有効期限切れのユーザを一括で使用不可にします。
def self.lock_expired_users
User.find_each do |user|
user.lock_access! if user.expired? && user.active_for_authentication?
end
end
# ユーザの情報をエクスポートします。
# @param [Hash] options
def self.export(options = {format: :text})
header = %w(
username
full_name
full_name_transcription
email
user_number
role
user_group
library
locale
locked
required_role
created_at
updated_at
expired_at
keyword_list
note
)
header += %w(
checkout_icalendar_token
save_checkout_history
) if defined? EnjuCirculation
header << "save_search_history" if defined? EnjuSearchLog
header << "share_bookmarks" if defined? EnjuBookmark
lines = []
User.find_each.map{|u|
line = []
line << u.username
line << u.try(:profile).try(:full_name)
line << u.try(:profile).try(:full_name_transcription)
line << u.email
line << u.try(:profile).try(:user_number)
line << u.role.try(:name)
line << u.try(:profile).try(:user_group).try(:name)
line << u.try(:profile).try(:library).try(:name)
line << u.try(:profile).try(:locale)
line << u.access_locked?
line << u.try(:profile).try(:required_role).try(:name)
line << u.created_at
line << u.updated_at
line << u.try(:profile).try(:expired_at)
line << u.try(:profile).try(:keyword_list).try(:split).try(:join, "//")
line << u.try(:profile).try(:note)
if defined? EnjuCirculation
line << u.try(:profile).try(:checkout_icalendar_token)
line << u.try(:profile).try(:save_checkout_history)
end
if defined? EnjuSearchLog
line << u.try(:profile).try(:save_search_history)
end
if defined? EnjuBookmark
line << u.try(:profile).try(:share_bookmarks)
end
lines << line
}
if options[:format] == :text
lines.map{|line| line.to_csv(col_sep: "\t")}.unshift(header.to_csv(col_sep: "\t")).join
else
lines
end
end
end
# ユーザにパスワードが必要かどうかをチェックします。
# @return [Boolean]
def password_required?
if Devise.mappings[:user].modules.include?(:database_authenticatable)
!persisted? || !password.nil? || !password_confirmation.nil?
end
end
# ユーザが特定の権限を持っているかどうかをチェックします。
# @param [String] role_in_question 権限名
# @return [Boolean]
def has_role?(role_in_question)
return false unless role
return true if role.name == role_in_question
case role.name
when 'Administrator'
return true
when 'Librarian'
return true if role_in_question == 'User'
else
false
end
end
# ユーザに使用不可の設定を反映させます。
def set_lock_information
if locked == '1' && active_for_authentication?
lock_access!
elsif locked == '0' && !active_for_authentication?
unlock_access!
end
end
def set_confirmation
if respond_to?(:confirm!)
reload
confirm!
end
end
# ユーザが有効期限切れかどうかをチェックし、期限切れであれば使用不可に設定します。
# @return [Object]
def check_expiration
return if has_role?('Administrator')
if expired_at
if expired_at.beginning_of_day < Time.zone.now.beginning_of_day
lock_access! if active_for_authentication?
end
end
end
# ユーザの削除前に、管理者ユーザが不在にならないかどうかをチェックします。
# @return [Object]
def check_role_before_destroy
if has_role?('Administrator')
if Role.find_by(name: 'Administrator').users.count == 1
raise username + 'This is the last administrator in this system.'
end
end
end
# ユーザに自動生成されたパスワードを設定します。
# @return [String]
def set_auto_generated_password
password = Devise.friendly_token[0..7]
self.password = password
self.password_confirmation = password
end
# ユーザが有効期限切れかどうかをチェックします。
# @return [Boolean]
def expired?
if expired_at
true if expired_at.beginning_of_day < Time.zone.now.beginning_of_day
end
end
# ユーザが管理者かどうかをチェックします。
# @return [Boolean]
def is_admin?
return true if has_role?('Administrator')
false
end
# ユーザがシステム上の最後のLibrarian権限ユーザかどうかをチェックします。
# @return [Boolean]
def last_librarian?
if has_role?('Librarian')
role = Role.find_by(name: 'Librarian')
return true if role.users.count == 1
false
end
end
def send_confirmation_instructions
Devise::Mailer.confirmation_instructions(self).deliver if email.present?
end
# ユーザが削除可能かどうかをチェックします。
# @param [User] current_user ユーザ
# @return [Object]
def deletable_by?(current_user)
return nil unless current_user
if defined?(EnjuCirculation)
# 未返却の資料のあるユーザを削除しようとした
if checkouts.count.positive?
errors.add(:base, I18n.t('user.this_user_has_checked_out_item'))
end
end
if has_role?('Librarian')
# 管理者以外のユーザが図書館員を削除しようとした。図書館員の削除は管理者しかできない
unless current_user.has_role?('Administrator')
errors.add(:base, I18n.t('user.only_administrator_can_destroy'))
end
# 最後の図書館員を削除しようとした
if last_librarian?
errors.add(:base, I18n.t('user.last_librarian'))
end
end
# 最後の管理者を削除しようとした
if has_role?('Administrator')
if Role.find_by(name: 'Administrator').users.count == 1
errors.add(:base, I18n.t('user.last_administrator'))
end
end
if errors[:base] == []
true
else
false
end
end
end
end
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string(255) default(""), not null
# encrypted_password :string(255) default(""), not null
# reset_password_token :string(255)
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0)
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :string(255)
# last_sign_in_ip :string(255)
# password_salt :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
# confirmation_sent_at :datetime
# unconfirmed_email :string(255)
# failed_attempts :integer default(0)
# unlock_token :string(255)
# locked_at :datetime
# authentication_token :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# username :string(255) not null
# library_id :integer default(1), not null
# user_group_id :integer default(1), not null
# expired_at :datetime
# required_role_id :integer default(1), not null
# note :text
# keyword_list :text
# user_number :string(255)
# state :string(255)
# locale :string(255)
# enju_access_key :string(255)
# save_checkout_history :boolean
# checkout_icalendar_token :string(255)
# share_bookmarks :boolean
# save_search_history :boolean
# answer_feed_token :string(255)
#