-
-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow for multi-tenancy #83
Comments
Hi @koenhandekyn! Thanks for the kind words 😊 I like your suggestions. Would definitely want to add something like that if you or someone made a PR. I'm afraid I don't have the time right now. Also, I would very much prefer if we can do it in a backwards compatible way. At least until 1.0. |
I'd love this too! I may need to work around it by creating multiple user models, which could cause my app problems :( |
I'm not against passing the whole PRs welcome 😊 |
I created a first-pass version that seems to work locally allowing email and phone number passwordless by overriding some methods in the session controller and overriding the mailer. Def not the cleanest, but it seems to work. Below is just a first-pass version; there are probably a lot of bugs In a bit of a hurry but when I get some time I'd love to loop back and actually contribute! Overriden controller methods in an initializer # require_dependency 'passwordless/sessions_controller'
Rails.application.config.after_initialize do
Passwordless::SessionsController.class_eval do
def find_authenticatable
if params[:auth_method] == 'email'
email = params[:passwordless][:email].downcase.strip
elsif params[:auth_method] == 'phone'
email = params[:passwordless][:phone].downcase.strip
else
raise "Unknown auth method #{params[:auth_method]}"
end
# email = passwordless_session_params[email_field].downcase.strip
if authenticatable_class.respond_to?(:fetch_resource_for_passwordless)
authenticatable_class.fetch_resource_for_passwordless(params)
else
authenticatable_class.where("lower(#{email_field}) = ?", email).first
end
end
def passwordless_session_params
params.require(:passwordless).permit(:token, authenticatable_class.passwordless_email_field, :email_field, :phone_field)
end
end
end Overriden mailer module Passwordless
# The mailer responsible for sending Passwordless' mails.
class MultiTenantMailer < Passwordless.config.parent_mailer.constantize
default from: Passwordless.config.default_from_address
# Sends a token and a magic link
#
# @param session [Session] An instance of Passwordless::Session
# @param token [String] The token in plaintext. Falls back to `session.token` hoping it
# is still in memory (optional)
def sign_in(session, token = nil)
@token = token || session.token
@magic_link = Passwordless.context.url_for(
session,
action: "confirm",
id: session.to_param,
token: @token
)
puts "TEST MAILER"
# email_field = session.authenticatable.class.passwordless_email_field
mail(
to: session.authenticatable.send(:email),
subject: I18n.t("passwordless.mailer.sign_in.subject")
)
end
end
end My model class User < ApplicationRecord
passwordless_with :phone
def self.fetch_resource_for_passwordless(params)
if params[:passwordless][:phone].present?
User.find_by(phone: params[:passwordless][:phone])
elsif params[:passwordless][:email].present?
User.find_by(email: params[:passwordless][:email])
end
end |
first of all, compliments to this nice and clean standalone implementation for passwordless authentication
in my use case we have a multi-tenant application where a user is not purely identified by it's email address but where there is another property that identifies the so called 'tennant'. this could be for example the hostname (in multi homed setups), an explicit tenant identifier in the path, etc
i've looked at the codebase and the current implementation is limiting to a single parameter name.
to make the code more general, instead of passing in only the email identifier to the fetch_resource_for_passwordless method, it's more generic to pass in all params. like that the users can user all params without restrictions
in the readme i put some examples, the third shows how it could be used to allow for multi-tenancy based on an extra param.
to be even more generic, the full request would need to be passed to be able to access the HOSTNAME for example in which case the host name is the discriminator of the tenant.
further i noticed also the following: the code assumes configuration of the name of the email field. However, one could simplify the code as follows. By default the code could assume the name of the field is 'email', and to cope for the case where the field name is different, one simply just needs to add an override for fetch_resource_for_passwordless. this simplification was also implemented in the fork. the sole impact is that the default template can not be rendered dynamically but that's almost a non issue because the user will override these anyhow.
https://github.com/koenhandekyn/passwordless?organization=koenhandekyn&organization=koenhandekyn
note : does anyone know of an omni-auth adaptor? that seems to make sense to me as an easy way to bridge to devise also for example
The text was updated successfully, but these errors were encountered: