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
use billing::app_store_client::AppStoreClient;
use billing::google_play_client::GooglePlayClient;
use billing::stripe_client::StripeClient;
use document_service::DocumentService;
use std::env;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};

use libsecp256k1::PublicKey;
use lockbook_shared::api::{ErrorWrapper, Request, RequestWrapper};
use lockbook_shared::{clock, pubkey, SharedError};
use semver::Version;
use serde::{Deserialize, Serialize};

use crate::account_service::GetUsageHelperError;
use crate::billing::billing_service::StripeWebhookError;
use crate::billing::stripe_error::SimplifiedStripeError;
use crate::schema::ServerV4;
use crate::ServerError::ClientError;
pub use stripe;
use tracing::log::warn;

static CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");

#[derive(Clone)]
pub struct ServerState<S, A, G, D>
where
    S: StripeClient,
    A: AppStoreClient,
    G: GooglePlayClient,
    D: DocumentService,
{
    pub config: config::Config,
    pub index_db: Arc<Mutex<ServerV4>>,
    pub stripe_client: S,
    pub google_play_client: G,
    pub app_store_client: A,
    pub document_service: D,
}

#[derive(Clone)]
pub struct RequestContext<TRequest> {
    pub request: TRequest,
    pub public_key: PublicKey,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ServerError<U: Debug> {
    ClientError(U),
    InternalError(String),
}

#[macro_export]
macro_rules! internal {
    ($($arg:tt)*) => {{
        let msg = format!($($arg)*);
        tracing::error!("{}", msg);
        $crate::ServerError::InternalError(msg)
    }};
}

pub fn handle_version_header<Req: Request>(
    config: &config::Config, version: &Option<String>,
) -> Result<(), ErrorWrapper<Req::Error>> {
    let v = &version.clone().unwrap_or("0.0.0".to_string());
    let Ok(v) = Version::parse(v) else {
        warn!("version not parsable, request rejected: {v}");
        return Err(ErrorWrapper::BadRequest);
    };
    router_service::CORE_VERSION_COUNTER
        .with_label_values(&[&(v.to_string())])
        .inc();
    if !config.server.min_core_version.matches(&v) {
        return Err(ErrorWrapper::<Req::Error>::ClientUpdateRequired);
    }
    Ok(())
}

pub fn verify_auth<TRequest>(
    config: &config::Config, request: &RequestWrapper<TRequest>,
) -> Result<(), SharedError>
where
    TRequest: Request + Serialize,
{
    pubkey::verify(
        &request.signed_request.public_key,
        &request.signed_request,
        config.server.max_auth_delay as u64,
        config.server.max_auth_delay as u64,
        clock::get_time,
    )
}

pub mod account_service;
pub mod billing;
pub mod config;
pub mod document_service;
pub mod error_handler;
pub mod file_service;
pub mod loggers;
pub mod metrics;
pub mod router_service;
pub mod schema;
pub mod utils;