Description
If there's an email address for the person being invited (which we don't require yet)
It'd be awesome if the email included a one-click link to accept the invitation without logging in (so with a token like the email verification works now)
Related:
- We shouldn't let you add someone as an owner without their consent #924 (the owner invitation system so far)
- Add some sort of notification that you have invitations to own a crate #1116 (showing a notification on crates.io)
Instructions
Invitations get created in the krate.owner_add method.
Currently, if you add someone as an owner multiple times, it just updates the one existing invitation record. We don't want to send multiple emails in this situation, as this would be an easy vector for spamming someone.
You can tell whether a row was inserted or not when you say on conflict do update
by adding a returning
method call to request that the query returns some of the data, getting the result with the get_result
method, and calling the optional
method to tell diesel it's ok if it doesn't get a result. If the query did nothing (because that record already existed), nothing will be returned and this diesel statement will result in a None
value. Here's an example where we do this:
So after creating an invitation, and only if that invitation record was created (rather than only updated because it already existed), send the invited user an email.
Get the email address by first getting the User
(owner
here is an Owner::User
, change the underscore in that match pattern to a variable name to be able to use the inner User
that Owner::User
holds)
Get the email address for that User
NOT through the email
field; that's left over from before we verified email addresses. Instead, use the verified_email
method. If the user doesn't have a verified email address, don't send the email.
Send the email by calling a new function you'll need to create in src/email.rs
. The new function should swallow all errors like send_user_confirm_email
does by using let _ =
, but should call send_email
like try_send_user_confirm_email
does. I think we only need one function in the case of sending owner invitation emails, rather than the two functions we have for verifying your email address, because we always want creating the invitation to succeed even if we can't send an email about it.
I would merge a PR that sends an email that always has the same content; something along the lines of "You've been invited to become the owner of a crate! Please visit https://crates.io/me/pending-invites to accept or reject this invitation."
The enhancements I could see making to that email would be:
- Including the name of the crate you're being invited to own
- Adding the username of the person who sent the invite
- Adding a URL with a randomly-generated token (that we'd need to store in a new column on the invitations table) so that you could click on that link to accept the invitation (this would need to be a new URL and controller action added)
but I would rather have a PR with the basic implementation of this feature than no PR.
We don't have a great way to write tests that check emails are sent :-/ You should be able to test this out locally; the emails will be "sent" to a file in /tmp/
.