shuttle_common/models/
user.rs

1#[cfg(feature = "display")]
2use std::fmt::Write;
3
4use chrono::{DateTime, Utc};
5#[cfg(feature = "display")]
6use crossterm::style::Stylize;
7use serde::{Deserialize, Serialize};
8use strum::{EnumString, IntoStaticStr};
9
10#[derive(Debug, Deserialize, Serialize)]
11#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
12#[typeshare::typeshare]
13pub struct UserResponse {
14    pub id: String,
15    /// Auth0 id (deprecated)
16    pub name: Option<String>,
17    /// Auth0 id
18    pub auth0_id: Option<String>,
19    // deprecated
20    pub key: Option<String>,
21    pub account_tier: AccountTier,
22    pub subscriptions: Vec<Subscription>,
23    pub flags: Option<Vec<String>>,
24}
25
26impl UserResponse {
27    #[cfg(feature = "display")]
28    pub fn to_string_colored(&self) -> String {
29        let mut s = String::new();
30        writeln!(&mut s, "{}", "Account info:".bold()).unwrap();
31        writeln!(&mut s, "  User ID: {}", self.id).unwrap();
32        writeln!(&mut s, "  Account tier: {}", self.account_tier).unwrap();
33        if !self.subscriptions.is_empty() {
34            writeln!(&mut s, "  Subscriptions:").unwrap();
35            for sub in &self.subscriptions {
36                writeln!(
37                    &mut s,
38                    "    - {}: Type: {}, Quantity: {}, Created: {}, Updated: {}",
39                    sub.id, sub.r#type, sub.quantity, sub.created_at, sub.updated_at,
40                )
41                .unwrap();
42            }
43        }
44        if let Some(flags) = self.flags.as_ref() {
45            if !flags.is_empty() {
46                writeln!(&mut s, "  Feature flags:").unwrap();
47                for flag in flags {
48                    writeln!(&mut s, "    - {}", flag).unwrap();
49                }
50            }
51        }
52
53        s
54    }
55}
56
57#[derive(
58    // std
59    Clone,
60    Copy,
61    Debug,
62    Default,
63    Eq,
64    PartialEq,
65    Ord,
66    PartialOrd,
67    // serde
68    Deserialize,
69    Serialize,
70    // strum
71    EnumString,
72    IntoStaticStr,
73    strum::Display,
74)]
75#[serde(rename_all = "lowercase")]
76#[strum(serialize_all = "lowercase")]
77#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
78#[typeshare::typeshare]
79pub enum AccountTier {
80    #[default]
81    Basic,
82    /// A basic user that is pending a payment on the backend
83    PendingPaymentPro,
84    CancelledPro,
85    Pro,
86    Growth,
87    /// Higher limits and partial admin endpoint access
88    Employee,
89    /// Unlimited resources, full API access, admin endpoint access
90    Admin,
91}
92
93#[derive(Debug, Deserialize, Serialize)]
94#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
95#[typeshare::typeshare]
96pub struct Subscription {
97    pub id: String,
98    pub r#type: SubscriptionType,
99    pub quantity: i32,
100    pub created_at: DateTime<Utc>,
101    pub updated_at: DateTime<Utc>,
102}
103
104#[derive(Debug, Deserialize)]
105#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
106#[typeshare::typeshare]
107pub struct SubscriptionRequest {
108    pub id: String,
109    pub r#type: SubscriptionType,
110    pub quantity: i32,
111}
112
113#[derive(
114    // std
115    Clone,
116    Debug,
117    Eq,
118    PartialEq,
119    // serde
120    Deserialize,
121    Serialize,
122    // strum
123    EnumString,
124    strum::Display,
125    IntoStaticStr,
126)]
127#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
128#[serde(rename_all = "lowercase")]
129#[strum(serialize_all = "lowercase")]
130#[typeshare::typeshare]
131pub enum SubscriptionType {
132    Pro,
133    Rds,
134}