vortex_sdk/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// User type for JWT generation
5#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct User {
8    pub id: String,
9    pub email: String,
10    #[serde(skip_serializing_if = "Option::is_none")]
11    pub admin_scopes: Option<Vec<String>>,
12}
13
14impl User {
15    pub fn new(id: &str, email: &str) -> Self {
16        Self {
17            id: id.to_string(),
18            email: email.to_string(),
19            admin_scopes: None,
20        }
21    }
22
23    pub fn with_admin_scopes(mut self, scopes: Vec<String>) -> Self {
24        self.admin_scopes = Some(scopes);
25        self
26    }
27}
28
29/// Identifier for a user (email, sms, etc.)
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct Identifier {
32    #[serde(rename = "type")]
33    pub identifier_type: String,
34    pub value: String,
35}
36
37impl Identifier {
38    pub fn new(identifier_type: &str, value: &str) -> Self {
39        Self {
40            identifier_type: identifier_type.to_string(),
41            value: value.to_string(),
42        }
43    }
44}
45
46/// Group information for JWT generation (input)
47/// Supports both 'id' (legacy) and 'groupId' (preferred) for backward compatibility
48#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub struct Group {
51    #[serde(rename = "type")]
52    pub group_type: String,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub id: Option<String>,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub group_id: Option<String>,
57    pub name: String,
58}
59
60impl Group {
61    pub fn new(group_type: &str, name: &str) -> Self {
62        Self {
63            group_type: group_type.to_string(),
64            id: None,
65            group_id: None,
66            name: name.to_string(),
67        }
68    }
69
70    pub fn with_id(mut self, id: &str) -> Self {
71        self.id = Some(id.to_string());
72        self
73    }
74
75    pub fn with_group_id(mut self, group_id: &str) -> Self {
76        self.group_id = Some(group_id.to_string());
77        self
78    }
79}
80
81/// Invitation group from API responses
82/// This matches the MemberGroups table structure from the API
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct InvitationGroup {
86    /// Vortex internal UUID
87    pub id: String,
88    /// Vortex account ID
89    pub account_id: String,
90    /// Customer's group ID (the ID they provided to Vortex)
91    pub group_id: String,
92    /// Group type (e.g., "workspace", "team")
93    #[serde(rename = "type")]
94    pub group_type: String,
95    /// Group name
96    pub name: String,
97    /// ISO 8601 timestamp when the group was created
98    pub created_at: String,
99}
100
101/// Invitation target (email or sms)
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct InvitationTarget {
104    #[serde(rename = "type")]
105    pub target_type: String,
106    pub value: String,
107}
108
109impl InvitationTarget {
110    pub fn new(target_type: &str, value: &str) -> Self {
111        Self {
112            target_type: target_type.to_string(),
113            value: value.to_string(),
114        }
115    }
116}
117
118/// Invitation acceptance information
119#[derive(Debug, Clone, Serialize, Deserialize)]
120#[serde(rename_all = "camelCase")]
121pub struct InvitationAcceptance {
122    pub id: Option<String>,
123    pub account_id: Option<String>,
124    pub project_id: Option<String>,
125    pub accepted_at: Option<String>,
126    pub target: Option<InvitationTarget>,
127}
128
129/// Full invitation details
130#[derive(Debug, Clone, Serialize, Deserialize)]
131#[serde(rename_all = "camelCase")]
132pub struct Invitation {
133    #[serde(default)]
134    pub id: String,
135    #[serde(default)]
136    pub account_id: String,
137    #[serde(default)]
138    pub click_throughs: u32,
139    pub configuration_attributes: Option<HashMap<String, serde_json::Value>>,
140    pub attributes: Option<HashMap<String, serde_json::Value>>,
141    #[serde(default)]
142    pub created_at: String,
143    #[serde(default)]
144    pub deactivated: bool,
145    #[serde(default)]
146    pub delivery_count: u32,
147    #[serde(default)]
148    pub delivery_types: Vec<String>,
149    #[serde(default)]
150    pub foreign_creator_id: String,
151    #[serde(default)]
152    pub invitation_type: String,
153    pub modified_at: Option<String>,
154    #[serde(default)]
155    pub status: String,
156    #[serde(default)]
157    pub target: Vec<InvitationTarget>,
158    #[serde(default)]
159    pub views: u32,
160    #[serde(default)]
161    pub widget_configuration_id: String,
162    #[serde(default)]
163    pub project_id: String,
164    #[serde(default)]
165    pub groups: Vec<InvitationGroup>,
166    #[serde(default)]
167    pub accepts: Vec<InvitationAcceptance>,
168    pub expired: bool,
169    #[serde(skip_serializing_if = "Option::is_none")]
170    pub expires: Option<String>,
171}
172
173/// Response containing multiple invitations
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct InvitationsResponse {
176    pub invitations: Option<Vec<Invitation>>,
177}