1use chrono::{DateTime, Utc};
4use edda_types::Edition;
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7
8use crate::{Nonce, PublicKey, Role, Signature, SignedCert, bytes};
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
13pub struct Claims {
14 pub key: PublicKey,
16 pub campaign: Uuid,
17 pub role: Principal,
18 pub name: String,
20 #[serde(default)]
22 pub edition: Edition,
23 #[serde(default, skip_serializing_if = "CampaignSettings::is_default")]
25 pub settings: CampaignSettings,
26 pub expires_at: DateTime<Utc>,
27}
28
29#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
33#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
34pub struct CampaignSettings {
35 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
37 pub read_only: bool,
38 #[serde(default, skip_serializing_if = "Quotas::is_default")]
40 pub quotas: Quotas,
41}
42
43impl CampaignSettings {
44 pub fn is_default(&self) -> bool {
47 *self == Self::default()
48 }
49}
50
51#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
54#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
55#[serde(default)]
56pub struct Quotas {
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub characters: Option<u32>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub monsters: Option<u32>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub rules_texts: Option<u32>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub combats: Option<u32>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub plans: Option<u32>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub devices: Option<u32>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub events_per_combat: Option<u32>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub connections_per_combat: Option<u32>,
73}
74
75impl Quotas {
76 pub fn is_default(&self) -> bool {
78 *self == Self::default()
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
84#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
85#[serde(rename_all = "snake_case")]
86pub enum Principal {
87 Dm,
88 Player,
89 Service,
92}
93
94impl From<Role> for Principal {
95 fn from(role: Role) -> Self {
96 match role {
97 Role::Dm => Principal::Dm,
98 Role::Player => Principal::Player,
99 }
100 }
101}
102
103impl Claims {
104 pub fn is_dm(&self) -> bool {
106 self.role == Principal::Dm
107 }
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
113pub struct ChallengeRequest {
114 pub campaign: Uuid,
115 pub key: PublicKey,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
121pub struct Challenge {
122 pub id: Uuid,
123 pub nonce: Nonce,
124 pub campaign: Uuid,
125 pub server: PublicKey,
128 pub expires_at: DateTime<Utc>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
134#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
135pub struct LoginProof {
136 pub challenge: Uuid,
137 pub nonce: Nonce,
138 pub campaign: Uuid,
139 pub server: PublicKey,
140}
141
142impl From<&Challenge> for LoginProof {
143 fn from(c: &Challenge) -> Self {
144 Self {
145 challenge: c.id,
146 nonce: c.nonce,
147 campaign: c.campaign,
148 server: c.server,
149 }
150 }
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
156pub struct LoginRequest {
157 pub challenge: Uuid,
158 pub signature: Signature,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
163#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
164pub struct Session {
165 pub token: String,
167 pub claims: Claims,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
173pub struct NewCampaign {
174 pub name: String,
175 pub edition: Edition,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
181#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
182pub struct CreatedCampaign {
183 pub campaign: Campaign,
184 pub setup_code: String,
185}
186
187#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
191pub struct AuthExport {
192 pub campaign: Campaign,
193 pub created_at: DateTime<Utc>,
194 pub devices: Vec<Device>,
195 #[serde(default, skip_serializing_if = "CampaignSettings::is_default")]
196 pub settings: CampaignSettings,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
202#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
203pub struct SetupCode {
204 pub code: String,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
210#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
211pub struct SetupRequest {
212 pub code: String,
213 pub cert: SignedCert,
215}
216
217#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
219#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
220pub struct Campaign {
221 pub id: Uuid,
222 pub name: String,
223 #[serde(default)]
225 pub edition: Edition,
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
231#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
232pub struct Device {
233 pub cert: SignedCert,
234 pub added_at: DateTime<Utc>,
235 #[serde(default, skip_serializing_if = "Option::is_none")]
236 pub revoked_at: Option<DateTime<Utc>>,
237}
238
239#[derive(Debug, Clone, Serialize, Deserialize)]
241#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
242pub struct ServerKey {
243 pub key: PublicKey,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
249pub struct PairingSlot {
250 pub slot: u16,
251 pub expires_at: DateTime<Utc>,
252}
253
254#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
257#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
258pub struct PairingMessage {
259 #[serde(with = "bytes::vec")]
261 #[cfg_attr(feature = "openapi", schema(value_type = String))]
262 pub data: Vec<u8>,
263}