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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use clap::{Parser, Subcommand};
#[derive(Debug, Clone, Subcommand)]
pub enum AuthCommands {
/// Log into Rerun.
///
/// This command opens a page in your default browser, allowing you
/// to log in to the Rerun Data Platform.
///
/// Once you've logged in, your credentials are stored on your machine.
///
/// To sign up, contact us through the form linked at <https://rerun.io/#open-source-vs-commercial>.
Login(LoginCommand),
/// Log out of Rerun.
///
/// This command clears the credentials stored on your machine
/// and ends your session.
Logout(LogoutCommand),
/// Retrieve the stored access token.
///
/// The access token is part of the credentials produced by `rerun auth login`,
/// and is used to authorize requests to the Rerun Data Platform.
Token(TokenCommand),
/// Generate a fresh access token.
///
/// You can use this token to authorize requests to the Rerun Data Platform.
///
/// It's closer to an API key than an access token, as it can be revoked before
/// it expires.
GenerateToken(GenerateTokenCommand),
}
#[derive(Debug, Clone, Parser)]
pub struct LoginCommand {
// Double-negative because it's an opt-out flag.
/// Post a link instead of directly opening in the browser.
#[clap(long, default_value = "false")]
no_open_browser: bool,
/// Trigger the full login flow even if valid credentials already exist.
#[clap(long, default_value = "false")]
force: bool,
/// `WorkOS` organization ID to log in to.
///
/// If you belong to multiple organizations, this selects which one
/// to use. Without this flag, the browser will prompt you to choose
/// (or reuse the previous selection).
#[clap(long, hide = true)]
org_id: Option<String>,
}
#[derive(Debug, Clone, Parser)]
pub struct LogoutCommand {
/// Post a link instead of directly opening in the browser.
#[clap(long, default_value = "false")]
no_open_browser: bool,
}
#[derive(Debug, Clone, Parser)]
pub struct TokenCommand {}
#[derive(Debug, Clone, Parser)]
pub struct GenerateTokenCommand {
/// Origin of the server to request the token from.
#[clap(long)]
server: String,
/// Duration of the token, either in:
/// - "human time", e.g. `1 day`, or
/// - ISO 8601 duration format, e.g. `P1D`.
#[clap(long)]
expiration: String,
/// Which permission the token should have.
///
/// [`read`, `read-write`]
#[clap(long, default_value = "read")]
permission: String,
}
impl AuthCommands {
pub fn run(self, runtime: &tokio::runtime::Handle) -> Result<(), re_auth::cli::Error> {
match self {
Self::Login(args) => {
let options = re_auth::cli::LoginOptions {
open_browser: !args.no_open_browser,
force_login: args.force,
org_id: args.org_id,
};
runtime.block_on(re_auth::cli::login(options))
}
Self::Logout(args) => {
let options = re_auth::cli::LogoutOptions {
open_browser: !args.no_open_browser,
};
re_auth::cli::logout(&options)
}
Self::Token(_) => runtime.block_on(re_auth::cli::token()),
Self::GenerateToken(args) => {
let server = parse_http_or_rerun_uri(&args.server)
.map_err(|err| re_auth::cli::Error::Generic(err.into()))?;
let expiration = args
.expiration
.parse::<jiff::Span>()
.map_err(|err| re_auth::cli::Error::Generic(err.into()))?;
let permission = args
.permission
.parse::<re_auth::Permission>()
.map_err(|err| re_auth::cli::Error::Generic(err.into()))?;
let options = re_auth::cli::GenerateTokenOptions {
server,
expiration,
permission,
};
runtime.block_on(re_auth::cli::generate_token(options))
}
}
}
}
#[derive(Debug)]
struct InvalidUri;
impl std::fmt::Display for InvalidUri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"invalid uri, expected one of: `rerun://`, `rerun+http://`, `rerun+https://`, `http://`, `https://`"
)
}
}
impl std::error::Error for InvalidUri {}
fn parse_http_or_rerun_uri(s: &str) -> Result<url::Origin, InvalidUri> {
if let Ok(url) = s.parse::<re_uri::Origin>() {
Ok(url::Url::parse(&url.as_url()).expect("valid url").origin())
} else if let Ok(url) = url::Url::parse(s) {
Ok(url.origin())
} else {
Err(InvalidUri)
}
}