You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.7 KiB
139 lines
3.7 KiB
#![allow(clippy::unused_unit)] |
|
|
|
use crate::db_conn::Db; |
|
use crate::models::User; |
|
use rocket::request::{FromRequest, Outcome, Request}; |
|
use rocket::response::Redirect; |
|
use rocket::serde::Deserialize; |
|
use std::env; |
|
use url::Url; |
|
|
|
pub struct RefHeader(pub String); |
|
|
|
#[rocket::async_trait] |
|
impl<'r> FromRequest<'r> for RefHeader { |
|
type Error = (); |
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { |
|
match request.headers().get_one("Referer") { |
|
Some(h) => Outcome::Success(RefHeader(h.to_string())), |
|
None => Outcome::Forward(()), |
|
} |
|
} |
|
} |
|
|
|
#[get("/?p=cs")] |
|
pub fn cs_login(r: RefHeader) -> Redirect { |
|
let mast_url = env::var("MAST_BASE_URL").unwrap(); |
|
let mast_cli = env::var("MAST_CLIENT").unwrap(); |
|
let mast_scope = env::var("MAST_SCOPE").unwrap(); |
|
|
|
let jump_to_url = Url::parse(&r.0).unwrap(); |
|
|
|
let mut redirect_url = env::var("AUTH_BACKEND_URL") |
|
.map(|url| Url::parse(&url).unwrap()) |
|
.unwrap_or_else(|_| jump_to_url.clone()); |
|
redirect_url.set_path("/_login/cs/auth"); |
|
|
|
redirect_url = Url::parse_with_params( |
|
redirect_url.as_str(), |
|
&[ |
|
("redirect_url", redirect_url.as_str()), |
|
("jump_to_url", jump_to_url.as_str()), |
|
], |
|
) |
|
.unwrap(); |
|
|
|
let url = Url::parse_with_params( |
|
&format!("{}oauth/authorize", mast_url), |
|
&[ |
|
("redirect_uri", redirect_url.as_str()), |
|
("client_id", &mast_cli), |
|
("scope", &mast_scope), |
|
("response_type", "code"), |
|
], |
|
) |
|
.unwrap(); |
|
|
|
Redirect::to(url.to_string()) |
|
} |
|
|
|
#[derive(Deserialize, Debug)] |
|
#[serde(crate = "rocket::serde")] |
|
struct Token { |
|
pub access_token: String, |
|
} |
|
|
|
#[derive(Deserialize, Debug)] |
|
#[serde(crate = "rocket::serde")] |
|
struct Account { |
|
pub id: String, |
|
} |
|
#[get("/cs/auth?<code>&<redirect_url>&<jump_to_url>")] |
|
pub async fn cs_auth(code: String, redirect_url: String, jump_to_url: String, db: Db) -> Redirect { |
|
let mast_url = env::var("MAST_BASE_URL").unwrap(); |
|
let mast_cli = env::var("MAST_CLIENT").unwrap(); |
|
let mast_sec = env::var("MAST_SECRET").unwrap(); |
|
let mast_scope = env::var("MAST_SCOPE").unwrap(); |
|
|
|
// to keep same |
|
let redirect_url = Url::parse_with_params( |
|
redirect_url.as_str(), |
|
&[ |
|
("redirect_url", redirect_url.as_str()), |
|
("jump_to_url", jump_to_url.as_str()), |
|
], |
|
) |
|
.unwrap(); |
|
|
|
let client = reqwest::Client::new(); |
|
let r = client |
|
.post(format!("{}oauth/token", &mast_url)) |
|
.form(&[ |
|
("client_id", mast_cli.as_str()), |
|
("client_secret", mast_sec.as_str()), |
|
("scope", mast_scope.as_str()), |
|
("redirect_uri", redirect_url.as_str()), |
|
("grant_type", "authorization_code"), |
|
("code", code.as_str()), |
|
]) |
|
.send() |
|
.await |
|
.unwrap(); |
|
//dbg!(&r); |
|
|
|
let token: Token = r.json().await.unwrap(); |
|
//dbg!(&token); |
|
|
|
let client = reqwest::Client::new(); |
|
let account = client |
|
.get(format!("{}api/v1/accounts/verify_credentials", &mast_url)) |
|
.bearer_auth(token.access_token) |
|
.send() |
|
.await |
|
.unwrap() |
|
.json::<Account>() |
|
.await |
|
.unwrap(); |
|
|
|
//dbg!(&account); |
|
|
|
let tk = User::find_or_create_token(&db, &format!("cs_{}", &account.id), false) |
|
.await |
|
.unwrap(); |
|
|
|
Redirect::to(format!( |
|
"{}?token={}", |
|
{ |
|
if env::var("FRONTEND_WHITELIST") |
|
.unwrap_or_default() |
|
.split(',') |
|
.any(|url| jump_to_url.starts_with(url)) |
|
{ |
|
&jump_to_url |
|
} else { |
|
"/" |
|
} |
|
}, |
|
&tk |
|
)) |
|
}
|
|
|