Skip to content

Commit

Permalink
feat: add model layer for abstraction over db types
Browse files Browse the repository at this point in the history
  • Loading branch information
H1ghBre4k3r committed Aug 29, 2023
1 parent 049b39f commit f8c1f13
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 36 deletions.
8 changes: 5 additions & 3 deletions src/functions/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if #[cfg(feature = "ssr")] {
};
use crate::hooks::use_identity;
use crate::utils::password::{verify_password, hash_password};
use crate::repository::{User, UserCreateData};
use crate::model::User;
}
}

Expand Down Expand Up @@ -50,11 +50,13 @@ pub async fn register(
return Ok(RegistrationResult::PasswordsDoNotMatch);
}

if let Err(e) = User::create(UserCreateData {
if let Err(e) = (User {
username,
password: hash_password(password)?,
email,
..Default::default()
})
.create()
.await
.map_err(|_| RegistrationResult::CredentialsAlreadyTaken)
{
Expand All @@ -81,7 +83,7 @@ pub async fn login(cx: Scope, username: String, password: String) -> Result<(),
));
}

let user: Option<User> = User::get_by_username(&username).await?;
let user: Option<User> = User::get_by_username(&username).await;

let Some(user) = user else {
return Err(ServerFnError::ServerError("User not found".into()));
Expand Down
31 changes: 17 additions & 14 deletions src/hooks/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,26 @@ use surrealdb::{
Surreal,
};

pub async fn use_database(ns: impl ToString) -> Surreal<Client> {
let db = Surreal::new::<Ws>("127.0.0.1:8000")
.await
.expect("could not connect to database");
pub async fn use_database(db: impl ToString) -> Surreal<Client> {
let connection =
Surreal::new::<Ws>(env::var("SURREAL_URL").expect("no surreal url db user given"))
.await
.expect("could not connect to database");

db.signin(Root {
// TODO: these should not be hardcoded but rather extracted from environment
username: &env::var("SURREAL_USER").expect("no surreal db user given"),
password: &env::var("SURREAL_PW").expect("no surreal pw given"),
})
.await
.expect("could not login to database");
connection
.signin(Root {
// TODO: these should not be hardcoded but rather extracted from environment
username: &env::var("SURREAL_USER").expect("no surreal db user given"),
password: &env::var("SURREAL_PW").expect("no surreal pw given"),
})
.await
.expect("could not login to database");

db.use_ns("aoc-website")
.use_db(ns.to_string())
connection
.use_ns("aoc-website")
.use_db(db.to_string())
.await
.expect("could not switch to correct namespace");

db
connection
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod components;
pub mod contexts;
pub mod functions;
pub mod hooks;
pub mod model;
pub mod repository;
pub mod utils;
pub mod views;
Expand Down
9 changes: 9 additions & 0 deletions src/model/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use cfg_if::cfg_if;

cfg_if! {
if #[cfg(feature = "ssr")] {
mod user;

pub use self::user::*;
}
}
50 changes: 50 additions & 0 deletions src/model/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::error::Error;

use crate::repository::UserRepository;

#[derive(Debug, Clone, Default)]
pub struct User {
pub id: String,
pub username: String,
pub email: String,
pub password: String,
}

impl User {
pub async fn create(self) -> Result<(), Box<dyn Error>> {
let User {
username,
email,
password,
..
} = self;
UserRepository::create(username, password, email).await?;

Ok(())
}

pub async fn get_by_username(username: impl ToString) -> Option<User> {
let Some(user) = UserRepository::get_by_username(username)
.await
.ok()
.flatten()
else {
return None;
};

let id = user.id().expect("user from database should have id");
let UserRepository {
username,
password,
email,
..
} = user;

Some(Self {
id,
username,
password,
email,
})
}
}
56 changes: 37 additions & 19 deletions src/repository/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,43 @@ use surrealdb::sql::Thing;

use crate::hooks::use_database;

// TODO: maybe create this via a macro?
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct UserCreateData {
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct UserRepository {
#[serde(skip_serializing)]
id: Option<Thing>,
pub username: String,
pub password: String,
pub email: String,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct User {
id: Thing,
pub username: String,
pub password: String,
pub email: String,
}

impl User {
impl UserRepository {
const TABLE: &str = "user";

pub fn id(&self) -> String {
format!("{}:{}", self.id.tb, self.id.id)
pub fn id(&self) -> Option<String> {
self.id.as_ref().map(|id| format!("{}:{}", id.tb, id.id))
}

pub async fn get_all() -> Result<Vec<User>, surrealdb::Error> {
pub async fn get_all() -> Result<Vec<UserRepository>, surrealdb::Error> {
let db = use_database("aoc-website").await;

db.select(Self::TABLE).await
}

pub async fn get_by_id(id: impl ToString) -> Result<Option<UserRepository>, surrealdb::Error> {
let db = use_database("aoc-website").await;

let mut result = db
.query("SELECT * FROM type::table($table) where id = $id;")
.bind(("table", Self::TABLE))
.bind(("id", id.to_string()))
.await?;

result.take(0)
}

pub async fn get_by_username(
username: impl ToString,
) -> Result<Option<User>, surrealdb::Error> {
) -> Result<Option<UserRepository>, surrealdb::Error> {
let db = use_database("aoc-website").await;

let mut result = db
Expand All @@ -46,10 +51,23 @@ impl User {
result.take(0)
}

pub async fn create(data: UserCreateData) -> Result<(), surrealdb::Error> {
pub async fn create(
username: String,
password: String,
email: String,
) -> Result<Option<UserRepository>, surrealdb::Error> {
let db = use_database("aoc-website").await;
let _: Vec<User> = db.create(Self::TABLE).content(data).await?;
let result: Vec<UserRepository> = db
.create("user")
.content(UserRepository {
username,
password,
email,
..Default::default()
})
.await?;

Ok(())
// TODO: this should be changed in beta9
Ok(result.get(0).cloned())
}
}

0 comments on commit f8c1f13

Please sign in to comment.