-
Notifications
You must be signed in to change notification settings - Fork 675
Description
Extracted from #815
Now that we've been requiring verified email addresses for publishing, it's more likely this feature will work well.
This is a big task that's more complicated than it looks! Please ask questions if anything is confusing! This task would be great for someone looking to get experience with just about every part of crates.io: the frontend, the backend API, the database, email sending.
What should happen:
- When any owner of a crate (either by being an individual owner or having permission through a team) publishes a new version of a crate they own,
- Email all individual owners of that crate that have verified email addresses to notify them of the new version
- We could email all team owners as well, but we'd have to query GitHub for that each time and try to match up team members to crates.io accounts, seems complex. Let's start with individual owners.
- We could email the person who published the crate as well if they have permissions because of a team, so that they're notified more quickly if they didn't authorize that publish with their credentials. However, there'd be no way to turn this email off because we don't have a record on which to store that preference? I'm torn about whether we say "the person who did the publish always gets an email even if you've turned notifications off" or whether we say "people who have permissions via teams never get emails even if they're the one who published the crate". Open to arguments.
- The email should include the name of the crate, the version published, who published it, the date and time they published it, instructions on what to do if the publish wasn't authorized, and a link to the page to opt out of the emails. Here's an example of an email from rubygems.org:
- Let each owner of a crate opt out of getting these notifications for each crate they're an individual owner of. Rubygems.org has this preference page:
Implementation instructions
Roughly trying to separate these into pieces that can be submitted and reviewed as separate PRs; let me know if you run into any problems with the way I've split the tasks up.
-
Backend: email preference storing (addressed in backend: Add user email preference storing #1901)
- Create a migration (search for
diesel migration generatein this guide) that adds a column to thecrate_ownerstable... this isn't great because teams are also stored in this table and teams don't have emails, but I think this is the best spot for now. Name the column something likeemail_notifications, of type boolean, and set the default to true. In the database dump configuration, set this new column toprivate(we shouldn't include this value in public database dumps). - Create a function that updates the email notifications field with a given value; it'll look something like the
owner_removefunction. - Create a new API route in the router that's a PUT request to
/me/email_notificationsor similar and calls a new controller function that I think would fit in theuser/mecontroller, calledupdate_email_notificationsor similar - That controller should get a list of crate IDs and on/off values from radio buttons in the frontend about whether the current user wants to get email notifications for that crate or not. Iterate through the crate IDs, fetch any crate owner records for the current user and the given IDs (ignore IDs for crates that the current user doesn't actually own), and update the
email_notificationscolumn of those records with the values sent. Updating the values unconditionally is fine, I think. Ignore any crates that the current user owns that we didn't get any radio button value for. - So whether you have email notifications for a crate you own on or off should be private information. That makes me inclined to include this information in with the GET /me request and the
encodable_privateresponse that uses theEncodablePrivatestruct. Minimally, this should be a vector of (crate name, crate id, email notification value) tuples, I think. Enough to display the form with the radio buttons described below. - Write tests for the new update controller action and the new info in the /me response in with the other user tests.
- Create a migration (search for
-
Frontend: settings (addressed in front-end: Add email notification preferences #1913)
- Given that I think we should include the email setting values in with the
/meAPI request, I think the frontend should add a new section to https://crates.io/me whose HTML is here, as opposed to creating a whole separate page for email notifications. - This section should list all crates the current user owns as listed in the API response. My ember knowledge is still lacking, so I'm not sure how to describe how to do this the right way.
- There should be a form with radio buttons for each crate id and whether emails are on/off, and a button to save all the settings that sends the radio button values to the backend
/me/email_notificationscontroller described above. - If there's a good way to test this in the ember tests, please add some. I don't think there's going to be too much frontend logic though?
- Given that I think we should include the email setting values in with the
-
Backend: email sending (no PR yet)
- After the crate has been successfully added to the index, call a new
notify_ownersfunction. So use?onrepo.commit_and_push, and instead return the result fromnotify_ownersin thisadd_cratefunction. - In
add_crate, theCrateparameter is of this type, which currently doesn't have the owners available on it, nor should it because that is what gets serialized into the index. Theadd_cratefunction doesn't currently use a database connection. Therefore, I'm thinkingadd_crateshould have a new parameter that's a vector of email addresses. Thenadd_cratecan callnotify_ownerswith the email addresses, thekrate.name,krate.vers, andchrono::Utc::now(). - So in the publish controller, before
git::add_crateis called, we'll need to get the unique set of verified email addresses of the named owners plus the verified email address of the person who published the crate, if we decide we want to do that (see bolded bullet point at the top where I'm conflicted about this). We already have the set of crate owners available, which is aVecofOwners. So iterate through the owners, and for user owners, if theiremail_notificationsvalue istrue(the new column described above), collect the present verified email addresses into aHashSet(to get unique ones) and (maybe, see above) add the publisher's verified email address. - The new
notify_ownersfunction will probably look liketry_send_user_confirm_emailand can go in that file. Use the screenshot above of the rubygems email as a general guide for what should be in the email, and ask questions here if you have any. - We don't have a great way to write automated tests for emails sent from background jobs, but do write tests for gathering the email addresses of the owners.
- After the crate has been successfully added to the index, call a new

