v0.7 -- complete rework... override SessionController::create
This commit is contained in:
parent
7445bd8f06
commit
4dc121eb76
131
plugin.rb
131
plugin.rb
@ -4,72 +4,89 @@
|
||||
|
||||
# name: discourse-md5_authentication
|
||||
# about: A plugin to authenticate users with MD5 passwords from legacy systems
|
||||
# version: 0.6
|
||||
# version: 0.7
|
||||
# authors: saint
|
||||
# url: https://gitea.federated.computer/saint/discourse-md5_authentication.git
|
||||
|
||||
# This block will run after Discourse has initialized
|
||||
after_initialize do
|
||||
# Define a module to contain the MD5 authentication logic
|
||||
module LegacyMd5Authentication
|
||||
# Override the log_on_user method to include MD5 authentication
|
||||
def log_on_user(user, session, cookie_jar, opts = {})
|
||||
# If the user has an MD5 password and the MD5 password option is passed
|
||||
if user.custom_fields['md5_password'] && opts[:md5_password]
|
||||
# Check if the provided MD5 password matches the stored MD5 password
|
||||
if user.custom_fields['md5_password'] == Digest::MD5.hexdigest(opts[:md5_password])
|
||||
# Update the user to use the new password and clear the MD5 password
|
||||
user.update!(password: opts[:md5_password])
|
||||
user.custom_fields['md5_password'] = nil
|
||||
user.save_custom_fields
|
||||
else
|
||||
# Return nil if the MD5 password does not match
|
||||
return nil
|
||||
class ::SessionController < ApplicationController
|
||||
def create
|
||||
params.require(:login)
|
||||
params.require(:password)
|
||||
|
||||
return invalid_credentials if params[:password].length > User.max_password_length
|
||||
|
||||
user = User.find_by_username_or_email(normalized_login_param)
|
||||
|
||||
raise Discourse::ReadOnly if staff_writes_only_mode? && !user&.staff?
|
||||
|
||||
rate_limit_second_factor!(user)
|
||||
|
||||
if user.present?
|
||||
password = params[:password]
|
||||
custom_password_md5 = user.custom_fields['custom_password_md5']
|
||||
|
||||
# Check for MD5 password in custom field
|
||||
if custom_password_md5.present?
|
||||
|
||||
# MD5 password is present
|
||||
if Digest::MD5.hexdigest(password) == custom_password_md5
|
||||
|
||||
# MD5 matches, so update the user's password to the new one and remove the custom field
|
||||
user.password = password
|
||||
user.custom_fields['custom_password_md5'] = nil
|
||||
user.save!
|
||||
Rails.logger.debug "Updated MD5 password for user: #{user.id}"
|
||||
|
||||
else
|
||||
|
||||
# MD5 doesn't match, so we have a failed login attempt.
|
||||
Rails.logger.debug "Password incorrect for user: #{user.id}"
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
# If their password is incorrect
|
||||
elsif !user.confirm_password?(password)
|
||||
|
||||
# There is no MD5 password and the password was incorrect.
|
||||
Rails.logger.debug "Password incorrect for user: #{user.id}"
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
end
|
||||
# Call the original log_on_user method
|
||||
super
|
||||
end
|
||||
|
||||
# Define a method to authenticate a user with an MD5 password
|
||||
def authenticate_with_md5(username, password)
|
||||
# Find the user by username or email, ignoring case
|
||||
user = User.find_by_username_or_email(username.downcase.strip)
|
||||
# Check if the user exists and the provided MD5 password matches the stored MD5 password
|
||||
if user && user.custom_fields['md5_password'] == Digest::MD5.hexdigest(password)
|
||||
# Update the user to use the new password and clear the MD5 password
|
||||
user.update!(password: password)
|
||||
user.custom_fields['md5_password'] = nil
|
||||
user.save_custom_fields
|
||||
user
|
||||
# If the site requires user approval and the user is not approved yet
|
||||
if login_not_approved_for?(user)
|
||||
render json: login_not_approved
|
||||
return
|
||||
end
|
||||
|
||||
# User signed on with username and password, so let's prevent the invite link
|
||||
# from being used to log in (if one exists).
|
||||
Invite.invalidate_for_email(user.email)
|
||||
|
||||
# User's password has expired so they need to reset it
|
||||
if user.password_expired?(password)
|
||||
render json: { error: "expired", reason: "expired" }
|
||||
return
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Extend the DefaultCurrentUserProvider class to include our MD5 authentication logic
|
||||
class ::Auth::DefaultCurrentUserProvider
|
||||
prepend LegacyMd5Authentication
|
||||
|
||||
# Alias the original current_user method
|
||||
alias_method :original_current_user, :current_user
|
||||
def current_user
|
||||
# Attempt to find the current user using the standard Discourse method
|
||||
user = original_current_user
|
||||
return user if user
|
||||
|
||||
# Check for MD5 authentication if no user is found by the standard method
|
||||
username = @request.params[:login]
|
||||
password = @request.params[:password]
|
||||
|
||||
if username && password
|
||||
# Authenticate the user with MD5
|
||||
user = authenticate_with_md5(username, password)
|
||||
@env[CURRENT_USER_KEY] = user if user
|
||||
invalid_credentials
|
||||
return
|
||||
end
|
||||
|
||||
user
|
||||
if payload = login_error_check(user)
|
||||
return render json: payload
|
||||
end
|
||||
|
||||
second_factor_auth_result = authenticate_second_factor(user)
|
||||
return render(json: @second_factor_failure_payload) unless second_factor_auth_result.ok
|
||||
|
||||
if user.active && user.email_confirmed?
|
||||
login(user, second_factor_auth_result)
|
||||
else
|
||||
not_activated(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user