:3
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
use axum::{Router, http::StatusCode, routing::get};
|
||||
use crate::db::Database;
|
||||
use axum::{Router, extract::State, http::StatusCode, routing::get};
|
||||
|
||||
async fn root() -> (StatusCode, &'static str) {
|
||||
pub mod user;
|
||||
|
||||
async fn root(State(state): State<Database>) -> (StatusCode, &'static str) {
|
||||
(StatusCode::OK, "We Good twin :3c")
|
||||
}
|
||||
|
||||
pub fn register_routes() -> Router {
|
||||
let router = Router::new().route("/", get(root));
|
||||
pub fn register_routes() -> Router<Database> {
|
||||
let router = Router::new()
|
||||
.route("/", get(root))
|
||||
.nest("/user", user::register_routes());
|
||||
|
||||
Router::new().nest("/api", router)
|
||||
}
|
||||
|
||||
17
src/api/user/login.rs
Normal file
17
src/api/user/login.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::State,
|
||||
http::{HeaderMap, HeaderValue, StatusCode},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
|
||||
use crate::db::Database;
|
||||
|
||||
pub async fn route(State(db): State<Database>) -> Response {
|
||||
Response::builder()
|
||||
.header("Location", "/")
|
||||
.header("Set-Cookie", &format!("session=meowmeowmeow"))
|
||||
.status(StatusCode::SEE_OTHER)
|
||||
.body(Body::empty())
|
||||
.unwrap()
|
||||
}
|
||||
15
src/api/user/mod.rs
Normal file
15
src/api/user/mod.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use axum::{
|
||||
Router,
|
||||
routing::{get, post},
|
||||
};
|
||||
|
||||
use crate::db::Database;
|
||||
|
||||
pub mod login;
|
||||
pub mod register;
|
||||
|
||||
pub fn register_routes() -> Router<Database> {
|
||||
Router::new()
|
||||
.route("/register", post(register::route))
|
||||
.route("/login", post(login::route))
|
||||
}
|
||||
17
src/api/user/register.rs
Normal file
17
src/api/user/register.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::State,
|
||||
http::{HeaderMap, HeaderValue, StatusCode},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
|
||||
use crate::db::Database;
|
||||
|
||||
pub async fn route(State(db): State<Database>) -> Response {
|
||||
Response::builder()
|
||||
.header("Location", "/")
|
||||
.header("Set-Cookie", &format!("session=meowmeowmeow"))
|
||||
.status(StatusCode::SEE_OTHER)
|
||||
.body(Body::empty())
|
||||
.unwrap()
|
||||
}
|
||||
23
src/db/mod.rs
Normal file
23
src/db/mod.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use anyhow::Result;
|
||||
use sqlx::{Pool, Postgres, postgres::PgPoolOptions};
|
||||
|
||||
pub mod tables;
|
||||
|
||||
pub type CurrPool = Pool<Postgres>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Database {
|
||||
pool: CurrPool,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub async fn connect() -> Result<Self> {
|
||||
let url = "postgres://postgres:postgres@127.0.0.1:5432/persmgr";
|
||||
let pool = PgPoolOptions::new().connect(url).await?;
|
||||
Ok(Self { pool })
|
||||
}
|
||||
|
||||
pub fn pool(&self) -> &CurrPool {
|
||||
&self.pool
|
||||
}
|
||||
}
|
||||
1
src/db/tables/mod.rs
Normal file
1
src/db/tables/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod user;
|
||||
135
src/db/tables/user.rs
Normal file
135
src/db/tables/user.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
use anyhow::bail;
|
||||
|
||||
use crate::db::CurrPool;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct User {
|
||||
pub id: i64,
|
||||
pub email: String,
|
||||
pub verified_email: bool,
|
||||
pub username: String,
|
||||
pub pw_hash: String,
|
||||
pub pw_salt: String,
|
||||
pub pfp_id: i64,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub async fn get_by_id(pool: &CurrPool, id: i64) -> anyhow::Result<Self> {
|
||||
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
Ok(user)
|
||||
}
|
||||
pub async fn get_by_email(pool: &CurrPool, email: String) -> anyhow::Result<Self> {
|
||||
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE email = $1", email)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
Ok(user)
|
||||
}
|
||||
pub async fn get_by_username(pool: &CurrPool, username: String) -> anyhow::Result<Self> {
|
||||
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE username = $1", username)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
Ok(user)
|
||||
}
|
||||
pub async fn insert_new(&self, pool: &CurrPool) -> anyhow::Result<()> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO users (email, username, pw_hash, pw_salt)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
"#,
|
||||
self.email,
|
||||
self.username,
|
||||
self.pw_hash,
|
||||
self.pw_salt
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_username(
|
||||
&mut self,
|
||||
pool: &CurrPool,
|
||||
username: String,
|
||||
) -> anyhow::Result<&mut Self> {
|
||||
let new_user = sqlx::query_as!(
|
||||
User,
|
||||
"UPDATE users SET username = $1 WHERE id = $2 RETURNING *",
|
||||
username,
|
||||
self.id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
*self = new_user;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub async fn set_email(&mut self, pool: &CurrPool, email: String) -> anyhow::Result<&mut Self> {
|
||||
let new_user = sqlx::query_as!(
|
||||
User,
|
||||
"UPDATE users SET email = $1 WHERE id = $2 RETURNING *",
|
||||
email,
|
||||
self.id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
*self = new_user;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub async fn set_pw_hash(
|
||||
&mut self,
|
||||
pool: &CurrPool,
|
||||
pw_hash: String,
|
||||
) -> anyhow::Result<&mut Self> {
|
||||
let new_user = sqlx::query_as!(
|
||||
User,
|
||||
"UPDATE users SET pw_hash = $1 WHERE id = $2 RETURNING *",
|
||||
pw_hash,
|
||||
self.id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
*self = new_user;
|
||||
Ok(self)
|
||||
}
|
||||
pub async fn set_pw_salt(
|
||||
&mut self,
|
||||
pool: &CurrPool,
|
||||
pw_salt: String,
|
||||
) -> anyhow::Result<&mut Self> {
|
||||
let new_user = sqlx::query_as!(
|
||||
User,
|
||||
"UPDATE users SET pw_salt = $1 WHERE id = $2 RETURNING *",
|
||||
pw_salt,
|
||||
self.id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
*self = new_user;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub async fn set_email_verification_status(
|
||||
&mut self,
|
||||
pool: &CurrPool,
|
||||
status: bool,
|
||||
) -> anyhow::Result<&mut Self> {
|
||||
let new_user = sqlx::query_as!(
|
||||
User,
|
||||
"UPDATE users SET verified_email = $1 WHERE id = $2 RETURNING *",
|
||||
status,
|
||||
self.id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
*self = new_user;
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
22
src/main.rs
22
src/main.rs
@@ -1,10 +1,13 @@
|
||||
use axum::Router;
|
||||
use tower::ServiceBuilder;
|
||||
use tower_cookies::cookie::time::Duration;
|
||||
use tower_http::{services::ServeDir, trace::TraceLayer};
|
||||
use tower_sessions::{MemoryStore, SessionManagerLayer};
|
||||
use tracing::{info, level_filters::LevelFilter};
|
||||
use tracing_subscriber::FmtSubscriber;
|
||||
|
||||
mod api;
|
||||
mod db;
|
||||
mod pages;
|
||||
|
||||
#[tokio::main]
|
||||
@@ -14,13 +17,28 @@ async fn main() {
|
||||
.finish();
|
||||
tracing::subscriber::set_global_default(sub).unwrap();
|
||||
|
||||
info!("Connecting to DB");
|
||||
|
||||
let pool = db::Database::connect().await.unwrap();
|
||||
|
||||
info!("Server starting");
|
||||
|
||||
let session_store = MemoryStore::default();
|
||||
let session_layer = SessionManagerLayer::new(session_store)
|
||||
.with_secure(false)
|
||||
.with_expiry(tower_sessions::Expiry::OnInactivity(Duration::days(30)));
|
||||
|
||||
let app = Router::new()
|
||||
.merge(pages::register_routes())
|
||||
.merge(api::register_routes())
|
||||
.merge(pages::register_routes())
|
||||
.with_state(pool)
|
||||
.fallback_service(ServiceBuilder::new().service(ServeDir::new("res")))
|
||||
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));
|
||||
.layer(
|
||||
ServiceBuilder::new()
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.layer(tower_livereload::LiveReloadLayer::new())
|
||||
.layer(session_layer),
|
||||
);
|
||||
|
||||
let laddr = "0.0.0.0:8080";
|
||||
|
||||
|
||||
12
src/pages/login.rs
Normal file
12
src/pages/login.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use askama::Template;
|
||||
use axum::{http::StatusCode, response::Html};
|
||||
|
||||
#[derive(Debug, Template, Clone)]
|
||||
#[template(path = "login.html")]
|
||||
pub struct PageTemplate {}
|
||||
|
||||
pub async fn page() -> (StatusCode, Html<String>) {
|
||||
let page = PageTemplate {};
|
||||
|
||||
(StatusCode::OK, Html(page.render().unwrap()))
|
||||
}
|
||||
@@ -1,14 +1,20 @@
|
||||
use axum::{Router, routing::get};
|
||||
|
||||
use crate::db;
|
||||
|
||||
pub mod documents;
|
||||
pub mod events;
|
||||
pub mod index;
|
||||
pub mod login;
|
||||
pub mod register;
|
||||
pub mod roster;
|
||||
|
||||
pub fn register_routes() -> Router {
|
||||
pub fn register_routes() -> Router<db::Database> {
|
||||
Router::new()
|
||||
.route("/", get(index::page))
|
||||
.route("/roster", get(roster::page))
|
||||
.route("/events", get(events::page))
|
||||
.route("/documents", get(documents::page))
|
||||
.route("/login", get(login::page))
|
||||
.route("/register", get(register::page))
|
||||
}
|
||||
|
||||
12
src/pages/register.rs
Normal file
12
src/pages/register.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use askama::Template;
|
||||
use axum::{http::StatusCode, response::Html};
|
||||
|
||||
#[derive(Debug, Template, Clone)]
|
||||
#[template(path = "register.html")]
|
||||
pub struct PageTemplate {}
|
||||
|
||||
pub async fn page() -> (StatusCode, Html<String>) {
|
||||
let page = PageTemplate {};
|
||||
|
||||
(StatusCode::OK, Html(page.render().unwrap()))
|
||||
}
|
||||
Reference in New Issue
Block a user