You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.1 KiB
128 lines
3.1 KiB
require_relative '../../lib/edu/units'
|
|
|
|
class User < ApplicationRecord
|
|
# 邮箱验证
|
|
VALID_EMAIL_REGEX = /\A[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/i
|
|
# 手机号验证
|
|
VALID_PHONE_REGEX = /\A1\d{10}\z/
|
|
# 身份证验证
|
|
VALID_NUMBER_REGEX = /(\A[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^([A-Z]\d{6,10}(\(\w{1}\))?)\z)/
|
|
SESSION_ACTION = '_educoder_session'
|
|
validates :email, format: { with: VALID_EMAIL_REGEX }
|
|
validates :password, length: { minimum: 5, maximum: 50 }
|
|
validates_uniqueness_of :email, :if => Proc.new { |user| user.email_changed? && user.email.present? }, case_sensitive: false
|
|
before_save :update_hashed_password
|
|
scope :active, lambda { where(status: USER_STATUS::STATUS_ACTIVE) }
|
|
module USER_STATUS
|
|
STATUS_INVALID = 0
|
|
STATUS_ACTIVE = 1
|
|
STATUS_LOCKED = 2
|
|
end
|
|
def logged?
|
|
true
|
|
end
|
|
module USER_TYPE
|
|
ANONYMOUS = "Anonymous"
|
|
USER = "User"
|
|
end
|
|
|
|
def self.anonymous
|
|
User.find_by(user_type:USER_TYPE::ANONYMOUS)
|
|
end
|
|
|
|
def self.current=(user)
|
|
RequestStore.store[:current_user] = user
|
|
end
|
|
|
|
def self.current
|
|
RequestStore.store[:current_user]
|
|
end
|
|
def self.try_to_session_id(key)
|
|
user = Token.find_active_user(User::SESSION_ACTION, key)
|
|
user.update(last_login_on: Time.now) if user
|
|
user
|
|
end
|
|
def self.try_to_autologin(key)
|
|
user = Token.find_active_user('autologin', key)
|
|
user.update(last_login_on: Time.now) if user
|
|
user
|
|
end
|
|
|
|
def delete_session_token(value)
|
|
Token.where(:user_id => id, :action => 'session', :value => value).delete_all
|
|
end
|
|
|
|
def delete_autologin_token(value)
|
|
Token.where(:user_id => id, :action => 'autologin', :value => value).delete_all
|
|
end
|
|
|
|
# 修改用户状态
|
|
def activate
|
|
self.status = STATUS_ACTIVE
|
|
end
|
|
def lock
|
|
self.status = USER_STATUS::STATUS_LOCKED
|
|
end
|
|
|
|
|
|
# 用户账号状态
|
|
def active?
|
|
status == USER_STATUS::STATUS_ACTIVE
|
|
end
|
|
def invalid?
|
|
status == USER_STATUS::STATUS_INVALID
|
|
end
|
|
def locked?
|
|
status == USER_STATUS::STATUS_LOCKED
|
|
end
|
|
|
|
|
|
|
|
def self.try_to_login(login)
|
|
login = login.to_s.strip
|
|
# Make sure no one can sign in with an empty login or password
|
|
return nil if login.empty?
|
|
if (login =~ VALID_EMAIL_REGEX)
|
|
user = find_by_email(login)
|
|
elsif (login =~ VALID_PHONE_REGEX)
|
|
user = find_by_phone(login)
|
|
else
|
|
user = find_by_login(login)
|
|
end
|
|
|
|
user
|
|
rescue => text
|
|
raise text
|
|
end
|
|
|
|
# 密码加密
|
|
def self.password(clear_password)
|
|
Digest::SHA1.hexdigest(clear_password || "")
|
|
end
|
|
|
|
# 检查密码
|
|
def check_password?(clear_password)
|
|
# Preventing Timing Attack
|
|
ActiveSupport::SecurityUtils.secure_compare(
|
|
User.password("#{salt}#{User.password clear_password}"),
|
|
password
|
|
)
|
|
end
|
|
|
|
def self.generate_salt
|
|
Edu::Utils.random_hex(16)
|
|
end
|
|
|
|
# 密码加密
|
|
def salt_password(clear_password)
|
|
self.salt = User.generate_salt
|
|
self.password = User.password("#{salt}#{User.password clear_password}")
|
|
end
|
|
|
|
def update_hashed_password
|
|
if password
|
|
salt_password(password)
|
|
end
|
|
end
|
|
end
|