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
12 changes: 12 additions & 0 deletions src/user_management/operations.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod accept_invitation;
mod authenticate_with_code;
mod authenticate_with_email_verification;
mod authenticate_with_magic_auth;
Expand All @@ -9,8 +10,10 @@ mod create_password_reset;
mod create_user;
mod delete_user;
mod enroll_auth_factor;
mod find_invitation_by_token;
mod get_authorization_url;
mod get_email_verification;
mod get_invitation;
mod get_jwks;
mod get_jwks_url;
mod get_logout_url;
Expand All @@ -20,10 +23,14 @@ mod get_user;
mod get_user_by_external_id;
mod get_user_identities;
mod list_auth_factors;
mod list_invitations;
mod list_users;
mod reset_password;
mod revoke_invitation;
mod send_invitation;
mod update_user;

pub use accept_invitation::*;
pub use authenticate_with_code::*;
pub use authenticate_with_email_verification::*;
pub use authenticate_with_magic_auth::*;
Expand All @@ -35,8 +42,10 @@ pub use create_password_reset::*;
pub use create_user::*;
pub use delete_user::*;
pub use enroll_auth_factor::*;
pub use find_invitation_by_token::*;
pub use get_authorization_url::*;
pub use get_email_verification::*;
pub use get_invitation::*;
pub use get_jwks::*;
pub use get_jwks_url::*;
pub use get_logout_url::*;
Expand All @@ -46,6 +55,9 @@ pub use get_user::*;
pub use get_user_by_external_id::*;
pub use get_user_identities::*;
pub use list_auth_factors::*;
pub use list_invitations::*;
pub use list_users::*;
pub use reset_password::*;
pub use revoke_invitation::*;
pub use send_invitation::*;
pub use update_user::*;
128 changes: 128 additions & 0 deletions src/user_management/operations/accept_invitation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use async_trait::async_trait;
use thiserror::Error;

use crate::user_management::{Invitation, InvitationId, UserManagement};
use crate::{ResponseExt, WorkOsError, WorkOsResult};

/// An error returned from [`AcceptInvitation`].
#[derive(Debug, Error)]
pub enum AcceptInvitationError {}

impl From<AcceptInvitationError> for WorkOsError<AcceptInvitationError> {
fn from(err: AcceptInvitationError) -> Self {
Self::Operation(err)
}
}

/// [WorkOS Docs: Accept an invitation](https://workos.com/docs/reference/user-management/invitation/accept)
#[async_trait]
pub trait AcceptInvitation {
/// Accepts an invitation and, if linked to an organization, activates the user's membership in that organization.
///
/// [WorkOS Docs: Accept an invitation](https://workos.com/docs/reference/user-management/invitation/accept)
///
/// # Examples
///
/// ```
/// # use workos_sdk::WorkOsResult;
/// # use workos_sdk::user_management::*;
/// use workos_sdk::{ApiKey, WorkOs};
///
/// # async fn run() -> WorkOsResult<(), AcceptInvitationError> {
/// let workos = WorkOs::new(&ApiKey::from("sk_example_123456789"));
///
/// let invitation = workos
/// .user_management()
/// .accept_invitation(&InvitationId::from("invitation_01E4ZCR3C56J083X43JQXF3JK5"))
/// .await?;
/// # Ok(())
/// # }
/// ```
async fn accept_invitation(
&self,
invitation_id: &InvitationId,
) -> WorkOsResult<Invitation, AcceptInvitationError>;
}

#[async_trait]
impl AcceptInvitation for UserManagement<'_> {
async fn accept_invitation(
&self,
invitation_id: &InvitationId,
) -> WorkOsResult<Invitation, AcceptInvitationError> {
let url = self.workos.base_url().join(&format!(
"/user_management/invitations/{invitation_id}/accept"
))?;
let user = self
.workos
.client()
.post(url)
.bearer_auth(self.workos.key())
.send()
.await?
.handle_unauthorized_or_generic_error()?
.json::<Invitation>()
.await?;

Ok(user)
}
}

