summaryrefslogtreecommitdiffstats
path: root/adenosine-pds/src/bin/adenosine-pds.rs
blob: beb423ab7160033c9aa385d6cbd82080f640552b (plain)
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
use adenosine_pds::*;
use anyhow::Result;

use log::{self, debug};
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(
    rename_all = "kebab-case",
    about = "personal digital server (PDS) implementation for AT protocol (atproto.com)"
)]
struct Opt {
    // TODO: different path type for structopt?
    /// File path of sqlite database for storing IPLD blocks (aka, repository content)
    #[structopt(
        parse(from_os_str),
        global = true,
        long = "--block-db",
        env = "ATP_BLOCK_DB",
        default_value = "adenosine_pds_blockstore.sqlite"
    )]
    blockstore_db_path: std::path::PathBuf,

    /// File path of sqlite database for ATP service (user accounts, indices, etc)
    #[structopt(
        parse(from_os_str),
        global = true,
        long = "--atp-db",
        env = "ATP_ATP_DB",
        default_value = "adenosine_pds_atp.sqlite"
    )]
    atp_db_path: std::path::PathBuf,

    /// Log more messages. Pass multiple times for ever more verbosity
    #[structopt(global = true, long, short = "v", parse(from_occurrences))]
    verbose: i8,

    #[structopt(subcommand)]
    cmd: Command,
}

#[derive(StructOpt)]
enum Command {
    /// Start ATP server as a foreground process
    Serve {
        /// Localhost port to listen on
        #[structopt(long, default_value = "3030", env = "ATP_PDS_PORT")]
        port: u16,

        /// Secret key, encoded in hex. Use 'generate-secret' to create a new one
        #[structopt(
            long = "--pds-secret-key",
            env = "ATP_PDS_SECRET_KEY",
            hide_env_values = true
        )]
        pds_secret_key: String,
    },

    /// Helper to import an IPLD CARv1 file in to sqlite data store
    Import {
        /// CARv1 file path to import from
        car_path: std::path::PathBuf,

        /// name of pointer to root of CAR DAG tree. Usually a DID
        #[structopt(long, default_value = "last-import")]
        alias: String,
    },

    /// Helper to print MST keys/docs from a sqlite repo
    Inspect,

    /// Generate a PDS secret key and print to stdout (as hex)
    GenerateSecret,
}

fn main() -> Result<()> {
    dotenv::dotenv().ok();
    let opt = Opt::from_args();

    let log_level = match opt.verbose {
        std::i8::MIN..=-1 => "none",
        0 => "warn",
        1 => "info",
        2 => "debug",
        3..=std::i8::MAX => "trace",
    };
    // hyper logging is very verbose, so crank that down even if everything else is more verbose
    let cli_filter = format!("{},hyper=error", log_level);
    // defer to env var config, fallback to CLI settings
    let log_filter = std::env::var("RUST_LOG").unwrap_or(cli_filter);
    pretty_env_logger::formatted_timed_builder()
        .parse_filters(&log_filter)
        .init();

    debug!("config parsed, starting up");

    match opt.cmd {
        Command::Serve {
            port,
            pds_secret_key,
        } => {
            // TODO: log some config stuff?
            let keypair = KeyPair::from_hex(&pds_secret_key)?;
            run_server(port, &opt.blockstore_db_path, &opt.atp_db_path, keypair)
        }
        // TODO: handle alias
        Command::Import { car_path, alias } => {
            load_car_to_sqlite(&opt.blockstore_db_path, &car_path, &alias)
        }
        Command::Inspect {} => mst::dump_mst_keys(&opt.blockstore_db_path),
        Command::GenerateSecret {} => {
            let keypair = KeyPair::new_random();
            println!("{}", keypair.to_hex());
            Ok(())
        }
    }
}