summaryrefslogtreecommitdiff
path: root/server/src/models
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/models')
-rw-r--r--server/src/models/auth.rs63
-rw-r--r--server/src/models/mod.rs1
-rw-r--r--server/src/models/user.rs22
3 files changed, 85 insertions, 1 deletions
diff --git a/server/src/models/auth.rs b/server/src/models/auth.rs
new file mode 100644
index 0000000..03b198b
--- /dev/null
+++ b/server/src/models/auth.rs
@@ -0,0 +1,63 @@
+use crate::errors::AppError;
+use chrono::{Duration, Local};
+use jsonwebtoken::{encode, DecodingKey, EncodingKey, Header, Validation};
+use once_cell::sync::Lazy;
+use serde::{Deserialize, Serialize};
+
+struct Keys {
+ encoding: EncodingKey,
+ decoding: DecodingKey,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct Claims {
+ user_id: i32,
+ exp: usize,
+}
+
+#[derive(Serialize)]
+pub struct AuthBody {
+ access_token: String,
+ token_type: String,
+}
+
+static KEYS: Lazy<Keys> = Lazy::new(|| {
+ let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");
+ Keys::new(secret.as_bytes())
+});
+
+impl Keys {
+ fn new(secret: &[u8]) -> Self {
+ Self {
+ encoding: EncodingKey::from_secret(secret),
+ decoding: DecodingKey::from_secret(secret),
+ }
+ }
+}
+
+impl Claims {
+ pub fn new(user_id: i32) -> Self {
+ let expiration = Local::now() + Duration::days(2);
+
+ Self {
+ user_id,
+ exp: expiration.timestamp() as usize,
+ }
+ }
+
+ pub fn get_token(&self) -> Result<String, AppError> {
+ let token = encode(&Header::default(), &self, &KEYS.encoding)
+ .map_err(|_| AppError::TokenCreation)?;
+
+ Ok(token)
+ }
+}
+
+impl AuthBody {
+ pub fn new(access_token: String) -> Self {
+ Self {
+ access_token,
+ token_type: "Bearer".to_string(),
+ }
+ }
+}
diff --git a/server/src/models/mod.rs b/server/src/models/mod.rs
index 22d12a3..f9bae3d 100644
--- a/server/src/models/mod.rs
+++ b/server/src/models/mod.rs
@@ -1 +1,2 @@
+pub mod auth;
pub mod user;
diff --git a/server/src/models/user.rs b/server/src/models/user.rs
index 964f04a..38ec121 100644
--- a/server/src/models/user.rs
+++ b/server/src/models/user.rs
@@ -16,7 +16,7 @@ pub struct User {
#[derive(Deserialize, Serialize)]
pub struct UserList {
- id: i32,
+ pub id: i32,
email: String,
is_staff: Option<bool>,
}
@@ -61,6 +61,26 @@ impl User {
Ok(rec)
}
+ pub async fn find(user: User) -> Result<UserList, AppError> {
+ let pool = unsafe { get_client() };
+
+ let crypted_password = sha256::digest(user.password);
+
+ let rec = sqlx::query_as!(
+ UserList,
+ r#"
+ SELECT id, email, is_staff FROM "users"
+ WHERE email = $1 AND password = $2
+ "#,
+ user.email,
+ crypted_password
+ )
+ .fetch_one(pool)
+ .await?;
+
+ Ok(rec)
+ }
+
pub async fn list() -> Result<Vec<UserList>, AppError> {
let pool = unsafe { get_client() };
let rows = sqlx::query_as!(UserList, r#"SELECT id, email, is_staff FROM users"#)