Skip to content

Commit 06a8430

Browse files
authored
Merge pull request #10565 from Turbo87/owner-deps
models/owners: Remove `App` dependency
2 parents 3b294fe + 7b58aa2 commit 06a8430

File tree

2 files changed

+65
-71
lines changed

2 files changed

+65
-71
lines changed

src/controllers/krate/owners.rs

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ async fn modify_owners(
244244
)),
245245

246246
// An opaque error occurred.
247+
Err(OwnerAddError::Diesel(e)) => return Err(e.into()),
247248
Err(OwnerAddError::AppError(e)) => return Err(e),
248249
}
249250
}
@@ -290,56 +291,78 @@ async fn add_owner(
290291
krate: &Crate,
291292
login: &str,
292293
) -> Result<NewOwnerInvite, OwnerAddError> {
293-
use diesel::insert_into;
294-
295-
let owner = Owner::find_or_create_by_login(app, conn, req_user, login).await?;
296-
match owner {
297-
// Users are invited and must accept before being added
298-
Owner::User(user) => {
299-
let expires_at = Utc::now() + app.config.ownership_invitations_expiration;
300-
let invite = NewCrateOwnerInvitation {
301-
invited_user_id: user.id,
302-
invited_by_user_id: req_user.id,
303-
crate_id: krate.id,
304-
expires_at,
305-
};
306-
307-
let creation_ret = invite.create(conn).await.map_err(BoxedAppError::from)?;
308-
309-
match creation_ret {
310-
NewCrateOwnerInvitationOutcome::InviteCreated { plaintext_token } => {
311-
Ok(NewOwnerInvite::User(user, plaintext_token))
312-
}
313-
NewCrateOwnerInvitationOutcome::AlreadyExists => {
314-
Err(OwnerAddError::AlreadyInvited(Box::new(user)))
315-
}
316-
}
294+
if login.contains(':') {
295+
add_team_owner(app, conn, req_user, krate, login).await
296+
} else {
297+
invite_user_owner(app, conn, req_user, krate, login).await
298+
}
299+
}
300+
301+
async fn invite_user_owner(
302+
app: &App,
303+
conn: &mut AsyncPgConnection,
304+
req_user: &User,
305+
krate: &Crate,
306+
login: &str,
307+
) -> Result<NewOwnerInvite, OwnerAddError> {
308+
let user = User::find_by_login(conn, login)
309+
.await
310+
.optional()?
311+
.ok_or_else(|| bad_request(format_args!("could not find user with login `{login}`")))?;
312+
313+
// Users are invited and must accept before being added
314+
let expires_at = Utc::now() + app.config.ownership_invitations_expiration;
315+
let invite = NewCrateOwnerInvitation {
316+
invited_user_id: user.id,
317+
invited_by_user_id: req_user.id,
318+
crate_id: krate.id,
319+
expires_at,
320+
};
321+
322+
match invite.create(conn).await? {
323+
NewCrateOwnerInvitationOutcome::InviteCreated { plaintext_token } => {
324+
Ok(NewOwnerInvite::User(user, plaintext_token))
317325
}
318-
// Teams are added as owners immediately
319-
Owner::Team(team) => {
320-
insert_into(crate_owners::table)
321-
.values(&CrateOwner {
322-
crate_id: krate.id,
323-
owner_id: team.id,
324-
created_by: req_user.id,
325-
owner_kind: OwnerKind::Team,
326-
email_notifications: true,
327-
})
328-
.on_conflict(crate_owners::table.primary_key())
329-
.do_update()
330-
.set(crate_owners::deleted.eq(false))
331-
.execute(conn)
332-
.await
333-
.map_err(BoxedAppError::from)?;
334-
335-
Ok(NewOwnerInvite::Team(team))
326+
NewCrateOwnerInvitationOutcome::AlreadyExists => {
327+
Err(OwnerAddError::AlreadyInvited(Box::new(user)))
336328
}
337329
}
338330
}
339331

332+
async fn add_team_owner(
333+
app: &App,
334+
conn: &mut AsyncPgConnection,
335+
req_user: &User,
336+
krate: &Crate,
337+
login: &str,
338+
) -> Result<NewOwnerInvite, OwnerAddError> {
339+
// Always recreate teams to get the most up-to-date GitHub ID
340+
let team = Team::create_or_update(app, conn, login, req_user).await?;
341+
342+
// Teams are added as owners immediately, since the above call ensures
343+
// the user is a team member.
344+
diesel::insert_into(crate_owners::table)
345+
.values(&CrateOwner {
346+
crate_id: krate.id,
347+
owner_id: team.id,
348+
created_by: req_user.id,
349+
owner_kind: OwnerKind::Team,
350+
email_notifications: true,
351+
})
352+
.on_conflict(crate_owners::table.primary_key())
353+
.do_update()
354+
.set(crate_owners::deleted.eq(false))
355+
.execute(conn)
356+
.await?;
357+
358+
Ok(NewOwnerInvite::Team(team))
359+
}
360+
340361
/// Error results from a [`add_owner()`] model call.
341362
#[derive(Debug, Error)]
342363
enum OwnerAddError {
364+
#[error(transparent)]
365+
Diesel(#[from] diesel::result::Error),
343366
/// An opaque [`BoxedAppError`].
344367
#[error("{0}")] // AppError does not impl Error
345368
AppError(BoxedAppError),

src/models/owner.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
use crate::app::App;
2-
use crate::util::errors::{bad_request, AppResult};
31
use diesel::pg::Pg;
42
use diesel::prelude::*;
5-
use diesel_async::AsyncPgConnection;
63

74
use crate::models::{Crate, CrateOwnerInvitation, Team, User};
85
use crate::schema::crate_owners;
@@ -63,32 +60,6 @@ pub enum Owner {
6360
}
6461

6562
impl Owner {
66-
/// Finds the owner by name. Always recreates teams to get the most
67-
/// up-to-date GitHub ID. Fails out if the user isn't found in the
68-
/// database, the team isn't found on GitHub, or if the user isn't a member
69-
/// of the team on GitHub.
70-
///
71-
/// May be a user's GH login or a full team name. This is case
72-
/// sensitive.
73-
pub async fn find_or_create_by_login(
74-
app: &App,
75-
conn: &mut AsyncPgConnection,
76-
req_user: &User,
77-
name: &str,
78-
) -> AppResult<Owner> {
79-
if name.contains(':') {
80-
Ok(Owner::Team(
81-
Team::create_or_update(app, conn, name, req_user).await?,
82-
))
83-
} else {
84-
User::find_by_login(conn, name)
85-
.await
86-
.optional()?
87-
.map(Owner::User)
88-
.ok_or_else(|| bad_request(format_args!("could not find user with login `{name}`")))
89-
}
90-
}
91-
9263
pub fn kind(&self) -> i32 {
9364
match self {
9465
Owner::User(_) => OwnerKind::User as i32,

0 commit comments

Comments
 (0)