|
|
|
@ -1,15 +1,15 @@
|
|
|
|
|
#[macro_use]
|
|
|
|
|
extern crate rocket;
|
|
|
|
|
|
|
|
|
|
use core::panic;
|
|
|
|
|
use chrono::{Duration, Utc};
|
|
|
|
|
use core::panic;
|
|
|
|
|
use derive_more::From;
|
|
|
|
|
use reqwest::StatusCode;
|
|
|
|
|
use rocket::form::Form;
|
|
|
|
|
use rocket::fs::{relative, FileServer};
|
|
|
|
|
use rocket::http::{Cookie, CookieJar};
|
|
|
|
|
use rocket::request::{FromRequest};
|
|
|
|
|
use rocket::response::{Redirect, content::RawHtml};
|
|
|
|
|
use rocket::request::FromRequest;
|
|
|
|
|
use rocket::response::{content::RawHtml, Redirect};
|
|
|
|
|
use rocket::{request, Request};
|
|
|
|
|
use rocket_dyn_templates::{context, Template};
|
|
|
|
|
use sass_rocket_fairing::SassFairing;
|
|
|
|
@ -27,7 +27,12 @@ mod kyujitai;
|
|
|
|
|
|
|
|
|
|
#[get("/<challenge>")]
|
|
|
|
|
async fn get_challenge(challenge: u32, cookies: &CookieJar<'_>) -> Template {
|
|
|
|
|
println!("{:?}", cookies.get_private("user_name").map(|cookie| cookie.value().to_owned()));
|
|
|
|
|
println!(
|
|
|
|
|
"{:?}",
|
|
|
|
|
cookies
|
|
|
|
|
.get_private("user_name")
|
|
|
|
|
.map(|cookie| cookie.value().to_owned())
|
|
|
|
|
);
|
|
|
|
|
Template::render(
|
|
|
|
|
"index",
|
|
|
|
|
context! {
|
|
|
|
@ -76,7 +81,6 @@ fn login() -> Redirect {
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(FromForm)]
|
|
|
|
|
struct Login<'r> {
|
|
|
|
|
token_type: &'r str,
|
|
|
|
@ -87,15 +91,23 @@ struct Login<'r> {
|
|
|
|
|
|
|
|
|
|
#[post("/login", data = "<login>")]
|
|
|
|
|
async fn post_login(login: Form<Login<'_>>, cookies: &CookieJar<'_>) -> Redirect {
|
|
|
|
|
if (login.token_type != "Bearer" || login.scope != "guilds.join+identify+guilds") && User::init(login.access_token, cookies).await.is_ok() {
|
|
|
|
|
cookies.add(Cookie::new(TOKEN_EXPIRE_COOKIE, (Utc::now() + Duration::seconds(login.expires_in as i64)).timestamp().to_string()));
|
|
|
|
|
if (login.token_type != "Bearer" || login.scope != "guilds.join+identify+guilds")
|
|
|
|
|
&& User::init(login.access_token, cookies).await.is_ok()
|
|
|
|
|
{
|
|
|
|
|
cookies.add(Cookie::new(
|
|
|
|
|
TOKEN_EXPIRE_COOKIE,
|
|
|
|
|
(Utc::now() + Duration::seconds(login.expires_in as i64))
|
|
|
|
|
.timestamp()
|
|
|
|
|
.to_string(),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
Redirect::to("/")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[get("/success")]
|
|
|
|
|
fn success() -> RawHtml<&'static str> {
|
|
|
|
|
RawHtml("<form action=\"/login\" method=\"post\"></form>
|
|
|
|
|
RawHtml(
|
|
|
|
|
"<form action=\"/login\" method=\"post\"></form>
|
|
|
|
|
<script>
|
|
|
|
|
try {
|
|
|
|
|
const params = new URLSearchParams(location.hash.slice(1));
|
|
|
|
@ -111,7 +123,8 @@ fn success() -> RawHtml<&'static str> {
|
|
|
|
|
} catch {
|
|
|
|
|
location.href = \"/\";
|
|
|
|
|
}
|
|
|
|
|
</script>")
|
|
|
|
|
</script>",
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Referer(Option<String>);
|
|
|
|
@ -208,7 +221,10 @@ enum GetUserError {
|
|
|
|
|
ReqwestError(reqwest::Error),
|
|
|
|
|
DeserializeError(serde_json::Error),
|
|
|
|
|
#[allow(unused)]
|
|
|
|
|
DiscordError { status: StatusCode, message: Option<String> },
|
|
|
|
|
DiscordError {
|
|
|
|
|
status: StatusCode,
|
|
|
|
|
message: Option<String>,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_cookie_value<T: std::str::FromStr>(cookies: &CookieJar<'_>, name: &str) -> Option<T> {
|
|
|
|
@ -236,13 +252,16 @@ impl User {
|
|
|
|
|
return Err(GetUserError::DiscordError {
|
|
|
|
|
status,
|
|
|
|
|
message: text.ok(),
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
let user: Self = serde_json::from_str(&text?)?;
|
|
|
|
|
cookies.add_private(Cookie::new(TOKEN_COOKIE, token.to_owned()));
|
|
|
|
|
cookies.add_private(Cookie::new("user_id", user.id.to_string()));
|
|
|
|
|
cookies.add_private(Cookie::new("user_name", user.name.clone()));
|
|
|
|
|
cookies.add_private(Cookie::new("user_discriminator", user.discriminator.to_string()));
|
|
|
|
|
cookies.add_private(Cookie::new(
|
|
|
|
|
"user_discriminator",
|
|
|
|
|
user.discriminator.to_string(),
|
|
|
|
|
));
|
|
|
|
|
cookies.add_private(Cookie::new("user_avatar", user.avatar.clone()));
|
|
|
|
|
Ok(user)
|
|
|
|
|
}
|
|
|
|
@ -270,10 +289,12 @@ impl User {
|
|
|
|
|
Some(user) => user,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
};
|
|
|
|
|
if cookies.get(TOKEN_EXPIRE_COOKIE)
|
|
|
|
|
if cookies
|
|
|
|
|
.get(TOKEN_EXPIRE_COOKIE)
|
|
|
|
|
.map(|expire| expire.value().parse::<i64>())
|
|
|
|
|
.and_then(Result::ok)
|
|
|
|
|
.map_or(true, |timestamp| Utc::now().timestamp() >= timestamp) {
|
|
|
|
|
.map_or(true, |timestamp| Utc::now().timestamp() >= timestamp)
|
|
|
|
|
{
|
|
|
|
|
cookies.remove_private(Cookie::named(TOKEN_COOKIE));
|
|
|
|
|
cookies.remove_private(Cookie::named("user_id"));
|
|
|
|
|
cookies.remove_private(Cookie::named("user_name"));
|
|
|
|
@ -291,13 +312,15 @@ fn rocket() -> _ {
|
|
|
|
|
let config = rocket::Config::figment().merge(("port", 1313));
|
|
|
|
|
dotenv::dotenv().expect("Failed to load .env file");
|
|
|
|
|
rocket::custom(config)
|
|
|
|
|
.mount("/", routes![get_challenge, login, post_login, success, logout])
|
|
|
|
|
.mount(
|
|
|
|
|
"/",
|
|
|
|
|
routes![get_challenge, login, post_login, success, logout],
|
|
|
|
|
)
|
|
|
|
|
.mount("/css", FileServer::from(relative!("styles/css")))
|
|
|
|
|
.attach(Template::fairing())
|
|
|
|
|
.attach(SassFairing::default())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use crate::User;
|
|
|
|
|