Skip to content

Commit ac204a3

Browse files
sharifhsn64bit
andauthored
Add support for organization API (#265)
* Implement `invites` * Consistently inline format * Implement `users` * Replace `InviteRole` with generic `OrganizationRole` * Implement `projects` * Update requests to use builder * Remove `default` from builder * Update `projects` to include verification information (https://help.openai.com/en/articles/9824607-api-platform-verifications) * Implement `project_users` --------- Co-authored-by: Himanshu Neema <[email protected]>
1 parent 6858399 commit ac204a3

File tree

11 files changed

+551
-0
lines changed

11 files changed

+551
-0
lines changed

async-openai/src/invites.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::{Invite, InviteDeleteResponse, InviteListResponse, InviteRequest},
7+
Client,
8+
};
9+
10+
/// Invite and manage invitations for an organization. Invited users are automatically added to the Default project.
11+
pub struct Invites<'c, C: Config> {
12+
client: &'c Client<C>,
13+
}
14+
15+
impl<'c, C: Config> Invites<'c, C> {
16+
pub fn new(client: &'c Client<C>) -> Self {
17+
Self { client }
18+
}
19+
20+
/// Returns a list of runs belonging to a thread.
21+
pub async fn list<Q>(&self, query: &Q) -> Result<InviteListResponse, OpenAIError>
22+
where
23+
Q: Serialize + ?Sized,
24+
{
25+
self.client
26+
.get_with_query("/organization/invites", query)
27+
.await
28+
}
29+
30+
/// Retrieves an invite.
31+
pub async fn retrieve(&self, invite_id: &str) -> Result<Invite, OpenAIError> {
32+
self.client
33+
.get(format!("/organization/invites/{invite_id}").as_str())
34+
.await
35+
}
36+
37+
/// Create an invite for a user to the organization. The invite must be accepted by the user before they have access to the organization.
38+
pub async fn create(&self, request: InviteRequest) -> Result<Invite, OpenAIError> {
39+
self.client.post("/organization/invites", request).await
40+
}
41+
42+
/// Delete an invite. If the invite has already been accepted, it cannot be deleted.
43+
pub async fn delete(&self, invite_id: &str) -> Result<InviteDeleteResponse, OpenAIError> {
44+
self.client
45+
.delete(format!("/organization/invites/{invite_id}").as_str())
46+
.await
47+
}
48+
}

async-openai/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,18 @@ pub mod error;
9191
mod file;
9292
mod fine_tuning;
9393
mod image;
94+
mod invites;
9495
mod message_files;
9596
mod messages;
9697
mod model;
9798
mod moderation;
99+
mod project_users;
100+
mod projects;
98101
mod runs;
99102
mod steps;
100103
mod threads;
101104
pub mod types;
105+
mod users;
102106
mod util;
103107
mod vector_store_file_batches;
104108
mod vector_store_files;
@@ -115,13 +119,17 @@ pub use embedding::Embeddings;
115119
pub use file::Files;
116120
pub use fine_tuning::FineTuning;
117121
pub use image::Images;
122+
pub use invites::Invites;
118123
pub use message_files::MessageFiles;
119124
pub use messages::Messages;
120125
pub use model::Models;
121126
pub use moderation::Moderations;
127+
pub use project_users::ProjectUsers;
128+
pub use projects::Projects;
122129
pub use runs::Runs;
123130
pub use steps::Steps;
124131
pub use threads::Threads;
132+
pub use users::Users;
125133
pub use vector_store_file_batches::VectorStoreFileBatches;
126134
pub use vector_store_files::VectorStoreFiles;
127135
pub use vector_stores::VectorStores;

async-openai/src/project_users.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::{
7+
ProjectUser, ProjectUserCreateRequest, ProjectUserListResponse, ProjectUserUpdateRequest,
8+
},
9+
Client,
10+
};
11+
12+
/// Manage users within a project, including adding, updating roles, and removing users.
13+
/// Users cannot be removed from the Default project, unless they are being removed from the organization.
14+
pub struct ProjectUsers<'c, C: Config> {
15+
client: &'c Client<C>,
16+
}
17+
18+
impl<'c, C: Config> ProjectUsers<'c, C> {
19+
pub fn new(client: &'c Client<C>) -> Self {
20+
Self { client }
21+
}
22+
23+
/// Returns a list of users in the project.
24+
pub async fn list<Q>(
25+
&self,
26+
project_id: String,
27+
query: &Q,
28+
) -> Result<ProjectUserListResponse, OpenAIError>
29+
where
30+
Q: Serialize + ?Sized,
31+
{
32+
self.client
33+
.get_with_query(
34+
format!("/organization/projects/{project_id}/users").as_str(),
35+
query,
36+
)
37+
.await
38+
}
39+
40+
/// Adds a user to the project. Users must already be members of the organization to be added to a project.
41+
pub async fn create(
42+
&self,
43+
project_id: String,
44+
request: ProjectUserCreateRequest,
45+
) -> Result<ProjectUser, OpenAIError> {
46+
self.client
47+
.post(
48+
format!("/organization/projects/{project_id}/users").as_str(),
49+
request,
50+
)
51+
.await
52+
}
53+
54+
/// Retrieves a user in the project.
55+
pub async fn retrieve(
56+
&self,
57+
project_id: String,
58+
user_id: String,
59+
) -> Result<ProjectUser, OpenAIError> {
60+
self.client
61+
.get(format!("/organization/projects/{project_id}/users/{user_id}").as_str())
62+
.await
63+
}
64+
65+
/// Modifies a user's role in the project.
66+
pub async fn modify(
67+
&self,
68+
project_id: String,
69+
request: ProjectUserUpdateRequest,
70+
) -> Result<ProjectUser, OpenAIError> {
71+
self.client
72+
.post(
73+
format!("/organization/projects/{project_id}").as_str(),
74+
request,
75+
)
76+
.await
77+
}
78+
79+
/// Deletes a user from the project.
80+
pub async fn delete(
81+
&self,
82+
project_id: String,
83+
user_id: String,
84+
) -> Result<ProjectUser, OpenAIError> {
85+
self.client
86+
.delete(format!("/organization/projects/{project_id}/users/{user_id}").as_str())
87+
.await
88+
}
89+
}

async-openai/src/projects.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use serde::Serialize;
2+
3+
use crate::{
4+
config::Config,
5+
error::OpenAIError,
6+
types::{Project, ProjectCreateRequest, ProjectListResponse, ProjectUpdateRequest},
7+
Client,
8+
};
9+
10+
/// Manage the projects within an organization includes creation, updating, and archiving or projects.
11+
/// The Default project cannot be modified or archived.
12+
pub struct Projects<'c, C: Config> {
13+
client: &'c Client<C>,
14+
}
15+
16+
impl<'c, C: Config> Projects<'c, C> {
17+
pub fn new(client: &'c Client<C>) -> Self {
18+
Self { client }
19+
}
20+
21+
/// Returns a list of projects.
22+
pub async fn list<Q>(&self, query: &Q) -> Result<ProjectListResponse, OpenAIError>
23+
where
24+
Q: Serialize + ?Sized,
25+
{
26+
self.client
27+
.get_with_query("/organization/projects", query)
28+
.await
29+
}
30+
31+
/// Create a new project in the organization. Projects can be created and archived, but cannot be deleted.
32+
pub async fn create(&self, request: ProjectCreateRequest) -> Result<Project, OpenAIError> {
33+
self.client.post("/organization/projects", request).await
34+
}
35+
36+
/// Retrieves a project.
37+
pub async fn retrieve(&self, project_id: String) -> Result<Project, OpenAIError> {
38+
self.client
39+
.get(format!("/organization/projects/{project_id}").as_str())
40+
.await
41+
}
42+
43+
/// Modifies a project in the organization.
44+
pub async fn modify(
45+
&self,
46+
project_id: String,
47+
request: ProjectUpdateRequest,
48+
) -> Result<Project, OpenAIError> {
49+
self.client
50+
.post(
51+
format!("/organization/projects/{project_id}").as_str(),
52+
request,
53+
)
54+
.await
55+
}
56+
57+
/// Archives a project in the organization. Archived projects cannot be used or updated.
58+
pub async fn archive(&self, project_id: String) -> Result<Project, OpenAIError> {
59+
self.client
60+
.post(format!("/organization/projects/{project_id}").as_str(), ())
61+
.await
62+
}
63+
}

