aaaa
This commit is contained in:
parent
4d167f7160
commit
0ccf714d73
6 changed files with 160 additions and 6 deletions
48
Cargo.lock
generated
48
Cargo.lock
generated
|
@ -47,6 +47,18 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argon2"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"blake2",
|
||||||
|
"cpufeatures",
|
||||||
|
"password-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atoi"
|
name = "atoi"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -158,6 +170,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake2"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
@ -208,7 +229,9 @@ checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -574,7 +597,10 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
name = "goathacks-backend"
|
name = "goathacks-backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argon2",
|
||||||
"axum",
|
"axum",
|
||||||
|
"chrono",
|
||||||
|
"kankyo",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -585,6 +611,7 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -978,6 +1005,12 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kankyo"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "325a11231fa70c1d1b562655db757cefb6022876d62f173831f35bd670ae0c40"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -1268,6 +1301,17 @@ dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "password-hash"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pem-rfc7468"
|
name = "pem-rfc7468"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -2440,6 +2484,10 @@ name = "uuid"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.2",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
|
|
19
Cargo.toml
19
Cargo.toml
|
@ -9,10 +9,20 @@ thiserror="2"
|
||||||
tracing="0.1"
|
tracing="0.1"
|
||||||
tracing-subscriber={version="0.3", features=["env-filter"]}
|
tracing-subscriber={version="0.3", features=["env-filter"]}
|
||||||
tracing-appender="0.2"
|
tracing-appender="0.2"
|
||||||
axum = "0.8"
|
|
||||||
|
|
||||||
serde_json="1"
|
serde_json="1"
|
||||||
|
|
||||||
|
kankyo = "0.3"
|
||||||
|
|
||||||
|
chrono = "0.4"
|
||||||
|
|
||||||
|
argon2 = "0.5"
|
||||||
|
|
||||||
|
[dependencies.axum]
|
||||||
|
version = "0.8"
|
||||||
|
features = [
|
||||||
|
"json"
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version="0.12"
|
version="0.12"
|
||||||
|
@ -26,6 +36,13 @@ features=["trace"]
|
||||||
version="1"
|
version="1"
|
||||||
features=["derive"]
|
features=["derive"]
|
||||||
|
|
||||||
|
[dependencies.uuid]
|
||||||
|
version = "1"
|
||||||
|
features = [
|
||||||
|
"v4",
|
||||||
|
"serde"
|
||||||
|
]
|
||||||
|
|
||||||
# Async runtime
|
# Async runtime
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version="1"
|
version="1"
|
||||||
|
|
22
src/errors.rs
Normal file
22
src/errors.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
use axum::http::StatusCode;
|
||||||
|
use axum::Json;
|
||||||
|
use serde_json::json;
|
||||||
|
use thiserror::Error as thisError;
|
||||||
|
|
||||||
|
#[derive(thisError, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Invalid value provided: {0}")]
|
||||||
|
ValueError(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type EmptyResult = Result<()>;
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
impl IntoResponse for Error {
|
||||||
|
fn into_response(self) -> axum::response::Response {
|
||||||
|
let body = json!({"status": "error", "message": format!("{}", self)});
|
||||||
|
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(body)).into_response()
|
||||||
|
}
|
||||||
|
}
|
14
src/main.rs
14
src/main.rs
|
@ -1,22 +1,26 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use axum::{routing::get, Router};
|
use axum::{Router, routing::get};
|
||||||
use sqlx::postgres::PgPoolOptions;
|
use sqlx::postgres::PgPoolOptions;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
mod models;
|
||||||
|
mod errors;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "goathacks-backend=debug".into()))
|
.with(
|
||||||
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||||
|
.unwrap_or_else(|_| "goathacks-backend=debug".into()),
|
||||||
|
)
|
||||||
.with(tracing_subscriber::fmt::layer())
|
.with(tracing_subscriber::fmt::layer())
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let db_connection_str = std::env::var("DATABASE_URL")
|
let db_connection_str =
|
||||||
.unwrap_or_else(|_| "postgres://localhost/goathacks".into());
|
std::env::var("DATABASE_URL").unwrap_or_else(|_| "postgres://localhost/goathacks".into());
|
||||||
|
|
||||||
let pool = PgPoolOptions::new()
|
let pool = PgPoolOptions::new()
|
||||||
.max_connections(5)
|
.max_connections(5)
|
||||||
|
|
1
src/models/mod.rs
Normal file
1
src/models/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mod users;
|
62
src/models/users.rs
Normal file
62
src/models/users.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*! Users are entities that interact with the system.
|
||||||
|
*
|
||||||
|
* They are notably separate from any API tokens.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
use argon2::{password_hash::{rand_core::OsRng, SaltString}, Argon2};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
use crate::errors::{EmptyResult, Result};
|
||||||
|
|
||||||
|
/** A single User with access to the system
|
||||||
|
*
|
||||||
|
* The specific User object contains profile and biographic data that's either useful to ACM or
|
||||||
|
* required by external partners (see: MLH).
|
||||||
|
*/
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct User {
|
||||||
|
/// Unique user identifier, a V4 UUID
|
||||||
|
id: uuid::Uuid,
|
||||||
|
/// The user's name. Not guaranteed to be anything in particular, should be
|
||||||
|
/// treated as a standard UTF8 string
|
||||||
|
name: String,
|
||||||
|
/// User's (hashed) password
|
||||||
|
password_hash: String,
|
||||||
|
/// User's email. This must be validated for correct format!
|
||||||
|
email: String,
|
||||||
|
/// Whether the user is allowed to log in.
|
||||||
|
is_active: bool,
|
||||||
|
/// UTC date/time of creation
|
||||||
|
created: chrono::DateTime<Utc>,
|
||||||
|
/// UTC date/time of last login
|
||||||
|
last_login: Option<DateTime<Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for User {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} ({})", self.email, self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for User {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} ({})", self.email, self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
pub fn new_user() -> Self {
|
||||||
|
Self { id: uuid::Uuid::new_v4(), name: String::new(), password_hash: String::new(), email: String::new(), is_active: true, created: Utc::now(), last_login: None }
|
||||||
|
}
|
||||||
|
pub fn set_password(new_pw: String) -> EmptyResult {
|
||||||
|
|
||||||
|
let argon = Argon2::default();
|
||||||
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
|
|
||||||
|
let mut out: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue