I currently have three phoenix applications at work that share a common requirement, that requirement is that users must be invited to the system. Here is how I am currently doing the invitation system on one of the applications:
I have two schema’s:
User, and here’s what they look like:
schema "users" do field :first_name, :string field :last_name, :string field :email, :string field :password_hash, :string field :password_reset_hash, :string belongs_to :account, Aura.Account many_to_many :permissions, Aura.Permission, join_through: Aura.UserPermission, on_replace: :delete many_to_many :surgeons, Aura.Surgeon, join_through: Aura.UserSurgeon, on_replace: :delete field :password, :string, virtual: true field :password_confirmation, :string, virtual: true timestamps() end
schema "invitations" do field :first_name, :string field :last_name, :string field :email, :string field :token, :string belongs_to :account, Aura.Account many_to_many :permissions, Aura.Permission, join_through: Aura.InvitationPermission, on_replace: :delete many_to_many :surgeons, Aura.Surgeon, join_through: Aura.InvitationSurgeon, on_replace: :delete timestamps() end
Invitation is a struct that holds information that is required to create a user. So it holds things like the
account, etc… just like the
User that has a permission to invite another
User interacts with the
InvitationController to create an
Invitation. When that
Invitation is created an email is sent to the newly invited user with a url that has a unique token that they can click to begin the creation of their
User. Once they click the link and enter a password all of the information from the
Invitation is used to create their
User and then the
Invitation is deleted.
So this implemention has:
- Ecto migrations for the above structs
[:edit, :create_user]actions that are not guarded behind authentication to allow a new user to view their invitation, enter a password and then create their user.
[:index, :new, :create, :delete]actions are behind authentication to allow authentication users to view, create, and delete invitations.
- Associated html templates and views that go along with the above controller actions
My goal is to be able to have something like this that I can drop into newly created phoenix applications.
Here’s a list of thoughts/questions I currently have:
Does it make sense to extract this functionality or just continue to write this funtionality in each phoenix application? Ultimately it’s just a couple ecto structs and a phoenix controller implementation.
If I was to extract this functionality, how would I handle the flow of information from the extracted module’s
Invitationto the application’s
User? Does the extracted module just allow the application to hand over what is considered the
User? Because each application may have different data on a user.
Does it make sense to even have the concept of an
Invitation? I’ve been thinking that maybe when you invite a user, it just creates a
Userthat can’t login or isn’t activated.
Is it common or make sense to extract a phoenix controller out of the phoenix application and into its own module? This was my initial thought on how I would extract this funtionality. Basically extract the phoenix controller into the module, and allow the phoenix application that is implementing the module to use it in its router. I’m not sure how I would handle the flow of data related to #2 though.