Skip to content

Commit 5305ab6

Browse files
committed
add rerun auth generate-token
1 parent c91b4d5 commit 5305ab6

File tree

6 files changed

+102
-4
lines changed

6 files changed

+102
-4
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8444,6 +8444,7 @@ dependencies = [
84448444
"getrandom 0.3.3",
84458445
"http",
84468446
"indicatif",
8447+
"jiff",
84478448
"js-sys",
84488449
"jsonwebtoken",
84498450
"rand 0.9.2",
@@ -10670,6 +10671,7 @@ dependencies = [
1067010671
"indexmap 2.11.4",
1067110672
"indicatif",
1067210673
"itertools 0.14.0",
10674+
"jiff",
1067310675
"log",
1067410676
"puffin",
1067510677
"rayon",
@@ -10710,6 +10712,7 @@ dependencies = [
1071010712
"similar-asserts",
1071110713
"tokio",
1071210714
"unindent",
10715+
"url",
1071310716
]
1071410717

1071510718
[[package]]

crates/top/rerun/Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ default = [
3636
]
3737

3838
## Support the `rerun auth` command
39-
auth = ["re_auth/cli"]
39+
auth = ["re_auth/cli", "dep:jiff", "dep:url"]
4040

4141
## Enable anonymized telemetry using our analytics SDK.
4242
analytics = [
@@ -192,9 +192,11 @@ puffin.workspace = true
192192
rayon.workspace = true
193193

194194
# Native, optional:
195-
re_perf_telemetry = { workspace = true, features = ["tracy"], optional = true }
196195
clap = { workspace = true, optional = true, features = ["derive"] }
196+
jiff = { workspace = true, optional = true }
197+
re_perf_telemetry = { workspace = true, features = ["tracy"], optional = true }
197198
unindent = { workspace = true, optional = true }
199+
url = { workspace = true, optional = true }
198200

199201
[build-dependencies]
200202
re_build_tools.workspace = true

crates/top/rerun/src/commands/auth.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ pub enum AuthCommands {
1717
/// The access token is part of the credentials produced by `rerun auth login`,
1818
/// and is used to authorize requests to the Rerun data platform.
1919
Token(TokenCommand),
20+
21+
/// Generate a fresh token.
22+
GenerateToken(GenerateTokenCommand),
2023
}
2124

2225
#[derive(Debug, Clone, Parser)]
@@ -34,8 +37,21 @@ pub struct LoginCommand {
3437
#[derive(Debug, Clone, Parser)]
3538
pub struct TokenCommand {}
3639

40+
#[derive(Debug, Clone, Parser)]
41+
pub struct GenerateTokenCommand {
42+
/// Origin of the server to request the token from.
43+
#[clap(long)]
44+
server: String,
45+
46+
/// Duration of the token, either in:
47+
/// - "human time", e.g. `1 day`, or
48+
/// - ISO 8601 duration format, e.g. `P1D`.
49+
#[clap(long)]
50+
expiration: jiff::Span,
51+
}
52+
3753
impl AuthCommands {
38-
pub fn run(&self, runtime: &tokio::runtime::Handle) -> Result<(), re_auth::cli::Error> {
54+
pub fn run(self, runtime: &tokio::runtime::Handle) -> Result<(), re_auth::cli::Error> {
3955
match self {
4056
Self::Login(args) => {
4157
let options = re_auth::cli::LoginOptions {
@@ -46,6 +62,17 @@ impl AuthCommands {
4662
}
4763

4864
Self::Token(_) => runtime.block_on(re_auth::cli::token()),
65+
66+
Self::GenerateToken(args) => {
67+
let server = url::Url::parse(&args.server)
68+
.map_err(|err| re_auth::cli::Error::Generic(err.into()))?
69+
.origin();
70+
let options = re_auth::cli::GenerateTokenOptions {
71+
server,
72+
expiration: args.expiration,
73+
};
74+
runtime.block_on(re_auth::cli::generate_token(options))
75+
}
4976
}
5077
}
5178
}

crates/utils/re_auth/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ re_log.workspace = true
4242
async-trait.workspace = true
4343
base64.workspace = true
4444
http.workspace = true
45+
jiff.workspace = true
4546
jsonwebtoken.workspace = true
4647
saturating_cast.workspace = true
4748
thiserror.workspace = true

crates/utils/re_auth/src/cli.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use indicatif::ProgressBar;
44

55
pub use crate::callback_server::Error;
66
use crate::callback_server::OauthCallbackServer;
7-
use crate::oauth::api::{AuthenticateWithCode, Pkce, send_async};
7+
use crate::oauth::api::{AuthenticateWithCode, GenerateToken, Pkce, send_async};
88
use crate::oauth::{self, Credentials};
99

1010
pub struct LoginOptions {
@@ -137,3 +137,33 @@ pub async fn login(options: LoginOptions) -> Result<(), Error> {
137137

138138
Ok(())
139139
}
140+
141+
pub struct GenerateTokenOptions {
142+
pub server: url::Origin,
143+
pub expiration: jiff::Span,
144+
}
145+
146+
pub async fn generate_token(options: GenerateTokenOptions) -> Result<(), Error> {
147+
let credentials = match oauth::load_and_refresh_credentials().await {
148+
Ok(Some(credentials)) => credentials,
149+
150+
Ok(None) => return Err(Error::Generic(NoCredentialsError.into())),
151+
152+
Err(err) => {
153+
re_log::debug!("invalid credentials: {err}");
154+
return Err(Error::Generic(Box::new(ExpiredCredentialsError)));
155+
}
156+
};
157+
158+
let res = send_async(GenerateToken {
159+
server: options.server,
160+
token: credentials.access_token().as_str(),
161+
expiration: options.expiration,
162+
})
163+
.await
164+
.map_err(|err| Error::Generic(err.into()))?;
165+
166+
println!("{}", res.token);
167+
168+
Ok(())
169+
}

crates/utils/re_auth/src/oauth/api.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,38 @@ impl From<User> for crate::oauth::User {
296296
}
297297
}
298298
}
299+
300+
pub struct GenerateToken<'a> {
301+
pub server: url::Origin,
302+
pub token: &'a str,
303+
pub expiration: jiff::Span,
304+
}
305+
306+
#[derive(serde::Deserialize)]
307+
pub struct GenerateTokenResponse {
308+
pub token: String,
309+
}
310+
311+
impl IntoRequest for GenerateToken<'_> {
312+
type Res = GenerateTokenResponse;
313+
314+
fn into_request(self) -> Result<ehttp::Request, Error> {
315+
#[derive(serde::Serialize)]
316+
struct Body<'a> {
317+
token: &'a str,
318+
expiration: jiff::Span,
319+
}
320+
321+
ehttp::Request::json(
322+
format_args!(
323+
"{origin}/generate-token",
324+
origin = self.server.ascii_serialization()
325+
),
326+
&Body {
327+
token: self.token,
328+
expiration: self.expiration,
329+
},
330+
)
331+
.map_err(Error::Serialize)
332+
}
333+
}

0 commit comments

Comments
 (0)