Last active
March 20, 2020 13:55
-
-
Save paulcsmith/49fc1c4c833e2e6673ba4ca934eb70f2 to your computer and use it in GitHub Desktop.
Invite user to team with Lucky
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UserInvitations::New < BrowserAction | |
get "/teams/:team_id/user_invitations/new" do | |
html NewPage, operation: InviteUser.new | |
end | |
end | |
class UserInvitations::Create < BrowserAction | |
post "/teams/:team_id/user_invitations" do | |
team = TeamQuery.new.team_id(team_id).find | |
InviteUser.create(params, invited_by: current_user.id, team_id: team.id) do |op, user_invitation| | |
if user_invitation | |
flash.success = "Yay!" | |
redirect Teams::Show.with(team.id) | |
else | |
flash.failure = ":(" | |
render NewPage, operation: op | |
end | |
end | |
end | |
end | |
class UserInvitations::Show < BrowserAction | |
get "/user_invitations/:token" do | |
user_invitation = UserInvitationQuery.new.from_token(token).first? | |
if user_invitation && user.invitation.accepted | |
flash.info "You've already accepted this invitation, please sign in." | |
redirect SignIns::New | |
elsif user_invitation && !user_invitation.accepted? | |
render AcceptPage, operation: AcceptInvitation.new(user_invitation) | |
else | |
flash.failure = "This invitation does not exist or is expired" | |
redirect Home::Index | |
end | |
end | |
end | |
class UserInvitations::Accept < BrowserAction | |
post "/user_invitations/:token" do | |
invitation = UserInvitationQuery.new.from_token(token).first | |
AcceptInvitation.update(invitation, params) do |op, user| | |
if op.saved? | |
sign_in(user) | |
redirect Dashboard::Index | |
else | |
flash.failure "Need to make sure the form is ok" | |
render AcceptPage, operation: op | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UserInvitationEmail < BaseEmail | |
to @invitation.inviter!.email | |
subject "You've been invited!" | |
templates text, html | |
def initialize(@invitation : UserInvitation) | |
end | |
def email : String | |
@invitation.inviter!.email | |
end | |
end | |
# Text template example | |
# You've been invited to #{@invitation.team!.name}! | |
# | |
# Click here: #{UserInvitations::Show.with(token: @invitation.token} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class InviteUser < UserInvitation::SaveOperation | |
permit_column invitee_email | |
after_commit :send_invite_email | |
before_save do | |
sent_at.value = Time.utc | |
token.value = Random::Secure.hex(32) | |
end | |
def send_invite_email(user_invitation) | |
UserInvitationEmail.new(user_invitation).deliver_later | |
end | |
end | |
class AcceptInvitation < User::SaveOperation | |
attribute password : String | |
attribute password_confirmation : String | |
needs user_invitation : UserInvitation | |
after_save :update_invitation | |
def initialize | |
super | |
email.value = @user_invitation.invitee_email | |
end | |
before_save do | |
accepted_at.value = Time.utc | |
# Validate password. Probably with the password validation mixin used by SignUps | |
end | |
def update_invitation(user) | |
UserInvitation::SaveOperation.update!(accepted_at: Time.utc) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UserInvitations::NewPage < MainLayout | |
needs operation : InviteUser | |
def content | |
form_for UserInvitations::Create do | |
mount Shared::Field.new(@operation.invitee_email), &.text_input(autofocus: true) | |
submit "Invite" | |
end | |
end | |
end | |
class UserInvitations::AcceptPage < MainLayout | |
needs operation : AcceptInvitation | |
def content | |
form_for UserInvitations::Accept do | |
mount Shared::Field.new(@operation.password) | |
mount Shared::Field.new(@operation.password_confirmation) | |
submit "Create account" | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UserInvitation < BaseModel | |
table do | |
column sent_at : Time | |
column token : String | |
column invitee_email : String | |
column accepted_at : Time? | |
belongs_to inviter : User | |
belongs_to team : Team | |
end | |
def accepted? : Bool | |
accepted_at.present? | |
end | |
end | |
class UserInvitationQuery < UserInvitation::Query | |
def self.from_token(token_value : String) | |
token(token_value).sent_at.gt(1.week.ago) # Set an expiration | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment