allow users to sign up multiple times without throwing a 500

This commit is contained in:
Joseph Lyons 2022-11-15 20:04:56 -05:00
parent 275f0ae492
commit c3cf056fc5
3 changed files with 35 additions and 22 deletions

View file

@ -338,7 +338,7 @@ async fn create_signup(
Json(params): Json<Signup>, Json(params): Json<Signup>,
Extension(app): Extension<Arc<AppState>>, Extension(app): Extension<Arc<AppState>>,
) -> Result<()> { ) -> Result<()> {
app.db.create_signup(params).await?; app.db.create_signup(&params).await?;
Ok(()) Ok(())
} }

View file

@ -157,7 +157,7 @@ impl Db<sqlx::Sqlite> {
unimplemented!() unimplemented!()
} }
pub async fn create_signup(&self, _signup: Signup) -> Result<()> { pub async fn create_signup(&self, _signup: &Signup) -> Result<()> {
unimplemented!() unimplemented!()
} }
@ -375,7 +375,7 @@ impl Db<sqlx::Postgres> {
}) })
} }
pub async fn create_signup(&self, signup: Signup) -> Result<()> { pub async fn create_signup(&self, signup: &Signup) -> Result<()> {
test_support!(self, { test_support!(self, {
sqlx::query( sqlx::query(
" "
@ -394,6 +394,8 @@ impl Db<sqlx::Postgres> {
) )
VALUES VALUES
($1, $2, FALSE, $3, $4, $5, FALSE, $6, $7, $8) ($1, $2, FALSE, $3, $4, $5, FALSE, $6, $7, $8)
ON CONFLICT (email_address) DO UPDATE SET
email_address = excluded.email_address
RETURNING id RETURNING id
", ",
) )
@ -1259,7 +1261,7 @@ pub struct IncomingContactRequest {
pub should_notify: bool, pub should_notify: bool,
} }
#[derive(Clone, Deserialize)] #[derive(Clone, Deserialize, Default)]
pub struct Signup { pub struct Signup {
pub email_address: String, pub email_address: String,
pub platform_mac: bool, pub platform_mac: bool,
@ -1284,7 +1286,7 @@ pub struct WaitlistSummary {
pub unknown_count: i64, pub unknown_count: i64,
} }
#[derive(FromRow, PartialEq, Debug, Serialize, Deserialize)] #[derive(Clone, FromRow, PartialEq, Debug, Serialize, Deserialize)]
pub struct Invite { pub struct Invite {
pub email_address: String, pub email_address: String,
pub email_confirmation_code: String, pub email_confirmation_code: String,

View file

@ -644,10 +644,14 @@ async fn test_signups() {
let test_db = PostgresTestDb::new(build_background_executor()); let test_db = PostgresTestDb::new(build_background_executor());
let db = test_db.db(); let db = test_db.db();
let usernames = (0..8).map(|i| format!("person-{i}")).collect::<Vec<_>>();
// people sign up on the waitlist // people sign up on the waitlist
for i in 0..8 { let all_signups = usernames
db.create_signup(Signup { .iter()
email_address: format!("person-{i}@example.com"), .enumerate()
.map(|(i, username)| Signup {
email_address: format!("{username}@example.com"),
platform_mac: true, platform_mac: true,
platform_linux: i % 2 == 0, platform_linux: i % 2 == 0,
platform_windows: i % 4 == 0, platform_windows: i % 4 == 0,
@ -655,8 +659,13 @@ async fn test_signups() {
programming_languages: vec!["rust".into(), "c".into()], programming_languages: vec!["rust".into(), "c".into()],
device_id: Some(format!("device_id_{i}")), device_id: Some(format!("device_id_{i}")),
}) })
.await .collect::<Vec<Signup>>();
.unwrap();
for signup in &all_signups {
// Users can sign up multiple times without issues
for _ in 0..2 {
db.create_signup(&signup).await.unwrap();
}
} }
assert_eq!( assert_eq!(
@ -679,9 +688,9 @@ async fn test_signups() {
assert_eq!( assert_eq!(
addresses, addresses,
&[ &[
"person-0@example.com", all_signups[0].email_address.as_str(),
"person-1@example.com", all_signups[1].email_address.as_str(),
"person-2@example.com" all_signups[2].email_address.as_str()
] ]
); );
assert_ne!( assert_ne!(
@ -705,9 +714,9 @@ async fn test_signups() {
assert_eq!( assert_eq!(
addresses, addresses,
&[ &[
"person-3@example.com", all_signups[3].email_address.as_str(),
"person-4@example.com", all_signups[4].email_address.as_str(),
"person-5@example.com" all_signups[5].email_address.as_str()
] ]
); );
@ -733,11 +742,10 @@ async fn test_signups() {
} = db } = db
.create_user_from_invite( .create_user_from_invite(
&Invite { &Invite {
email_address: signups_batch1[0].email_address.clone(), ..signups_batch1[0].clone()
email_confirmation_code: signups_batch1[0].email_confirmation_code.clone(),
}, },
NewUserParams { NewUserParams {
github_login: "person-0".into(), github_login: usernames[0].clone(),
github_user_id: 0, github_user_id: 0,
invite_count: 5, invite_count: 5,
}, },
@ -747,8 +755,11 @@ async fn test_signups() {
.unwrap(); .unwrap();
let user = db.get_user_by_id(user_id).await.unwrap().unwrap(); let user = db.get_user_by_id(user_id).await.unwrap().unwrap();
assert!(inviting_user_id.is_none()); assert!(inviting_user_id.is_none());
assert_eq!(user.github_login, "person-0"); assert_eq!(user.github_login, usernames[0]);
assert_eq!(user.email_address.as_deref(), Some("person-0@example.com")); assert_eq!(
user.email_address,
Some(all_signups[0].email_address.clone())
);
assert_eq!(user.invite_count, 5); assert_eq!(user.invite_count, 5);
assert_eq!(signup_device_id.unwrap(), "device_id_0"); assert_eq!(signup_device_id.unwrap(), "device_id_0");
@ -776,7 +787,7 @@ async fn test_signups() {
email_confirmation_code: "the-wrong-code".to_string(), email_confirmation_code: "the-wrong-code".to_string(),
}, },
NewUserParams { NewUserParams {
github_login: "person-1".into(), github_login: usernames[1].clone(),
github_user_id: 2, github_user_id: 2,
invite_count: 5, invite_count: 5,
}, },