impl auth
This commit is contained in:
parent
1e31d74904
commit
e47b29da21
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1668,6 +1668,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -17,3 +17,4 @@ reqwest = { version = "0.12.5", features = ["json"] }
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
serde_json = "1.0.120"
|
||||
tokio = { version = "1.38.0", features = ["full"] }
|
||||
url = "2.5.2"
|
||||
|
@ -79,7 +79,9 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_upload_token(&self) -> anyhow::Result<types::response::GetFileLinkTokenResponse> {
|
||||
pub async fn get_upload_token(
|
||||
&self,
|
||||
) -> anyhow::Result<types::response::GetFileLinkTokenResponse> {
|
||||
if self.last_refresh.read().await.elapsed().as_secs() > self.token_valid_time.into() {
|
||||
self.refresh_token().await?;
|
||||
}
|
||||
@ -162,12 +164,10 @@ impl Client {
|
||||
|
||||
match serde_json::from_str(&text) {
|
||||
std::result::Result::Ok(json) => Ok(json),
|
||||
Err(err) => {
|
||||
match serde_json::from_str::<types::response::SendyError>(&text) {
|
||||
Err(err) => match serde_json::from_str::<types::response::SendyError>(&text) {
|
||||
std::result::Result::Ok(json) => Err(anyhow::anyhow!("{:?}", json)),
|
||||
Err(_) => Err(anyhow::Error::new(err).context(text.trim().to_string())),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,6 +302,39 @@ pub async fn refresh_token(
|
||||
// .map_err(Into::into)
|
||||
}
|
||||
|
||||
pub async fn rid_token_auth(rid_code: &str) -> anyhow::Result<types::response::RIDTokenResponse> {
|
||||
let client = reqwest::Client::new();
|
||||
let request = client
|
||||
.get(format!("https://www.rakuten-drive.com/api/v1/auth/rd/custom/token?rid_code={}&is_extension=false", rid_code))
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let text = request.text().await?;
|
||||
|
||||
let json: types::response::RIDTokenResponse = serde_json::from_str(&text)?;
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
pub async fn get_refresh_token(
|
||||
token: &str,
|
||||
) -> anyhow::Result<types::response::VerifyCustomTokenResponse> {
|
||||
let client = reqwest::Client::new();
|
||||
let req = types::request::VerifyCustomTokenRequest {
|
||||
token: token.to_string(),
|
||||
return_secure_token: true,
|
||||
};
|
||||
let request = client
|
||||
.post("https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=AIzaSyDyp5IGr4nXbYin_oduNGi6ci-AnWcuAYE")
|
||||
.json(&req)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let text = request.text().await?;
|
||||
|
||||
let json: types::response::VerifyCustomTokenResponse = serde_json::from_str(&text)?;
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
// https://www.rakuten-drive.com/api/account/refreshtoken POST RefreshTokenRequest RefreshTokenResponse
|
||||
// https://forest.sendy.jp/cloud/service/file/v1/file POST FileDetailRequest FileDetailResponse
|
||||
// https://forest.sendy.jp/cloud/service/file/v1/files POST ListFilesRequest ListFilesResponse
|
||||
|
28
src/main.rs
28
src/main.rs
@ -106,6 +106,7 @@ enum Commands {
|
||||
},
|
||||
#[clap(about = "Print file detail")]
|
||||
Info { path: String },
|
||||
Auth {},
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@ -140,8 +141,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
Commands::Mkdir { name, path } => {
|
||||
client.mkdir(name, path.as_deref()).await.unwrap();
|
||||
}
|
||||
Commands::Copy { src: _, dest: _ } => {
|
||||
todo!("Copy");
|
||||
Commands::Copy { src, dest } => {
|
||||
client.copy(src, dest).await.unwrap();
|
||||
}
|
||||
Commands::Rename { path, name } => {
|
||||
client.rename(path, name).await.unwrap();
|
||||
@ -149,6 +150,29 @@ async fn main() -> anyhow::Result<()> {
|
||||
Commands::Info { path } => {
|
||||
client.info(path).await.unwrap();
|
||||
}
|
||||
Commands::Auth {} => {
|
||||
println!("Click the link below to authorize the app:\n");
|
||||
let link = "https://login.account.rakuten.com/sso/authorize?response_type=code&client_id=rakuten_drive_web&redirect_uri=https://www.rakuten-drive.com/oauth-callback&scope=openid+profile+email&prompt=login&ui_locales=en";
|
||||
println!("{}\n", link);
|
||||
|
||||
println!("Paste the URL you were redirected to:");
|
||||
let mut auth_url = String::new();
|
||||
std::io::stdin().read_line(&mut auth_url).unwrap();
|
||||
let auth_url = url::Url::parse(auth_url.trim())?;
|
||||
|
||||
let params = auth_url.query_pairs().collect::<Vec<_>>();
|
||||
|
||||
let rid_code = params
|
||||
.iter()
|
||||
.find(|(key, _)| key == "code")
|
||||
.map(|(_, value)| value.to_string())
|
||||
.ok_or_else(|| anyhow::anyhow!("Code not found in URL"))?;
|
||||
|
||||
let rid_token_auth_res = client::rid_token_auth(rid_code.as_str()).await?;
|
||||
let token_verify_res = client::get_refresh_token(&rid_token_auth_res.custom_token).await?;
|
||||
|
||||
println!("Refresh token: {}", token_verify_res.refresh_token);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -152,3 +152,10 @@ pub struct CopyFileRequestFile {
|
||||
pub size: i64,
|
||||
pub version_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VerifyCustomTokenRequest {
|
||||
pub return_secure_token: bool,
|
||||
pub token: String,
|
||||
}
|
@ -176,3 +176,20 @@ pub enum SendyErrorType {
|
||||
SendyErrShareUpwardShareExist,
|
||||
SendyErrShareFolderIncludedOrInclude,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct RIDTokenResponse {
|
||||
pub custom_token: String,
|
||||
pub is_new_user: String, // "false"
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VerifyCustomTokenResponse {
|
||||
pub kind: String,
|
||||
pub id_token: String,
|
||||
pub refresh_token: String,
|
||||
pub expires_in: String,
|
||||
pub is_new_user: bool,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user