Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/data-model/src/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub struct User {
pub locked_at: Option<DateTime<Utc>>,
pub deactivated_at: Option<DateTime<Utc>>,
pub can_request_admin: bool,
pub is_guest: bool,
}

impl User {
Expand All @@ -43,6 +44,7 @@ impl User {
locked_at: None,
deactivated_at: None,
can_request_admin: false,
is_guest: false,
}]
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/handlers/src/admin/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub struct User {

/// Whether the user can request admin privileges.
admin: bool,

/// Whether the user was a guest before migrating to MAS,
legacy_guest: bool,
}

impl User {
Expand All @@ -65,6 +68,7 @@ impl User {
locked_at: None,
deactivated_at: None,
admin: false,
legacy_guest: false,
},
Self {
id: Ulid::from_bytes([0x02; 16]),
Expand All @@ -73,6 +77,7 @@ impl User {
locked_at: None,
deactivated_at: None,
admin: true,
legacy_guest: false,
},
Self {
id: Ulid::from_bytes([0x03; 16]),
Expand All @@ -81,6 +86,7 @@ impl User {
locked_at: Some(DateTime::default()),
deactivated_at: None,
admin: false,
legacy_guest: true,
},
]
}
Expand All @@ -95,6 +101,7 @@ impl From<mas_data_model::User> for User {
locked_at: user.locked_at,
deactivated_at: user.deactivated_at,
admin: user.can_request_admin,
legacy_guest: user.is_guest,
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/handlers/src/admin/v1/users/deactivate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ mod tests {
"created_at": "2022-01-16T14:40:00Z",
"locked_at": null,
"deactivated_at": "2022-01-16T14:40:00Z",
"admin": false
"admin": false,
"legacy_guest": false
},
"links": {
"self": "/api/admin/v1/users/01FSHN9AG0MZAA6S4AF7CTV32E"
Expand Down Expand Up @@ -289,7 +290,8 @@ mod tests {
"created_at": "2022-01-16T14:40:00Z",
"locked_at": "2022-01-16T14:40:00Z",
"deactivated_at": "2022-01-16T14:41:00Z",
"admin": false
"admin": false,
"legacy_guest": false
},
"links": {
"self": "/api/admin/v1/users/01FSHN9AG0MZAA6S4AF7CTV32E"
Expand Down
14 changes: 14 additions & 0 deletions crates/handlers/src/admin/v1/users/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ pub struct FilterParams {
#[serde(rename = "filter[admin]")]
admin: Option<bool>,

/// Retrieve users with (or without) the `legacy_guest` flag set
#[serde(rename = "filter[legacy-guest]")]
legacy_guest: Option<bool>,

/// Retrieve the items with the given status
///
/// Defaults to retrieve all users, including locked ones.
Expand All @@ -75,6 +79,10 @@ impl std::fmt::Display for FilterParams {
write!(f, "{sep}filter[admin]={admin}")?;
sep = '&';
}
if let Some(legacy_guest) = self.legacy_guest {
write!(f, "{sep}filter[legacy-guest]={legacy_guest}")?;
sep = '&';
}
if let Some(status) = self.status {
write!(f, "{sep}filter[status]={status}")?;
sep = '&';
Expand Down Expand Up @@ -143,6 +151,12 @@ pub async fn handler(
None => filter,
};

let filter = match params.legacy_guest {
Some(true) => filter.guest_only(),
Some(false) => filter.non_guest_only(),
None => filter,
};

let filter = match params.status {
Some(UserStatus::Active) => filter.active_only(),
Some(UserStatus::Locked) => filter.locked_only(),
Expand Down
2 changes: 2 additions & 0 deletions crates/handlers/src/rate_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ mod tests {
locked_at: None,
deactivated_at: None,
can_request_admin: false,
is_guest: true,
};

let bob = User {
Expand All @@ -338,6 +339,7 @@ mod tests {
locked_at: None,
deactivated_at: None,
can_request_admin: false,
is_guest: true,
};

// Three times the same IP address should be allowed
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/storage-pg/src/iden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub enum Users {
LockedAt,
DeactivatedAt,
CanRequestAdmin,
IsGuest,
}

#[derive(sea_query::Iden)]
Expand Down
13 changes: 13 additions & 0 deletions crates/storage-pg/src/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ mod priv_ {
pub(super) locked_at: Option<DateTime<Utc>>,
pub(super) deactivated_at: Option<DateTime<Utc>>,
pub(super) can_request_admin: bool,
pub(super) is_guest: bool,
}
}

Expand All @@ -89,6 +90,7 @@ impl From<UserLookup> for User {
locked_at: value.locked_at,
deactivated_at: value.deactivated_at,
can_request_admin: value.can_request_admin,
is_guest: value.is_guest,
}
}
}
Expand All @@ -114,6 +116,10 @@ impl Filter for UserFilter<'_> {
.add_option(self.can_request_admin().map(|can_request_admin| {
Expr::col((Users::Table, Users::CanRequestAdmin)).eq(can_request_admin)
}))
.add_option(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the index on (is_guest, can_request_admin) intended to be a future PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but also low-priority for now, it is performant enough in most cases

self.is_guest()
.map(|is_guest| Expr::col((Users::Table, Users::IsGuest)).eq(is_guest)),
)
}
}

Expand All @@ -140,6 +146,7 @@ impl UserRepository for PgUserRepository<'_> {
, locked_at
, deactivated_at
, can_request_admin
, is_guest
FROM users
WHERE user_id = $1
"#,
Expand Down Expand Up @@ -176,6 +183,7 @@ impl UserRepository for PgUserRepository<'_> {
, locked_at
, deactivated_at
, can_request_admin
, is_guest
FROM users
WHERE LOWER(username) = LOWER($1)
"#,
Expand Down Expand Up @@ -249,6 +257,7 @@ impl UserRepository for PgUserRepository<'_> {
locked_at: None,
deactivated_at: None,
can_request_admin: false,
is_guest: false,
})
}

