Merge branch 'main' into reconnections-2
This commit is contained in:
commit
969c314315
78 changed files with 2759 additions and 1281 deletions
|
@ -338,7 +338,7 @@ async fn create_signup(
|
|||
Json(params): Json<NewSignup>,
|
||||
Extension(app): Extension<Arc<AppState>>,
|
||||
) -> Result<()> {
|
||||
app.db.create_signup(params).await?;
|
||||
app.db.create_signup(¶ms).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -57,16 +57,14 @@ async fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
let mut zed_user_ids = Vec::<UserId>::new();
|
||||
for (github_user, admin) in zed_users {
|
||||
if let Some(user) = db
|
||||
if db
|
||||
.get_user_by_github_account(&github_user.login, Some(github_user.id))
|
||||
.await
|
||||
.expect("failed to fetch user")
|
||||
.is_none()
|
||||
{
|
||||
zed_user_ids.push(user.id);
|
||||
} else if let Some(email) = &github_user.email {
|
||||
zed_user_ids.push(
|
||||
if let Some(email) = &github_user.email {
|
||||
db.create_user(
|
||||
email,
|
||||
admin,
|
||||
|
@ -77,11 +75,8 @@ async fn main() {
|
|||
},
|
||||
)
|
||||
.await
|
||||
.expect("failed to insert user")
|
||||
.user_id,
|
||||
);
|
||||
} else if admin {
|
||||
zed_user_ids.push(
|
||||
.expect("failed to insert user");
|
||||
} else if admin {
|
||||
db.create_user(
|
||||
&format!("{}@zed.dev", github_user.login),
|
||||
admin,
|
||||
|
@ -92,9 +87,8 @@ async fn main() {
|
|||
},
|
||||
)
|
||||
.await
|
||||
.expect("failed to insert user")
|
||||
.user_id,
|
||||
);
|
||||
.expect("failed to insert user");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -660,9 +660,9 @@ impl Database {
|
|||
|
||||
// signups
|
||||
|
||||
pub async fn create_signup(&self, signup: NewSignup) -> Result<()> {
|
||||
pub async fn create_signup(&self, signup: &NewSignup) -> Result<()> {
|
||||
self.transact(|tx| async {
|
||||
signup::ActiveModel {
|
||||
signup::Entity::insert(signup::ActiveModel {
|
||||
email_address: ActiveValue::set(signup.email_address.clone()),
|
||||
email_confirmation_code: ActiveValue::set(random_email_confirmation_code()),
|
||||
email_confirmation_sent: ActiveValue::set(false),
|
||||
|
@ -673,9 +673,15 @@ impl Database {
|
|||
editor_features: ActiveValue::set(Some(signup.editor_features.clone())),
|
||||
programming_languages: ActiveValue::set(Some(signup.programming_languages.clone())),
|
||||
device_id: ActiveValue::set(signup.device_id.clone()),
|
||||
added_to_mailing_list: ActiveValue::set(signup.added_to_mailing_list),
|
||||
..Default::default()
|
||||
}
|
||||
.insert(&tx)
|
||||
})
|
||||
.on_conflict(
|
||||
OnConflict::column(signup::Column::EmailAddress)
|
||||
.update_column(signup::Column::EmailAddress)
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(&tx)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
|
@ -746,6 +752,7 @@ impl Database {
|
|||
.or(signup::Column::PlatformUnknown.eq(true)),
|
||||
),
|
||||
)
|
||||
.order_by_asc(signup::Column::CreatedAt)
|
||||
.limit(count as u64)
|
||||
.into_model()
|
||||
.all(&tx)
|
||||
|
@ -772,32 +779,41 @@ impl Database {
|
|||
Err(anyhow!("email address is already in use"))?;
|
||||
}
|
||||
|
||||
let inviter = match user::Entity::find()
|
||||
.filter(user::Column::InviteCode.eq(code))
|
||||
let inviting_user_with_invites = match user::Entity::find()
|
||||
.filter(
|
||||
user::Column::InviteCode
|
||||
.eq(code)
|
||||
.and(user::Column::InviteCount.gt(0)),
|
||||
)
|
||||
.one(&tx)
|
||||
.await?
|
||||
{
|
||||
Some(inviter) => inviter,
|
||||
Some(inviting_user) => inviting_user,
|
||||
None => {
|
||||
return Err(Error::Http(
|
||||
StatusCode::NOT_FOUND,
|
||||
"invite code not found".to_string(),
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"unable to find an invite code with invites remaining".to_string(),
|
||||
))?
|
||||
}
|
||||
};
|
||||
|
||||
if inviter.invite_count == 0 {
|
||||
Err(Error::Http(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"no invites remaining".to_string(),
|
||||
))?;
|
||||
}
|
||||
user::Entity::update_many()
|
||||
.filter(
|
||||
user::Column::Id
|
||||
.eq(inviting_user_with_invites.id)
|
||||
.and(user::Column::InviteCount.gt(0)),
|
||||
)
|
||||
.col_expr(
|
||||
user::Column::InviteCount,
|
||||
Expr::col(user::Column::InviteCount).sub(1),
|
||||
)
|
||||
.exec(&tx)
|
||||
.await?;
|
||||
|
||||
let signup = signup::Entity::insert(signup::ActiveModel {
|
||||
email_address: ActiveValue::set(email_address.into()),
|
||||
email_confirmation_code: ActiveValue::set(random_email_confirmation_code()),
|
||||
email_confirmation_sent: ActiveValue::set(false),
|
||||
inviting_user_id: ActiveValue::set(Some(inviter.id)),
|
||||
inviting_user_id: ActiveValue::set(Some(inviting_user_with_invites.id)),
|
||||
platform_linux: ActiveValue::set(false),
|
||||
platform_mac: ActiveValue::set(false),
|
||||
platform_windows: ActiveValue::set(false),
|
||||
|
@ -873,26 +889,6 @@ impl Database {
|
|||
let signup = signup.update(&tx).await?;
|
||||
|
||||
if let Some(inviting_user_id) = signup.inviting_user_id {
|
||||
let result = user::Entity::update_many()
|
||||
.filter(
|
||||
user::Column::Id
|
||||
.eq(inviting_user_id)
|
||||
.and(user::Column::InviteCount.gt(0)),
|
||||
)
|
||||
.col_expr(
|
||||
user::Column::InviteCount,
|
||||
Expr::col(user::Column::InviteCount).sub(1),
|
||||
)
|
||||
.exec(&tx)
|
||||
.await?;
|
||||
|
||||
if result.rows_affected == 0 {
|
||||
Err(Error::Http(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"no invites remaining".to_string(),
|
||||
))?;
|
||||
}
|
||||
|
||||
contact::Entity::insert(contact::ActiveModel {
|
||||
user_id_a: ActiveValue::set(inviting_user_id),
|
||||
user_id_b: ActiveValue::set(user.id),
|
||||
|
|
|
@ -20,6 +20,7 @@ pub struct Model {
|
|||
pub platform_unknown: bool,
|
||||
pub editor_features: Option<Vec<String>>,
|
||||
pub programming_languages: Option<Vec<String>>,
|
||||
pub added_to_mailing_list: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
|
@ -27,7 +28,7 @@ pub enum Relation {}
|
|||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Invite {
|
||||
pub email_address: String,
|
||||
pub email_confirmation_code: String,
|
||||
|
@ -42,6 +43,7 @@ pub struct NewSignup {
|
|||
pub editor_features: Vec<String>,
|
||||
pub programming_languages: Vec<String>,
|
||||
pub device_id: Option<String>,
|
||||
pub added_to_mailing_list: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, FromQueryResult)]
|
||||
|
|
|
@ -667,19 +667,29 @@ async fn test_signups() {
|
|||
let test_db = TestDb::postgres(build_background_executor());
|
||||
let db = test_db.db();
|
||||
|
||||
// people sign up on the waitlist
|
||||
for i in 0..8 {
|
||||
db.create_signup(NewSignup {
|
||||
email_address: format!("person-{i}@example.com"),
|
||||
let usernames = (0..8).map(|i| format!("person-{i}")).collect::<Vec<_>>();
|
||||
|
||||
let all_signups = usernames
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, username)| NewSignup {
|
||||
email_address: format!("{username}@example.com"),
|
||||
platform_mac: true,
|
||||
platform_linux: i % 2 == 0,
|
||||
platform_windows: i % 4 == 0,
|
||||
editor_features: vec!["speed".into()],
|
||||
programming_languages: vec!["rust".into(), "c".into()],
|
||||
device_id: Some(format!("device_id_{i}")),
|
||||
added_to_mailing_list: i != 0, // One user failed to subscribe
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
.collect::<Vec<NewSignup>>();
|
||||
|
||||
// people sign up on the waitlist
|
||||
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!(
|
||||
|
@ -702,9 +712,9 @@ async fn test_signups() {
|
|||
assert_eq!(
|
||||
addresses,
|
||||
&[
|
||||
"person-0@example.com",
|
||||
"person-1@example.com",
|
||||
"person-2@example.com"
|
||||
all_signups[0].email_address.as_str(),
|
||||
all_signups[1].email_address.as_str(),
|
||||
all_signups[2].email_address.as_str()
|
||||
]
|
||||
);
|
||||
assert_ne!(
|
||||
|
@ -728,9 +738,9 @@ async fn test_signups() {
|
|||
assert_eq!(
|
||||
addresses,
|
||||
&[
|
||||
"person-3@example.com",
|
||||
"person-4@example.com",
|
||||
"person-5@example.com"
|
||||
all_signups[3].email_address.as_str(),
|
||||
all_signups[4].email_address.as_str(),
|
||||
all_signups[5].email_address.as_str()
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -756,11 +766,10 @@ async fn test_signups() {
|
|||
} = db
|
||||
.create_user_from_invite(
|
||||
&Invite {
|
||||
email_address: signups_batch1[0].email_address.clone(),
|
||||
email_confirmation_code: signups_batch1[0].email_confirmation_code.clone(),
|
||||
..signups_batch1[0].clone()
|
||||
},
|
||||
NewUserParams {
|
||||
github_login: "person-0".into(),
|
||||
github_login: usernames[0].clone(),
|
||||
github_user_id: 0,
|
||||
invite_count: 5,
|
||||
},
|
||||
|
@ -770,8 +779,11 @@ async fn test_signups() {
|
|||
.unwrap();
|
||||
let user = db.get_user_by_id(user_id).await.unwrap().unwrap();
|
||||
assert!(inviting_user_id.is_none());
|
||||
assert_eq!(user.github_login, "person-0");
|
||||
assert_eq!(user.email_address.as_deref(), Some("person-0@example.com"));
|
||||
assert_eq!(user.github_login, usernames[0]);
|
||||
assert_eq!(
|
||||
user.email_address,
|
||||
Some(all_signups[0].email_address.clone())
|
||||
);
|
||||
assert_eq!(user.invite_count, 5);
|
||||
assert_eq!(signup_device_id.unwrap(), "device_id_0");
|
||||
|
||||
|
@ -799,7 +811,7 @@ async fn test_signups() {
|
|||
email_confirmation_code: "the-wrong-code".to_string(),
|
||||
},
|
||||
NewUserParams {
|
||||
github_login: "person-1".into(),
|
||||
github_login: usernames[1].clone(),
|
||||
github_user_id: 2,
|
||||
invite_count: 5,
|
||||
},
|
||||
|
|
|
@ -5566,6 +5566,13 @@ async fn test_random_collaboration(
|
|||
guest_client.username,
|
||||
id
|
||||
);
|
||||
assert_eq!(
|
||||
guest_snapshot.abs_path(),
|
||||
host_snapshot.abs_path(),
|
||||
"{} has different abs path than the host for worktree {}",
|
||||
guest_client.username,
|
||||
id
|
||||
);
|
||||
assert_eq!(
|
||||
guest_snapshot.entries(false).collect::<Vec<_>>(),
|
||||
host_snapshot.entries(false).collect::<Vec<_>>(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue