diff --git a/src/util/structs/Token.rs b/src/util/structs/Token.rs deleted file mode 100644 index b2a5b04..0000000 --- a/src/util/structs/Token.rs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Yggdrasil: Minecraft authentication server - * Copyright (C) 2023 0xf8.dev@proton.me - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - */ - -use serde::{Deserialize, Serialize}; - -use structs::Account::Account; - -use crate::*; - -#[derive(Deserialize, Serialize, Debug)] -pub struct Token { - id: i64, - access: String, - client: String, - account: Account, - issued: i64, - expires: i64, -} - -impl Token { - pub async fn from_id(db: &Database, id: i64) -> Option { - let record = sqlx::query_as!(RawToken, "SELECT * FROM tokens WHERE id = $1", id) - .fetch_one(&db.pool) - .await; - match record { - Ok(t) => Some(t.complete(db).await), - Err(_) => None, - } - } - - pub fn random_token() -> String { - random_string::generate(128, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.") - } -} - -pub struct RawToken { - id: i64, - access: String, - client: String, - account: i64, - issued: i64, - expires: i64 -} - -impl RawToken { - pub async fn complete(self, db: &Database) -> Token { - Token { - id: self.id, - access: self.access, - client: self.client, - account: Account::from_id(db, self.account).await.expect("Couldn't resolve token owner"), - issued: self.issued, - expires: self.expires, - } - } -} diff --git a/src/util/structs/Account.rs b/src/util/structs/account.rs similarity index 98% rename from src/util/structs/Account.rs rename to src/util/structs/account.rs index 4a02952..3de6199 100644 --- a/src/util/structs/Account.rs +++ b/src/util/structs/account.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use structs::Profile::{Profile, ProfileRaw}; +use structs::profile::{Profile, ProfileRaw}; use crate::*; diff --git a/src/util/structs/BlockedServer.rs b/src/util/structs/blocked_server.rs similarity index 100% rename from src/util/structs/BlockedServer.rs rename to src/util/structs/blocked_server.rs diff --git a/src/util/structs/Cape.rs b/src/util/structs/cape.rs similarity index 100% rename from src/util/structs/Cape.rs rename to src/util/structs/cape.rs diff --git a/src/util/structs/mod.rs b/src/util/structs/mod.rs index 71ef60c..ac4d865 100644 --- a/src/util/structs/mod.rs +++ b/src/util/structs/mod.rs @@ -10,12 +10,12 @@ */ // yeah yeah snake_case whatever -pub mod Account; -pub mod BlockedServer; -pub mod Cape; -pub mod Profile; -pub mod ProfileAttributes; -pub mod Session; -pub mod TexturedObject; -pub mod Token; +pub mod account; +pub mod blocked_server; +pub mod cape; +pub mod profile; +pub mod profile_attributes; +pub mod session; +pub mod textured_object; +pub mod token; diff --git a/src/util/structs/Profile.rs b/src/util/structs/profile.rs similarity index 98% rename from src/util/structs/Profile.rs rename to src/util/structs/profile.rs index 424a607..d70b832 100644 --- a/src/util/structs/Profile.rs +++ b/src/util/structs/profile.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; -use structs::{Cape::Cape, ProfileAttributes::ProfileAttributes}; +use structs::{cape::Cape, profile_attributes::ProfileAttributes}; use crate::*; diff --git a/src/util/structs/ProfileAttributes.rs b/src/util/structs/profile_attributes.rs similarity index 100% rename from src/util/structs/ProfileAttributes.rs rename to src/util/structs/profile_attributes.rs diff --git a/src/util/structs/Session.rs b/src/util/structs/session.rs similarity index 82% rename from src/util/structs/Session.rs rename to src/util/structs/session.rs index fa98b5e..94e5030 100644 --- a/src/util/structs/Session.rs +++ b/src/util/structs/session.rs @@ -9,9 +9,10 @@ * You should have received a copy of the GNU General Public License along with this program. If not, see . */ +use anyhow::Result; use serde::{Deserialize, Serialize}; -use structs::Profile::Profile; +use structs::profile::Profile; use crate::*; @@ -34,6 +35,14 @@ impl Session { Err(_) => None, } } + + pub async fn create(db: &Database, profile: &Profile, server_id: String, ip_addr: String) -> Result<()> { + sqlx::query!("INSERT INTO sessions(profile, server_id, ip_addr) VALUES ($1, $2, $3)", profile.id, server_id, ip_addr) + .execute(&db.pool) + .await?; + + Ok(()) + } } #[derive(Deserialize, Serialize, Debug)] diff --git a/src/util/structs/TexturedObject.rs b/src/util/structs/textured_object.rs similarity index 98% rename from src/util/structs/TexturedObject.rs rename to src/util/structs/textured_object.rs index 9a1bf94..706633b 100644 --- a/src/util/structs/TexturedObject.rs +++ b/src/util/structs/textured_object.rs @@ -13,7 +13,7 @@ use std::time::UNIX_EPOCH; use serde::{Deserialize, Serialize}; use json::{object, JsonValue}; -use structs::Profile::Profile; +use structs::profile::Profile; use crate::*; diff --git a/src/util/structs/token.rs b/src/util/structs/token.rs new file mode 100644 index 0000000..06dd0c5 --- /dev/null +++ b/src/util/structs/token.rs @@ -0,0 +1,117 @@ +/* + * Yggdrasil: Minecraft authentication server + * Copyright (C) 2023 0xf8.dev@proton.me + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + */ + +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use sqlx::Error; + +use structs::account::Account; + +use crate::*; + +#[derive(Deserialize, Serialize, Debug)] +pub struct Token { + pub id: i64, + pub access: String, + pub client: String, + pub account: Account, + pub issued: i64, + pub expires: i64, +} + +impl Token { + pub async fn from_id(db: &Database, id: i64) -> Option { + let record = sqlx::query_as!(RawToken, "SELECT * FROM tokens WHERE id = $1", id) + .fetch_one(&db.pool) + .await; + + match record { + Ok(r) => Some(r.complete(db).await), + Err(_) => None, + } + } + + pub async fn from_access_token(db: &Database, access: String) -> Option { + let record = sqlx::query_as!(RawToken, "SELECT * FROM tokens WHERE access = $1", access) + .fetch_one(&db.pool) + .await; + + match record { + Ok(r) => Some(r.complete(db).await), + Err(_) => None + } + } + + pub async fn from_client_token(db: &Database, client: String) -> Option { + let record = sqlx::query_as!(RawToken, "SELECT * FROM tokens WHERE client = $1", client) + .fetch_one(&db.pool) + .await; + + match record { + Ok(r) => Some(r.complete(db).await), + Err(_) => None + } + } + + pub fn random_token() -> String { + random_string::generate(128, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.") + } + + async fn remove_expired(db: &Database) -> Result<()> { + let time = (get_unix_timestamp() / 1000) as f64; + sqlx::query!("DELETE FROM tokens WHERE expires <= $1", time) + .execute(&db.pool) + .await?; + + Ok(()) + } + + pub async fn validate_with(&self, db: &Database, client: String, allow_old: bool) -> Result { + Self::remove_expired(db).await?; + + Ok({ + if self.client != client { return Ok(false) } + else if !allow_old { get_unix_timestamp() / 1000 < (self.issued + 864000) as u128 } + else { true } + }) + } + + pub async fn validate(&self, db: &Database, allow_old: bool) -> Result { + Self::remove_expired(db).await?; + + Ok({ + if !allow_old { get_unix_timestamp() / 1000 < (self.issued + 864000) as u128 } + else { true } + }) + } +} + +pub struct RawToken { + id: i64, + access: String, + client: String, + account: i64, + issued: i64, + expires: i64 +} + +impl RawToken { + pub async fn complete(self, db: &Database) -> Token { + Token { + id: self.id, + access: self.access, + client: self.client, + account: Account::from_id(db, self.account).await.expect("Couldn't resolve token owner"), + issued: self.issued, + expires: self.expires, + } + } +}