Skip to content

Commit

Permalink
attempt to add most server logic (not routes) for auth
Browse files Browse the repository at this point in the history
  • Loading branch information
callmeclover committed Apr 24, 2024
1 parent d9514aa commit 1d1f38e
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 36 deletions.
17 changes: 9 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ version = "0.1.0"
edition = "2021"

[dependencies]
axum = {version="0.7.5", features=["ws"]}
axum = { version="0.7.5", features=["ws"] }
rustrict = "0.7.24"
tokio = {version = "1.36.0", features=["full"]}
tokio = { version = "1.36.0", features=["full"] }
pulldown-cmark = "0.10.0"
tokio-tungstenite = {version="0.21.0", features=["__rustls-tls"]}
tokio-tungstenite = { version="0.21.0", features=["__rustls-tls"] }
futures-util = "0.3.30"
headers = "0.4.0"
tracing-subscriber = {version="0.3.18", features=["env-filter"]}
axum-extra = {version="0.9.3", features=["typed-header"]}
tracing-subscriber = { version="0.3.18", features=["env-filter"] }
axum-extra = { version="0.9.3", features=["typed-header"] }
tracing = "0.1.40"
futures = "0.3.30"
chrono = { version = "0.4.37", features = ["serde", "wasmbind"] }
tower-http = {version="0.5.2", features=["fs", "trace"]}
tower-http = { version="0.5.2", features=["fs", "trace"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
postgres = "0.19.7"
lazy_static = "1.4.0"
once_cell = "1.19.0"
ammonia = "4.0.0"
kuchikiki = "0.8.2"
js-sys = "0.3.69"
uuid = { version = "1.8.0", features = ["v4", "fast-rng"] }
uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] }
sea-orm = { version = "0.12", features = ["sqlx-postgres", "runtime-tokio-rustls", "macros", "with-uuid", "with-json"] }

3 changes: 3 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
- [x] Rewrite that axum example to not be an example
- [ ] Make messaging good
- [ ] Add authentication and account system


NOTE: authentication stores uuid, username, email, and password
32 changes: 12 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,36 @@
mod message;
mod user;
use message::model::*;
use message::func::{ into_censored_md, VecWithHardLimit };
use user::model::*;
use message::{ model::*, func::{ into_censored_md, VecWithHardLimit } };
use message::;
use user::{ model::*, auth::* };

use chrono::Utc;
use axum::{
extract::{ State, ws::{ Message, WebSocket, WebSocketUpgrade } },
extract::{ connect_info::ConnectInfo, State, ws::{ Message, WebSocket, WebSocketUpgrade } },
response::IntoResponse,
routing::get,
Router,
};
use pulldown_cmark::{ Parser, html::push_html };
use ammonia::clean;

use std::{ net::SocketAddr, path::PathBuf, collections::HashSet, sync::{ Arc, Mutex } };
use once_cell::sync::Lazy;
use tokio::sync::broadcast;
use tower_http::{ services::ServeDir, trace::{ DefaultMakeSpan, TraceLayer } };

use tracing_subscriber::{ layer::SubscriberExt, util::SubscriberInitExt };

//allows to extract the IP of connecting user
use axum::extract::connect_info::ConnectInfo;

//allows to split the websocket stream into separate TX and RX branches
use futures::{ sink::SinkExt, stream::StreamExt };

use postgres::Client;
use lazy_static::lazy_static;

lazy_static! {
static ref DB_CLIENT: Mutex<Client> = Mutex::new(
Client::connect("postgres://user:password@localhost/database", postgres::NoTls).unwrap()
);
}

static MESSAGES: Lazy<Mutex<Vec<MessageSent>>> = Lazy::new(|| Mutex::new(Vec::with_capacity(20)));
static USER_ID: Lazy<Arc<Mutex<i32>>> = Lazy::new(|| Arc::new(Mutex::new(0)));

lazy_static::lazy_static! {
static ref DB_CLIENT: Arc<Mutex<DatabaseConnectix>> = {
tokio::runtime::Runtime::new().unwrap().block_on(async {
DatabaseConnectix::default();
})
};
}

// Our shared state
struct AppState {
// We require unique usernames. This tracks which usernames have been taken.
Expand Down
39 changes: 39 additions & 0 deletions src/user/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use lazy_static::lazy_static;
use std::error::Error;
use sea_orm::*;
use crate::user::model::{Model, Entity as ModelEntity, Column as ModelColumn};

pub struct DatabaseConnectix {
connection: DatabaseConnection
}

impl Default for DatabaseConnectix {
pub async fn default() -> Self {
let uri = std::env::var("DB_URL").unwrap();
let db: DatabaseConnection = Database::connect(uri).await?;

return Self {
connection: db
};
}
}

impl DatabaseConnectix {
pub async fn new(uri: &str) -> Self {
let db: DatabaseConnection = Database::connect(uri).await?;

return Self {
connection: db
};
}

/// Gets a possible user id (if one exists) for a username.
pub async fn get_user_id(&self, name: &str) -> Result<i32, Box<dyn Error>> {
if let Some(res) = ModelEntity::find().expr(Expr::col("id").max()).filter(ModelColumn::Name.eq(name)).one(self.connection).await? {
if res.id == 9999 { return Box::new(Err("username is taken")); }
Ok(res.id+1)
} else {
Ok(0001)
}
}
}
3 changes: 2 additions & 1 deletion src/user/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod model;
pub mod model;
pub mod auth;
55 changes: 48 additions & 7 deletions src/user/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,74 @@ use std::error::Error;
use rustrict::{Censor, Type};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use sea_orm::prelude::*;

/// What am I?
/// A class meant to hold all the values the server uses to compute messages.
/// *Do not send me. Ever.*
#[derive(Clone)]
pub struct User {
/// Why is the user id (the number after the @) not stored here?
/// Because we can simplify this! Use the method `get_name_split()`.
pub name: String,
pub id: i32,
pub uuid: Uuid
pub glass: GlassModeration,
//pub sendable_user: SendableUser
pub sendable_user: SendableUser,
// pub password: String,
// pub email: String
}

impl User {
pub fn new(name: String) -> Self {
Self {
name,
uuid: Uuid::new_v4(),
glass: GlassModeration::default(),
sendable_user: SendableUser::new(name, self.uuid)
}
}

/// I exist because the name and id are merged into the name variable.
/// I return them seperately!
pub fn name_split(&self) -> (&str, &str) {
self.name.as_str().rsplit_once('@').unwrap()
}
}

/// What am I?
/// A struct so that we can save user data in the database.
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(column_name = "id", enum_name = "Id")]
pub id: i32,
#[sea_orm(column_name = "name", enum_name = "Name")]
pub name: String,
#[sea_orm(column_name = "uuid", enum_name = "UUID")]
pub uuid: Uuid,
#[sea_orm(column_name = "password", enum_name = "Password")]
pub password: String,
#[sea_orm(column_name = "email", enum_name = "Email")]
pub email: String,
#[sea_orm(column_name = "mod", enum_name = "Mod")]
/// This is just the DB equivalent of `glass`.
/// It's in JSON format.
pub moderation_stats: String
}

/// What am I?
/// A stripped down version of the `User` struct so that you can send something to the other clients.
#[derive(Serialize, Deserialize, Clone)]
pub struct SendableUser {
pub name: String,
pub id: i32,
pub uuid: Uuid
}

impl User {
pub fn new(name: String, id: i32) -> Self {
impl SendableUser {
pub fn new(name: String, uuid: Uuid) -> Self {
Self {
name,
id,
glass: GlassModeration::default()
uuid
}
}
}
Expand Down

0 comments on commit 1d1f38e

Please sign in to comment.