#[cfg(test)]
mod test {
use serde_json::json;
use tokio;

use crate::user_management::InvitationId;
use crate::{ApiKey, WorkOs};

use super::*;

#[tokio::test]
async fn it_calls_the_accept_invitation_endpoint() {
let mut server = mockito::Server::new_async().await;

let workos = WorkOs::builder(&ApiKey::from("sk_example_123456789"))
.base_url(&server.url())
.unwrap()
.build();

server
.mock("POST", "/user_management/invitations/invitation_01E4ZCR3C56J083X43JQXF3JK5/accept")
.match_header("Authorization", "Bearer sk_example_123456789")
.with_status(200)
.with_body(
json!({
"object": "invitation",
"id": "invitation_01E4ZCR3C56J083X43JQXF3JK5",
"email": "[email protected]",
"state": "accepted",
"accepted_at": "2021-06-27T19:07:33.155Z",
"revoked_at": null,
"expires_at": "2021-07-01T19:07:33.155Z",
"token": "Z1uX3RbwcIl5fIGJJJCXXisdI",
"accept_invitation_url": "https://your-app.com/invite?invitation_token=Z1uX3RbwcIl5fIGJJJCXXisdI",
"organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5",
"inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3",
"accepted_user_id": "user_01JBJDMMV04RSWPG30MQE8ADFV",
"created_at": "2021-06-25T19:07:33.155Z",
"updated_at": "2021-06-25T19:07:33.155Z"
})
.to_string(),
)
.create_async()
.await;

let invitation = workos
.user_management()
.accept_invitation(&InvitationId::from("invitation_01E4ZCR3C56J083X43JQXF3JK5"))
.await
.unwrap();

assert_eq!(
invitation.id,
InvitationId::from("invitation_01E4ZCR3C56J083X43JQXF3JK5")
);
assert!(invitation.accepted_at.is_some());
}
}
2 changes: 0 additions & 2 deletions src/user_management/operations/create_magic_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ pub trait CreateMagicAuth {
/// # Examples
///
/// ```
/// use std::collections::HashSet;
///
/// # use workos_sdk::WorkOsResult;
/// # use workos_sdk::user_management::*;
/// use workos_sdk::{ApiKey, WorkOs};
Expand Down
2 changes: 0 additions & 2 deletions src/user_management/operations/create_password_reset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ pub trait CreatePasswordReset {
/// # Examples
///
/// ```
/// use std::collections::HashSet;
///
/// # use workos_sdk::WorkOsResult;
/// # use workos_sdk::user_management::*;
/// use workos_sdk::{ApiKey, WorkOs};
Expand Down
2 changes: 0 additions & 2 deletions src/user_management/operations/create_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ pub trait CreateUser {
/// # Examples
///
/// ```
/// use std::collections::HashSet;
///
/// # use workos_sdk::WorkOsResult;
/// # use workos_sdk::user_management::*;
/// use workos_sdk::{ApiKey, WorkOs};
Expand Down
2 changes: 0 additions & 2 deletions src/user_management/operations/enroll_auth_factor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ pub trait EnrollAuthFactor {
/// # Examples
///
/// ```
/// use std::collections::HashSet;
///
/// # use workos_sdk::WorkOsResult;
/// # use workos_sdk::user_management::*;
/// use workos_sdk::{ApiKey, WorkOs};
Expand Down
129 changes: 129 additions & 0 deletions src/user_management/operations/find_invitation_by_token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use async_trait::async_trait;
use thiserror::Error;

use crate::user_management::{Invitation, InvitationToken, UserManagement};
use crate::{ResponseExt, WorkOsError, WorkOsResult};

/// An error returned from [`FindInvitationByToken`].
#[derive(Debug, Error)]
pub enum FindInvitationByTokenError {}

impl From<FindInvitationByTokenError> for WorkOsError<FindInvitationByTokenError> {
fn from(err: FindInvitationByTokenError) -> Self {
Self::Operation(err)
}
}

/// [WorkOS Docs: Find an invitation by token](https://workos.com/docs/reference/user-management/invitation/find-by-token)
#[async_trait]
pub trait FindInvitationByToken {
/// Retrieve an existing invitation using the token.
///
/// [WorkOS Docs: Find an invitation by token](https://workos.com/docs/reference/user-management/invitation/find-by-token)
///
/// # Examples
///
/// ```
/// # use workos_sdk::WorkOsResult;
/// # use workos_sdk::user_management::*;
/// use workos_sdk::{ApiKey, WorkOs};
///
/// # async fn run() -> WorkOsResult<(), FindInvitationByTokenError> {
/// let workos = WorkOs::new(&ApiKey::from("sk_example_123456789"));
///
/// let invitation = workos
/// .user_management()
/// .find_invitation_by_token(&InvitationToken::from("Z1uX3RbwcIl5fIGJJJCXXisdI"))
/// .await?;
/// # Ok(())
/// # }
/// ```
async fn find_invitation_by_token(
&self,
token: &InvitationToken,
) -> WorkOsResult<Invitation, FindInvitationByTokenError>;
}

#[async_trait]
impl FindInvitationByToken for UserManagement<'_> {
async fn find_invitation_by_token(
&self,
token: &InvitationToken,
) -> WorkOsResult<Invitation, FindInvitationByTokenError> {
let url = self
.workos
.base_url()
.join(&format!("/user_management/invitations/by_token/{token}"))?;
let organization = self
.workos
.client()
.get(url)
.bearer_auth(self.workos.key())
.send()
.await?
.handle_unauthorized_or_generic_error()?
.json::<Invitation>()
.await?;

Ok(organization)
}
}

#[cfg(test)]
mod test {
use serde_json::json;
use tokio;

use crate::{ApiKey, WorkOs, user_management::InvitationId};

use super::*;

#[tokio::test]
async fn it_calls_the_find_invitation_by_token_endpoint() {
let mut server = mockito::Server::new_async().await;

let workos = WorkOs::builder(&ApiKey::from("sk_example_123456789"))
.base_url(&server.url())
.unwrap()
.build();

server
.mock(
"GET",
"/user_management/invitations/by_token/Z1uX3RbwcIl5fIGJJJCXXisdI",
)
.match_header("Authorization", "Bearer sk_example_123456789")
.with_status(200)
.with_body(
json!({
"object": "invitation",
"id": "invitation_01E4ZCR3C56J083X43JQXF3JK5",
"email": "[email protected]",
"state": "pending",
"accepted_at": null,
"revoked_at": null,
"expires_at": "2021-07-01T19:07:33.155Z",
"token": "Z1uX3RbwcIl5fIGJJJCXXisdI",
"accept_invitation_url": "https://your-app.com/invite?invitation_token=Z1uX3RbwcIl5fIGJJJCXXisdI",
"organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5",
"inviter_user_id": "user_01HYGBX8ZGD19949T3BM4FW1C3",
"created_at": "2021-06-25T19:07:33.155Z",
"updated_at": "2021-06-25T19:07:33.155Z"
})
.to_string(),
)
.create_async()
.await;

let invitation = workos
.user_management()
.find_invitation_by_token(&InvitationToken::from("Z1uX3RbwcIl5fIGJJJCXXisdI"))
.await
.unwrap();

assert_eq!(
invitation.id,
InvitationId::from("invitation_01E4ZCR3C56J083X43JQXF3JK5")
)
}
}
Loading