Refactor User model, extract PamAuthenticable, LdapAuthenticable (#10217)

This commit is contained in:
Eugen Rochko 2019-03-14 02:13:42 +01:00 committed by GitHub
parent dfb9efae81
commit 9e33174604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 155 additions and 120 deletions

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module LdapAuthenticable
extend ActiveSupport::Concern
def ldap_setup(_attributes)
self.confirmed_at = Time.now.utc
self.admin = false
save!
end
class_methods do
def ldap_get_user(attributes = {})
resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first })
if resource.blank?
resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first })
resource.ldap_setup(attributes)
end
resource
end
end
end

View File

@ -7,6 +7,8 @@ module Omniauthable
TEMP_EMAIL_REGEX = /\Achange@me/ TEMP_EMAIL_REGEX = /\Achange@me/
included do included do
devise :omniauthable
def omniauth_providers def omniauth_providers
Devise.omniauth_configs.keys Devise.omniauth_configs.keys
end end

View File

@ -0,0 +1,68 @@
# frozen_string_literal: true
module PamAuthenticable
extend ActiveSupport::Concern
included do
devise :pam_authenticatable if ENV['PAM_ENABLED'] == 'true'
def pam_conflict(_attributes)
# Block pam login tries on traditional account
end
def pam_conflict?
if Devise.pam_authentication
encrypted_password.present? && pam_managed_user?
else
false
end
end
def pam_get_name
if account.present?
account.username
else
super
end
end
def pam_setup(_attributes)
account = Account.new(username: pam_get_name)
account.save!(validate: false)
self.email = "#{account.username}@#{find_pam_suffix}" if email.nil? && find_pam_suffix
self.confirmed_at = Time.now.utc
self.admin = false
self.account = account
account.destroy! unless save
end
def self.pam_get_user(attributes = {})
return nil unless attributes[:email]
resource = begin
if Devise.check_at_sign && !attributes[:email].index('@')
joins(:account).find_by(accounts: { username: attributes[:email] })
else
find_by(email: attributes[:email])
end
end
if resource.nil?
resource = new(email: attributes[:email], agreement: true)
if Devise.check_at_sign && !resource[:email].index('@')
resource[:email] = Rpam2.getenv(resource.find_pam_service, attributes[:email], attributes[:password], 'email', false)
resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" unless resource[:email]
end
end
resource
end
def self.authenticate_with_pam(attributes = {})
super if Devise.pam_authentication
end
end
end

View File

@ -0,0 +1,54 @@
# frozen_string_literal: true
module UserRoles
extend ActiveSupport::Concern
included do
scope :admins, -> { where(admin: true) }
scope :moderators, -> { where(moderator: true) }
scope :staff, -> { admins.or(moderators) }
end
def staff?
admin? || moderator?
end
def role
if admin?
'admin'
elsif moderator?
'moderator'
else
'user'
end
end
def role?(role)
case role
when 'user'
true
when 'moderator'
staff?
when 'admin'
admin?
else
false
end
end
def promote!
if moderator?
update!(moderator: false, admin: true)
elsif !admin?
update!(moderator: true)
end
end
def demote!
if admin?
update!(admin: false, moderator: true)
elsif moderator?
update!(moderator: false)
end
end
end

View File

@ -41,7 +41,7 @@
class User < ApplicationRecord class User < ApplicationRecord
include Settings::Extend include Settings::Extend
include Omniauthable include UserRoles
# The home and list feeds will be stored in Redis for this amount # The home and list feeds will be stored in Redis for this amount
# of time, and status fan-out to followers will include only people # of time, and status fan-out to followers will include only people
@ -61,9 +61,9 @@ class User < ApplicationRecord
devise :registerable, :recoverable, :rememberable, :trackable, :validatable, devise :registerable, :recoverable, :rememberable, :trackable, :validatable,
:confirmable :confirmable
devise :pam_authenticatable if ENV['PAM_ENABLED'] == 'true' include Omniauthable
include PamAuthenticable
devise :omniauthable include LdapAuthenticable
belongs_to :account, inverse_of: :user belongs_to :account, inverse_of: :user
belongs_to :invite, counter_cache: :uses, optional: true belongs_to :invite, counter_cache: :uses, optional: true
@ -79,9 +79,6 @@ class User < ApplicationRecord
validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create
scope :recent, -> { order(id: :desc) } scope :recent, -> { order(id: :desc) }
scope :admins, -> { where(admin: true) }
scope :moderators, -> { where(moderator: true) }
scope :staff, -> { admins.or(moderators) }
scope :confirmed, -> { where.not(confirmed_at: nil) } scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :enabled, -> { where(disabled: false) } scope :enabled, -> { where(disabled: false) }
scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) } scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
@ -104,39 +101,6 @@ class User < ApplicationRecord
attr_reader :invite_code attr_reader :invite_code
def pam_conflict(_)
# block pam login tries on traditional account
nil
end
def pam_conflict?
return false unless Devise.pam_authentication
encrypted_password.present? && pam_managed_user?
end
def pam_get_name
return account.username if account.present?
super
end
def pam_setup(_attributes)
acc = Account.new(username: pam_get_name)
acc.save!(validate: false)
self.email = "#{acc.username}@#{find_pam_suffix}" if email.nil? && find_pam_suffix
self.confirmed_at = Time.now.utc
self.admin = false
self.account = acc
acc.destroy! unless save
end
def ldap_setup(_attributes)
self.confirmed_at = Time.now.utc
self.admin = false
save!
end
def confirmed? def confirmed?
confirmed_at.present? confirmed_at.present?
end end
@ -145,33 +109,6 @@ class User < ApplicationRecord
invite_id.present? invite_id.present?
end end
def staff?
admin? || moderator?
end
def role
if admin?
'admin'
elsif moderator?
'moderator'
else
'user'
end
end
def role?(role)
case role
when 'user'
true
when 'moderator'
staff?
when 'admin'
admin?
else
false
end
end
def disable! def disable!
update!(disabled: true, update!(disabled: true,
last_sign_in_at: current_sign_in_at, last_sign_in_at: current_sign_in_at,
@ -186,6 +123,7 @@ class User < ApplicationRecord
new_user = !confirmed? new_user = !confirmed?
super super
prepare_new_user! if new_user prepare_new_user! if new_user
end end
@ -194,6 +132,7 @@ class User < ApplicationRecord
skip_confirmation! skip_confirmation!
save! save!
prepare_new_user! if new_user prepare_new_user! if new_user
end end
@ -202,22 +141,6 @@ class User < ApplicationRecord
prepare_returning_user! prepare_returning_user!
end end
def promote!
if moderator?
update!(moderator: false, admin: true)
elsif !admin?
update!(moderator: true)
end
end
def demote!
if admin?
update!(admin: false, moderator: true)
elsif moderator?
update!(moderator: false)
end
end
def disable_two_factor! def disable_two_factor!
self.otp_required_for_login = false self.otp_required_for_login = false
otp_backup_codes&.clear otp_backup_codes&.clear
@ -297,43 +220,6 @@ class User < ApplicationRecord
super super
end end
def self.pam_get_user(attributes = {})
return nil unless attributes[:email]
resource =
if Devise.check_at_sign && !attributes[:email].index('@')
joins(:account).find_by(accounts: { username: attributes[:email] })
else
find_by(email: attributes[:email])
end
if resource.blank?
resource = new(email: attributes[:email], agreement: true)
if Devise.check_at_sign && !resource[:email].index('@')
resource[:email] = Rpam2.getenv(resource.find_pam_service, attributes[:email], attributes[:password], 'email', false)
resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" unless resource[:email]
end
end
resource
end
def self.ldap_get_user(attributes = {})
resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first })
if resource.blank?
resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first })
resource.ldap_setup(attributes)
end
resource
end
def self.authenticate_with_pam(attributes = {})
return nil unless Devise.pam_authentication
super
end
def show_all_media? def show_all_media?
setting_display_media == 'show_all' setting_display_media == 'show_all'
end end