우리의 경우, Discourse를 백엔드로만 사용해야 할 필요가 있습니다 (+ CMS처럼 사용하는 것과 비슷하게).
다음과 같이 가입과 로그인 라우트를 노출했습니다:
skip_before_action :redirect_to_login_if_required, raise: false
skip_before_action :verify_authenticity_token, raise: false
… 그리고 api_parameter_allowed?에서 해당 라우트를 허용했습니다. 최종 버전에서는 보안 수준을 조금이라도 높이기 위해 어떤 종류의 솔트(salt)를 추가할 예정이지만, 현재는 초안 단계입니다.
… 그리고 아래 코드를 사용했습니다.
제가 놓친 부분이 있는지 알고 싶습니다. 향후에는 구글, 아마도 애플로 로그인할 예정이며, 이 플로우를 사용하면 이메일 가입 및 이메일 로그인 플로우에서 브라우저를 전혀 열지 않아도 됩니다.
회원가입과 로그인을 모두 API를 통해 처리하는 방법을 찾았으며, hopefully 모든 것이 정상적으로 작동할 것으로 기대합니다.
사용자를 생성하기 위해 다음 코드를 사용합니다.
normalized_username = User.normalize_username(username)
rescue
normalized_username = nil
end
raise PluginError.new(:invalid_signup_username) if !normalized_username.present? || User.username_exists?(normalized_username) || User.reserved_username?(normalized_username)
# Try like this
raise PluginError.new(:invalid_signup_email) if (existing_user = User.find_by_email(email))
begin
new_user = User.new
new_user.name = first_name
new_user.email = email
new_user.password = password
new_user.username = username
new_user.active = false
new_user.approved = true
new_user.approved_by_id = -1
new_user.approved_at = DateTime.now
new_user.password_required!
new_user.save
new_user.email_tokens.create(email: email) unless new_user.email_tokens.active.exists?
if (email_token = new_user.email_tokens.active.where(email: email)&.first)
EmailToken.confirm(email_token.token, skip_reviewable: true)
end
new_user.update!(active: true)
rescue => e
raise e
end
사용자를 가입시키기 위해 다음 코드를 사용합니다.
new_user = self.class.commit_user_to_db(first_name, email, password, username)
raise PluginError.new(:error_creating_user_discourse) unless new_user.present? && new_user.is_a?(User) && new_user.approved?
user_api_key = UserApiKey.create!(
application_name: "#{application_name}-v#{version}",
client_id: client_id,
user_id: new_user.id,
push_url: "https://api.discourse.org/api/publish_#{platform === Constants::PLATFORMS[:ios] ? 'ios' : ''}#{platform === Constants::PLATFORMS[:android] ? 'android' : ''}",
scopes: %w[notifications session_info read write message_bus push]
)
사용자 API 키는 다음 코드를 사용하여 가져옵니다.
email = params[:email]&.to_s
password = params[:password]&.to_s
return render json: PluginError.new(:invalid_login_email) unless email.present?
return render json: PluginError.new(:invalid_login_password) unless password.present?
user = User.joins(:user_emails).where({ user_emails: { email: email } })&.first
return render json: PluginError.new(:invalid_login_email) unless user.present?
return render json: PluginError.new(:invalid_login_password) unless user.confirm_password?(password)
#destroy any old keys we had for this client_id
UserApiKey.where(user_id: user.id, client_id: client_id).destroy_all
user_api_key = UserApiKey.create!(
application_name: "#{application_name}-v#{version}",
client_id: client_id,
user_id: user.id,
push_url: "https://api.discourse.org/api/publish_#{platform === Constants::PLATFORMS[:ios] ? 'ios' : ''}#{platform === Constants::PLATFORMS[:android] ? 'android' : ''}",
scopes: %w[notifications session_info read write message_bus push]
)
Discourse의 관점에서 이 방식이 괜찮은가요?
우리의 사용자는 웹사이트에 절대 접속하지 않으며, 모든 곳에서 이를 숨기고 싶습니다.