examples_fxa_client/
main.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5mod devices;
6mod send_tab;
7
8use std::fs;
9
10use clap::{Parser, Subcommand, ValueEnum};
11use cli_support::{fxa_creds, init_logging_with};
12use fxa_client::{FirefoxAccount, FxaConfig, FxaServer};
13
14static CREDENTIALS_FILENAME: &str = "credentials.json";
15static CLIENT_ID: &str = "a2270f727f45f648";
16static REDIRECT_URI: &str = "https://accounts.firefox.com/oauth/success/a2270f727f45f648";
17
18use anyhow::Result;
19
20#[derive(Parser)]
21#[command(about, long_about = None)]
22struct Cli {
23    /// The FxA server to use
24    #[arg(value_enum, default_value_t = Server::Release)]
25    server: Server,
26
27    /// Request a session scope
28    #[clap(long, short, action)]
29    session_scope: bool,
30
31    /// Print out log to the console.  The default level is WARN
32    #[clap(long, short, action)]
33    log: bool,
34
35    /// Set the logging level to INFO
36    #[clap(long, short, action)]
37    info: bool,
38
39    /// Set the logging level to DEBUG
40    #[clap(long, short, action)]
41    debug: bool,
42
43    #[command(subcommand)]
44    command: Command,
45}
46
47#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
48enum Server {
49    /// Official server
50    Release,
51    /// China server
52    China,
53    /// stable dev sever
54    Stable,
55    /// staging dev sever
56    Stage,
57    /// local dev sever
58    LocalDev,
59}
60
61#[derive(Subcommand)]
62enum Command {
63    Devices(devices::DeviceArgs),
64    SendTab(send_tab::SendTabArgs),
65    Disconnect,
66}
67
68fn main() -> Result<()> {
69    let cli = Cli::parse();
70    nss::ensure_initialized();
71    viaduct_dev::use_dev_backend();
72    if cli.log {
73        if cli.debug {
74            init_logging_with("debug");
75        } else if cli.info {
76            init_logging_with("info");
77        } else {
78            init_logging_with("warn");
79        }
80    }
81
82    let scopes: &[&str] = if cli.session_scope {
83        &[fxa_creds::SYNC_SCOPE, fxa_creds::SESSION_SCOPE]
84    } else {
85        &[fxa_creds::SYNC_SCOPE]
86    };
87
88    println!();
89    let account = load_account(&cli, scopes)?;
90    match cli.command {
91        Command::Devices(args) => devices::run(&account, args),
92        Command::SendTab(args) => send_tab::run(&account, args),
93        Command::Disconnect => {
94            account.disconnect();
95            Ok(())
96        }
97    }?;
98
99    Ok(())
100}
101
102fn load_account(cli: &Cli, scopes: &[&str]) -> Result<FirefoxAccount> {
103    let config = FxaConfig {
104        server: match cli.server {
105            Server::Release => FxaServer::Release,
106            Server::Stable => FxaServer::Stable,
107            Server::Stage => FxaServer::Stage,
108            Server::China => FxaServer::China,
109            Server::LocalDev => FxaServer::LocalDev,
110        },
111        redirect_uri: REDIRECT_URI.into(),
112        client_id: CLIENT_ID.into(),
113        token_server_url_override: None,
114    };
115    fxa_creds::get_cli_fxa(config, &credentials_path(), scopes).map(|cli| cli.account)
116}
117
118pub fn persist_fxa_state(acct: &FirefoxAccount) -> Result<()> {
119    let json = acct.to_json().unwrap();
120    Ok(fs::write(credentials_path(), json)?)
121}
122
123fn credentials_path() -> String {
124    cli_support::cli_data_path(CREDENTIALS_FILENAME)
125}