backend/
app.rs

1use firebase_auth::FirebaseUser;
2use serde::Serialize;
3use socketioxide::SocketIo;
4use sqlx::PgPool;
5use thiserror::Error;
6use tokio::sync::watch;
7use ts_rs::TS;
8use uuid::Uuid;
9
10/// Top-level application state.
11///
12/// Cheaply cloneable and intended to be moved around the program.
13#[derive(Clone)]
14pub struct AppState {
15    /// Connection to the Postgres database.
16    pub db: PgPool,
17
18    /// Socket for communicating with Automerge document server.
19    pub automerge_io: SocketIo,
20
21    pub app_status: watch::Receiver<AppStatus>,
22}
23
24#[derive(Clone, Debug, PartialEq, Eq)]
25pub enum AppStatus {
26    Starting,
27    Migrating,
28    Running,
29    #[allow(dead_code)]
30    Failed(String),
31}
32
33/// Context available to RPC procedures.
34#[derive(Clone)]
35pub struct AppCtx {
36    /// Application state.
37    pub state: AppState,
38
39    /// Authenticated Firebase user, if any.
40    pub user: Option<FirebaseUser>,
41}
42
43/// A page of items along with pagination metadata.
44#[derive(Clone, Debug, Serialize, TS)]
45pub struct Paginated<T> {
46    /// The total number of items matching the query criteria.
47    pub total: i32,
48
49    /// The number of items skipped.
50    pub offset: i32,
51
52    /// The items in the current page.
53    pub items: Vec<T>,
54}
55
56/// Top-level application error.
57#[derive(Error, Debug)]
58pub enum AppError {
59    /// Error from the SQL database.
60    #[error("SQL database error: {0}")]
61    Db(#[from] sqlx::Error),
62
63    /// Error from the socket communicating with the Automerge document server.
64    #[error("Error receiving acknowledgment from socket: {0}")]
65    Ack(#[from] socketioxide::AckError<()>),
66
67    /// Client made request with invalid data.
68    #[error("Request with invalid data: {0}")]
69    Invalid(String),
70
71    /// Client has not authenticated using Firebase auth.
72    #[error("Authentication credentials were not provided")]
73    Unauthorized,
74
75    /// Something went wrong in a socket call to the automerge server
76    #[error("Automerge server error: {0}")]
77    AutomergeServer(String),
78
79    /// Client does not have permission to perform the requested action on the
80    /// document ref.
81    #[error("Not authorized to access ref: {0}")]
82    Forbidden(Uuid),
83}