Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

let invited members access OrgMemberHeaders #5461

Merged
merged 1 commit into from
Jan 27, 2025
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
53 changes: 37 additions & 16 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,29 @@ pub struct OrgHeaders {
pub device: Device,
pub user: User,
pub membership_type: MembershipType,
pub membership_status: MembershipStatus,
pub membership: Membership,
pub ip: ClientIp,
}

impl OrgHeaders {
fn is_member(&self) -> bool {
// NOTE: we don't care about MembershipStatus at the moment because this is only used
// where an invited, accepted or confirmed user is expected if this ever changes or
// if from_i32 is changed to return Some(Revoked) this check needs to be changed accordingly
self.membership_type >= MembershipType::User
}
fn is_confirmed_and_admin(&self) -> bool {
self.membership_status == MembershipStatus::Confirmed && self.membership_type >= MembershipType::Admin
}
fn is_confirmed_and_manager(&self) -> bool {
self.membership_status == MembershipStatus::Confirmed && self.membership_type >= MembershipType::Manager
}
fn is_confirmed_and_owner(&self) -> bool {
self.membership_status == MembershipStatus::Confirmed && self.membership_type == MembershipType::Owner
}
}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for OrgHeaders {
type Error = &'static str;
Expand Down Expand Up @@ -574,29 +593,31 @@ impl<'r> FromRequest<'r> for OrgHeaders {
};

let user = headers.user;
let membership = match Membership::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await {
Some(member) => {
if member.status == MembershipStatus::Confirmed as i32 {
member
} else {
err_handler!("The current user isn't confirmed member of the organization")
}
}
None => err_handler!("The current user isn't member of the organization"),
let Some(membership) = Membership::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await else {
err_handler!("The current user isn't member of the organization");
};

Outcome::Success(Self {
host: headers.host,
device: headers.device,
user,
membership_type: {
if let Some(org_usr_type) = MembershipType::from_i32(membership.atype) {
org_usr_type
if let Some(member_type) = MembershipType::from_i32(membership.atype) {
member_type
} else {
// This should only happen if the DB is corrupted
err_handler!("Unknown user type in the database")
}
},
membership_status: {
if let Some(member_status) = MembershipStatus::from_i32(membership.status) {
// NOTE: add additional check for revoked if from_i32 is ever changed
// to return Revoked status.
member_status
} else {
err_handler!("User status is either revoked or invalid.")
}
},
membership,
ip: headers.ip,
})
Expand All @@ -621,7 +642,7 @@ impl<'r> FromRequest<'r> for AdminHeaders {

async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = try_outcome!(OrgHeaders::from_request(request).await);
if headers.membership_type >= MembershipType::Admin {
if headers.is_confirmed_and_admin() {
Outcome::Success(Self {
host: headers.host,
device: headers.device,
Expand Down Expand Up @@ -683,7 +704,7 @@ impl<'r> FromRequest<'r> for ManagerHeaders {

async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = try_outcome!(OrgHeaders::from_request(request).await);
if headers.membership_type >= MembershipType::Manager {
if headers.is_confirmed_and_manager() {
match get_col_id(request) {
Some(col_id) => {
let mut conn = match DbConn::from_request(request).await {
Expand Down Expand Up @@ -738,7 +759,7 @@ impl<'r> FromRequest<'r> for ManagerHeadersLoose {

async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = try_outcome!(OrgHeaders::from_request(request).await);
if headers.membership_type >= MembershipType::Manager {
if headers.is_confirmed_and_manager() {
Outcome::Success(Self {
host: headers.host,
device: headers.device,
Expand Down Expand Up @@ -801,7 +822,7 @@ impl<'r> FromRequest<'r> for OwnerHeaders {

async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = try_outcome!(OrgHeaders::from_request(request).await);
if headers.membership_type == MembershipType::Owner {
if headers.is_confirmed_and_owner() {
Outcome::Success(Self {
device: headers.device,
user: headers.user,
Expand All @@ -826,7 +847,7 @@ impl<'r> FromRequest<'r> for OrgMemberHeaders {

async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = try_outcome!(OrgHeaders::from_request(request).await);
if headers.membership_type >= MembershipType::User {
if headers.is_member() {
Outcome::Success(Self {
host: headers.host,
user: headers.user,
Expand Down
14 changes: 14 additions & 0 deletions src/db/models/organization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,27 @@ db_object! {
}

// https://github.com/bitwarden/server/blob/b86a04cef9f1e1b82cf18e49fc94e017c641130c/src/Core/Enums/OrganizationUserStatusType.cs
#[derive(PartialEq)]
pub enum MembershipStatus {
Revoked = -1,
Invited = 0,
Accepted = 1,
Confirmed = 2,
}

impl MembershipStatus {
pub fn from_i32(status: i32) -> Option<Self> {
match status {
0 => Some(Self::Invited),
1 => Some(Self::Accepted),
2 => Some(Self::Confirmed),
// NOTE: we don't care about revoked members where this is used
// if this ever changes also adapt the OrgHeaders check.
_ => None,
}
}
}

#[derive(Copy, Clone, PartialEq, Eq, num_derive::FromPrimitive)]
pub enum MembershipType {
Owner = 0,
Expand Down