93 lines
2.9 KiB
Ruby
93 lines
2.9 KiB
Ruby
# plugins/discourse-md5_authentication/plugin.rb
|
|
|
|
# frozen_string_literal: true
|
|
|
|
# name: discourse-md5_authentication
|
|
# about: A plugin to authenticate users with MD5 passwords from legacy systems
|
|
# version: 0.7
|
|
# authors: saint
|
|
# url: https://gitea.federated.computer/saint/discourse-md5_authentication.git
|
|
|
|
after_initialize do
|
|
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
|
|
|
|
# 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
|
|
invalid_credentials
|
|
return
|
|
end
|
|
|
|
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
|