darkwing/database/team/
model.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Team-related database models and types.
//!
//! This module contains the core data structures for representing teams and
//! their settings in the database, including plan types and team configuration.

#![allow(
  non_snake_case,
  reason = "sqlx query_as macro does not support FromRow trait, so we cant use renamed fields. see https://github.com/launchbadge/sqlx/issues/1372 and https://github.com/launchbadge/sqlx/issues/514"
)]

use sqlx::types::time::PrimitiveDateTime;
use sqlx::FromRow;

/// Represents the simplified plan status of a team.
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum Plan {
  /// Free tier with limited features
  Free,
  /// Paid tier
  Paid,
}

impl From<Team> for Plan {
  /// Converts a Team instance into its corresponding Plan status.
  ///
  /// # Arguments
  ///
  /// * `value` - The team instance to convert from
  ///
  /// # Returns
  ///
  /// Returns `Plan::Free` for beta, unknown, and free plans with default
  /// limits. Returns `Plan::Paid` for all other combinations.
  fn from(value: Team) -> Self {
    match (value.plan, value.browserProfilesLimit) {
      (DbPlan::Beta | DbPlan::Unknown, _) => Self::Free,
      (DbPlan::Free, 10) => Self::Free,
      _ => Self::Paid,
    }
  }
}

/// Represents the detailed plan type stored in the database.
#[derive(sqlx::Type, Debug, Clone)]
#[sqlx(rename_all = "lowercase")]
pub enum DbPlan {
  /// Beta testing plan (stopped being in use, but still present as enum
  /// variant in DB)
  Beta,
  /// Trial period plan
  Trial,
  /// Free tier plan
  Free,
  /// Base paid plan
  Base,
  /// Team plan
  Team,
  /// Enterprise plan
  Enterprise,
  /// Custom configured plan
  Custom,
  /// Unknown plan type (fallback)
  Unknown,
}

impl From<String> for DbPlan {
  /// Converts a string into its corresponding DbPlan variant.
  ///
  /// # Returns
  ///
  /// Returns the matching DbPlan variant, or DbPlan::Unknown if no match is
  /// found. Unknown plans are reported to Sentry for monitoring.
  fn from(value: String) -> Self {
    match value.to_lowercase().as_str() {
      "beta" => Self::Beta,
      "trial" => Self::Trial,
      "free" => Self::Free,
      "base" => Self::Base,
      "team" => Self::Team,
      "enterprise" => Self::Enterprise,
      "custom" => Self::Custom,
      _ => {
        sentry::capture_message(
          &format!("Unknown plan: {value}"),
          sentry::Level::Warning,
        );
        Self::Unknown
      }
    }
  }
}

/// Represents a team entity in the database.
#[derive(FromRow, Debug, Clone)]
#[allow(unused)]
pub struct Team {
  /// Unique identifier for the team
  pub id: u64,
  /// ID of the user who owns this team
  pub userId: i64,
  /// Name of the team
  pub name: String,
  /// Current plan type of the team
  pub plan: DbPlan,
  /// Maximum number of users allowed in the team
  pub usersLimit: u64,
  /// Maximum number of browser profiles allowed for the team
  pub browserProfilesLimit: u64,
  /// Timestamp when the current subscription expires
  pub subscriptionExpiration: PrimitiveDateTime,
  /// Flag indicating if sync is enabled for the team
  pub syncEnabled: i8,
}

impl Team {
  /// Returns the simplified plan status for this team.
  ///
  /// # Returns
  ///
  /// Returns either Plan::Free or Plan::Paid based on the team's configuration.
  pub fn get_plan(&self) -> Plan {
    Plan::from(self.clone())
  }
}

/// Represents a team setting in the database.
#[derive(FromRow, Debug)]
#[allow(unused)]
pub struct Setting {
  /// The scope level of the setting
  pub level: String,
  /// Category of the setting
  pub category: String,
  /// Parameter name
  pub param: String,
  /// Value to use when deleted
  pub deletedValue: String,
  /// Encrypted value of the setting
  pub valueCrypt: Option<Vec<u8>>,
  /// ID of the encryption key used
  pub cryptoKeyId: u32,
}