Skip to content

Commit

Permalink
wip: no errors
Browse files Browse the repository at this point in the history
  • Loading branch information
sargon64 committed Dec 12, 2023
1 parent ba5bbf8 commit 5df6063
Show file tree
Hide file tree
Showing 12 changed files with 879 additions and 517 deletions.
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ tracing-log = "0.2.0"
tracing-subscriber = { version = "0.3.18", features = ["chrono", "env-filter", "fmt"] }
poem = "1.3.59"
async-graphql-poem = "6.0.11"
tokio = { version = "1.35.0", features = ["macros"] }
tokio = { version = "1.35.0", features = ["macros", "rt-multi-thread"] }
sqlx = { version = "0.7.3", features = ["runtime-tokio-rustls", "postgres", "uuid", "chrono"] }
anyhow = "1.0.75"
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
fn main() {
// trigger recompilation when a new migration is added
println!("cargo:rerun-if-changed=migrations");
}
}
91 changes: 50 additions & 41 deletions src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use chrono::{DateTime, Utc};
use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, DatabaseConnection};
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;

use crate::{KEY, Key, users::User};
use crate::{models, users::User, Key, KEY};

bitflags::bitflags! {
pub struct Permission: i32 {
Expand All @@ -23,15 +23,15 @@ bitflags::bitflags! {

#[derive(Debug, Serialize, Deserialize)]
pub struct JWTAuth {
pub user: entity::users::Model,
pub user: models::dUser,
#[serde(with = "chrono::serde::ts_seconds")]
pub(crate) exp: DateTime<Utc>, // Required (validate_exp defaults to true in validation). Expiration time (as UTC timestamp)
#[serde(with = "chrono::serde::ts_seconds")]
pub(crate) iat: DateTime<Utc>, // Optional. Issued at (as UTC timestamp)
}

impl JWTAuth {
pub fn new(user: entity::users::Model) -> Self {
pub fn new(user: models::dUser) -> Self {
let now = Utc::now();

Self {
Expand All @@ -47,20 +47,26 @@ impl JWTAuth {

pub fn decode(dec: String, key: Key) -> Option<Self> {
let token = match jsonwebtoken::decode::<JWTAuth>(
&dec,
&jsonwebtoken::DecodingKey::from_secret(&key.0),
&jsonwebtoken::Validation::default(),
) {
Err(_) => { return None; },
Ok(t) => if t.claims.is_valid() { Some(t) } else { None }
&dec,
&jsonwebtoken::DecodingKey::from_secret(&key.0),
&jsonwebtoken::Validation::default(),
) {
Err(_) => {
return None;
}
Ok(t) => {
if t.claims.is_valid() {
Some(t)
} else {
None
}
}
};

Some(token.unwrap().claims)
}

pub fn encode(&self, key: Key) -> String {


jsonwebtoken::encode(
&jsonwebtoken::Header::default(),
&self,
Expand All @@ -74,50 +80,53 @@ impl JWTAuth {
pub enum Authorization {
Session(String),
ApiKey(Uuid),
None
None,
}

impl Authorization {
pub fn parse(s: Option<String>) -> Self {
match s {
Some(s) => {
match Uuid::parse_str(&s) {
Ok(uuid) => Self::ApiKey(uuid),
Err(_) => Self::Session(s)
}
Some(s) => match Uuid::parse_str(&s) {
Ok(uuid) => Self::ApiKey(uuid),
Err(_) => Self::Session(s),
},
None => Self::None
None => Self::None,
}
}

pub async fn get_user(&self, db: &DatabaseConnection) -> Option<entity::users::Model> {
pub async fn get_user(&self, db: &PgPool) -> Option<models::dUser> {
match self {
Self::Session(s) => {
let auth = JWTAuth::decode(s.to_string(), *KEY.clone());
match auth {
Some(auth) => {
let user = entity::users::Entity::find_by_id(auth.user.id)
.one(db)
.await
.unwrap()
.unwrap();
let user = sqlx::query_as!(
models::dUser,
"SELECT * FROM users WHERE id = $1",
auth.user.id
)
.fetch_one(db)
.await
.unwrap();

Some(user)
},
None => None
}
None => None,
}
},
}
Self::ApiKey(uuid) => {
let user = entity::users::Entity::find()
.filter(entity::users::Column::ApiKey.eq(sea_orm::prelude::Uuid::from_bytes(*uuid.as_bytes())))
.one(db)
.await
.unwrap()
.unwrap();
let user = sqlx::query_as!(
models::dUser,
"SELECT * FROM users WHERE api_key = $1",
sqlx::types::Uuid::from_bytes(*uuid.as_bytes())
)
.fetch_one(db)
.await
.unwrap();

Some(user)
},
_ => None
}
_ => None,
}
}
}
Expand All @@ -132,7 +141,7 @@ impl HasPermissions for &User {
}
}

impl HasPermissions for &entity::users::Model {
impl HasPermissions for &models::dUser {
fn permissions(&self) -> i32 {
self.permissions
}
Expand All @@ -144,7 +153,7 @@ impl HasPermissions for &mut User {
}
}

impl HasPermissions for &mut entity::users::Model {
impl HasPermissions for &mut models::dUser {
fn permissions(&self) -> i32 {
self.permissions
}
Expand All @@ -156,12 +165,12 @@ impl HasPermissions for User {
}
}

impl HasPermissions for entity::users::Model {
impl HasPermissions for models::dUser {
fn permissions(&self) -> i32 {
self.permissions
}
}

pub async fn validate_permissions<T: HasPermissions>(user: T, required: Permission) -> bool {
required.bits() & user.permissions() != 0
}
}
73 changes: 49 additions & 24 deletions src/cdn.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use entity::prelude::*;
use forge_lib::structs::v1::{unpack_v1_forgemod, ForgeModTypes};

use poem::{handler, web::Path, Response, IntoResponse, http::StatusCode};
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, DatabaseConnection};
use poem::{handler, http::StatusCode, web::Path, IntoResponse, Response};
use serde::Deserialize;
use sqlx::PgPool;

use crate::DB_POOL;
use crate::{models, DB_POOL};

#[derive(Copy, Clone, Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
Expand All @@ -15,61 +14,87 @@ pub enum CdnType {
}

async fn cdn_handler(
db: DatabaseConnection,
db: &PgPool,
slug: String,
version: String,
dl_type: CdnType,
) -> impl IntoResponse {
let db_mod = Mods::find()
.filter(entity::mods::Column::Slug.eq(&slug))
.one(&db)
// let db_mod = Mods::find()
// .filter(entity::mods::Column::Slug.eq(&slug))
// .one(&db)
// .await
// .unwrap();
let db_mod = sqlx::query_as!(models::dMod, "SELECT * FROM mods WHERE slug = $1", slug)
.fetch_optional(db)
.await
.unwrap();

if let Some(db_mod) = db_mod {
let db_version = Versions::find()
.filter(entity::versions::Column::ModId.eq(db_mod.id))
.filter(entity::versions::Column::Version.eq(&version))
.one(&db)
.await
.unwrap();
// let db_version = Versions::find()
// .filter(entity::versions::Column::ModId.eq(db_mod.id))
// .filter(entity::versions::Column::Version.eq(&version))
// .one(&db)
// .await
// .unwrap();
let db_version = sqlx::query_as!(
models::dVersion,
"SELECT * FROM versions WHERE mod_id = $1 AND version = $2",
db_mod.id,
version
)
.fetch_optional(db)
.await
.unwrap();

if let Some(db_version) = db_version {
let file = match std::fs::read(format!(
"./data/cdn/{}/{}.forgemod",
db_mod.id, db_version.id
)) {
Ok(file) => file,
Err(_) => return Response::builder().status(StatusCode::NOT_FOUND).body("Not Found"),
Err(_) => {
return Response::builder()
.status(StatusCode::NOT_FOUND)
.body("Not Found")
}
};
match dl_type {
CdnType::Dll => {
let package = unpack_v1_forgemod(&*file).unwrap();

match package {
ForgeModTypes::Mod(m) =>
{
ForgeModTypes::Mod(m) => {
return Response::builder()
.header("Content-Type", "application/octet-stream")
.header("Content-Disposition", format!("attachment; filename=\"{}.dll\"", m.manifest._id))
.header(
"Content-Disposition",
format!("attachment; filename=\"{}.dll\"", m.manifest._id),
)
.body(m.data.artifact_data);
},
}
_ => {
return Response::builder().status(StatusCode::NOT_FOUND).body("Not Found");
return Response::builder()
.status(StatusCode::NOT_FOUND)
.body("Not Found");
}
}
}
CdnType::Package => {
return Response::builder()
.header("Content-Type", "application/octet-stream")
.header("Content-Disposition", format!("attachment; filename=\"{}-v{}.beatforge\"", slug, version))
.header(
"Content-Disposition",
format!("attachment; filename=\"{}-v{}.beatforge\"", slug, version),
)
.body(file);
}
}
}
}

Response::builder().status(StatusCode::NOT_FOUND).body("Not Found")
Response::builder()
.status(StatusCode::NOT_FOUND)
.body("Not Found")
}

// #[get("/cdn/{slug}@{version}/{type}")]
Expand All @@ -79,7 +104,7 @@ pub async fn cdn_get(
// path: web::Path<(String, String, CdnType)>,
Path((slug, version, dl_type)): Path<(String, String, CdnType)>,
) -> impl IntoResponse {
let db = DB_POOL.get().unwrap().clone();
let db = DB_POOL.get().unwrap();

cdn_handler(db, slug, version, dl_type).await
}
Expand All @@ -91,7 +116,7 @@ pub async fn cdn_get_typeless(
// path: web::Path<(String, String)>,
Path((slug, version)): Path<(String, String)>,
) -> impl IntoResponse {
let db = DB_POOL.get().unwrap().clone();
let db = DB_POOL.get().unwrap();

cdn_handler(db, slug, version, CdnType::Package).await
}
Loading

0 comments on commit 5df6063

Please sign in to comment.