Expand Down Expand Up @@ -487,6 +496,10 @@ impl UserRepository for PgUserRepository<'_> {
Expr::col((Users::Table, Users::CanRequestAdmin)),
UserLookupIden::CanRequestAdmin,
)
.expr_as(
Expr::col((Users::Table, Users::IsGuest)),
UserLookupIden::IsGuest,
)
.from(Users::Table)
.apply_filter(filter)
.generate_pagination((Users::Table, Users::UserId), pagination)
Expand Down
7 changes: 7 additions & 0 deletions crates/storage-pg/src/user/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct SessionLookup {
user_locked_at: Option<DateTime<Utc>>,
user_deactivated_at: Option<DateTime<Utc>>,
user_can_request_admin: bool,
user_is_guest: bool,
}

impl TryFrom<SessionLookup> for BrowserSession {
Expand All @@ -76,6 +77,7 @@ impl TryFrom<SessionLookup> for BrowserSession {
locked_at: value.user_locked_at,
deactivated_at: value.user_deactivated_at,
can_request_admin: value.user_can_request_admin,
is_guest: value.user_is_guest,
};

Ok(BrowserSession {
Expand Down Expand Up @@ -201,6 +203,7 @@ impl BrowserSessionRepository for PgBrowserSessionRepository<'_> {
, u.locked_at AS "user_locked_at"
, u.deactivated_at AS "user_deactivated_at"
, u.can_request_admin AS "user_can_request_admin"
, u.is_guest AS "user_is_guest"
FROM user_sessions s
INNER JOIN users u
USING (user_id)
Expand Down Expand Up @@ -391,6 +394,10 @@ impl BrowserSessionRepository for PgBrowserSessionRepository<'_> {
Expr::col((Users::Table, Users::CanRequestAdmin)),
SessionLookupIden::UserCanRequestAdmin,
)
.expr_as(
Expr::col((Users::Table, Users::IsGuest)),
SessionLookupIden::UserIsGuest,
)
.from(UserSessions::Table)
.inner_join(
Users::Table,
Expand Down
23 changes: 23 additions & 0 deletions crates/storage/src/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl UserState {
pub struct UserFilter<'a> {
state: Option<UserState>,
can_request_admin: Option<bool>,
is_guest: Option<bool>,
_phantom: std::marker::PhantomData<&'a ()>,
}

Expand Down Expand Up @@ -120,6 +121,20 @@ impl UserFilter<'_> {
self
}

/// Filter for guest users
#[must_use]
pub fn guest_only(mut self) -> Self {
self.is_guest = Some(true);
self
}

/// Filter for non-guest users
#[must_use]
pub fn non_guest_only(mut self) -> Self {
self.is_guest = Some(false);
self
}

/// Get the state filter
///
/// Returns [`None`] if no state filter was set
Expand All @@ -135,6 +150,14 @@ impl UserFilter<'_> {
pub fn can_request_admin(&self) -> Option<bool> {
self.can_request_admin
}

/// Get the is guest filter
///
/// Returns [`None`] if no is guest filter was set
#[must_use]
pub fn is_guest(&self) -> Option<bool> {
self.is_guest
}
}

/// A [`UserRepository`] helps interacting with [`User`] saved in the storage
Expand Down
Loading
Loading