spacetimedb_cli/subcommands/
dns.rs

1use crate::common_args;
2use crate::config::Config;
3use crate::util::{add_auth_header_opt, decode_identity, get_auth_header, get_login_token_or_log_in, ResponseExt};
4use clap::ArgMatches;
5use clap::{Arg, Command};
6
7use spacetimedb_client_api_messages::name::{DomainName, InsertDomainResult};
8
9pub fn cli() -> Command {
10    Command::new("rename")
11        .about("Rename a database")
12        .arg(
13            Arg::new("new-name")
14                .long("to")
15                .required(true)
16                .help("The new name you would like to assign"),
17        )
18        .arg(
19            Arg::new("database-identity")
20                .required(true)
21                .help("The database identity to rename"),
22        )
23        .arg(common_args::server().help("The nickname, host name or URL of the server on which to set the name"))
24        .arg(common_args::yes())
25        .after_help("Run `spacetime rename --help` for more detailed information.\n")
26}
27
28pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::Error> {
29    let domain = args.get_one::<String>("new-name").unwrap();
30    let database_identity = args.get_one::<String>("database-identity").unwrap();
31    let server = args.get_one::<String>("server").map(|s| s.as_ref());
32    let force = args.get_flag("force");
33    let token = get_login_token_or_log_in(&mut config, server, !force).await?;
34    let identity = decode_identity(&token)?;
35    let auth_header = get_auth_header(&mut config, false, server, !force).await?;
36
37    let domain: DomainName = domain.parse()?;
38
39    let builder = reqwest::Client::new()
40        .post(format!(
41            "{}/v1/database/{database_identity}/names",
42            config.get_host_url(server)?
43        ))
44        .body(String::from(domain));
45    let builder = add_auth_header_opt(builder, &auth_header);
46
47    let result = builder.send().await?.json_or_error().await?;
48    match result {
49        InsertDomainResult::Success {
50            domain,
51            database_identity,
52        } => {
53            println!("Domain set to {} for identity {}.", domain, database_identity);
54        }
55        InsertDomainResult::TldNotRegistered { domain } => {
56            return Err(anyhow::anyhow!(
57                "The top level domain that you provided is not registered.\n\
58            This tld is not yet registered to any identity. You can register this domain with the following command:\n\
59            \n\
60            \tspacetime dns register-tld {}\n",
61                domain.tld()
62            ));
63        }
64        InsertDomainResult::PermissionDenied { domain } => {
65            //TODO(jdetter): Have a nice name generator here, instead of using some abstract characters
66            // we should perhaps generate fun names like 'green-fire-dragon' instead
67            let suggested_tld: String = identity.chars().take(12).collect();
68            if let Some(sub_domain) = domain.sub_domain() {
69                return Err(anyhow::anyhow!(
70                    "The top level domain {} is not registered to the identity you provided.\n\
71                We suggest you register a new tld:\n\
72                \tspacetime dns register-tld {}\n\
73                \n\
74                And then push to the domain that uses that tld:\n\
75                \tspacetime publish {}/{}\n",
76                    domain.tld(),
77                    suggested_tld,
78                    suggested_tld,
79                    sub_domain
80                ));
81            } else {
82                return Err(anyhow::anyhow!(
83                    "The top level domain {} is not registered to the identity you provided.\n\
84                We suggest you register a new tld:\n\
85                \tspacetime dns register-tld {}\n\
86                \n\
87                And then push to the domain that uses that tld:\n\
88                \tspacetime publish {}\n",
89                    domain.tld(),
90                    suggested_tld,
91                    suggested_tld
92                ));
93            }
94        }
95        InsertDomainResult::OtherError(e) => return Err(anyhow::anyhow!(e)),
96    }
97
98    Ok(())
99}