async-openai/src/types/common.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
use std::path::PathBuf;
22

33
use bytes::Bytes;
4+
use serde::{Deserialize, Serialize};
45

56
#[derive(Debug, Clone, PartialEq)]
67
pub enum InputSource {
78
Path { path: PathBuf },
89
Bytes { filename: String, bytes: Bytes },
910
VecU8 { filename: String, vec: Vec<u8> },
1011
}
12+
13+
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
14+
#[serde(rename_all = "snake_case")]
15+
pub enum OrganizationRole {
16+
Owner,
17+
Reader,
18+
}

async-openai/src/types/invites.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use crate::types::OpenAIError;
2+
use derive_builder::Builder;
3+
use serde::{Deserialize, Serialize};
4+
5+
use super::OrganizationRole;
6+
7+
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
8+
#[serde(rename_all = "snake_case")]
9+
pub enum InviteStatus {
10+
Accepted,
11+
Expired,
12+
Pending,
13+
}
14+
15+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Builder)]
16+
#[builder(name = "ProjectCreateRequestArgs")]
17+
#[builder(pattern = "mutable")]
18+
#[builder(setter(into, strip_option))]
19+
#[builder(derive(Debug))]
20+
#[builder(build_fn(error = "OpenAIError"))]
21+
#[serde(rename_all = "snake_case")]
22+
pub struct InviteRequest {
23+
email: String,
24+
role: OrganizationRole,
25+
}
26+
27+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
28+
#[serde(rename_all = "snake_case")]
29+
pub struct InviteListResponse {
30+
object: String,
31+
data: Vec<Invite>,
32+
first_id: Option<String>,
33+
last_id: Option<String>,
34+
has_more: Option<bool>,
35+
}
36+
37+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
38+
#[serde(rename_all = "snake_case")]
39+
pub struct InviteDeleteResponse {
40+
/// The object type, which is always `organization.invite.deleted`
41+
object: String,
42+
id: String,
43+
deleted: bool,
44+
}
45+
46+
/// Represents an individual `invite` to the organization.
47+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
48+
#[serde(rename_all = "snake_case")]
49+
pub struct Invite {
50+
/// The object type, which is always `organization.invite`
51+
object: String,
52+
/// The identifier, which can be referenced in API endpoints
53+
id: String,
54+
/// The email address of the individual to whom the invite was sent
55+
email: String,
56+
/// `owner` or `reader`
57+
role: OrganizationRole,
58+
/// `accepted`, `expired`, or `pending`
59+
status: InviteStatus,
60+
/// The Unix timestamp (in seconds) of when the invite was sent.
61+
invited_at: u32,
62+
/// The Unix timestamp (in seconds) of when the invite expires.
63+
expires_at: u32,
64+
/// The Unix timestamp (in seconds) of when the invite was accepted.
65+
accepted_at: u32,
66+
}

async-openai/src/types/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,20 @@ mod embedding;
1313
mod file;
1414
mod fine_tuning;
1515
mod image;
16+
mod invites;
1617
mod message;
1718
mod message_file;
1819
mod model;
1920
mod moderation;
21+
mod project_users;
22+
mod projects;
2023
#[cfg_attr(docsrs, doc(cfg(feature = "realtime")))]
2124
#[cfg(feature = "realtime")]
2225
pub mod realtime;
2326
mod run;
2427
mod step;
2528
mod thread;
29+
mod users;
2630
mod vector_store;
2731

2832
pub use assistant::*;
@@ -37,13 +41,17 @@ pub use embedding::*;
3741
pub use file::*;
3842
pub use fine_tuning::*;
3943
pub use image::*;
44+
pub use invites::*;
4045
pub use message::*;
4146
pub use message_file::*;
4247
pub use model::*;
4348
pub use moderation::*;
49+
pub use project_users::*;
50+
pub use projects::*;
4451
pub use run::*;
4552
pub use step::*;
4653
pub use thread::*;
54+
pub use users::*;
4755
pub use vector_store::*;
4856

4957
mod impls;

0 commit comments

Comments
 (0)