在我们的案例中,我们只需要将 Discourse 用作后端(某种程度上类似于 CMS)。
我通过以下方式公开了注册和登录的路由:
skip_before_action :redirect_to_login_if_required, raise: false
skip_before_action :verify_authenticity_token, raise: false
… 并在 api_parameter_allowed? 中允许了这些路由。在最终版本中,我会添加某种盐值以增加安全性,但这目前只是一个草稿。
… 并使用了以下代码。
我唯一想知道的是我是否遗漏了什么。未来我们可能会使用 Google 登录,也许还有 Apple,这种流程将允许我在通过电子邮件注册和通过电子邮件登录的流程中完全不需要打开浏览器。
我已经搞清楚了如何通过 API 完成注册和登录,希望一切顺利。
我使用以下代码创建用户:
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)
# 尝试这种方式
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)
# 销毁该 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 的角度来看,这样做没问题吗?
我们的用户永远不会访问网站,我们希望将其从所有地方隐藏起来。