Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 215 additions & 12 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ chrono-tz = "0.9.0"
reqwest = "0.12.3"
base64 = "0.22.0"
once_cell = "1.19.0"
validator = "0.18.1"
bcrypt = "0.15.1"
redis = { version = "0.25.4", features = ["r2d2"] }
r2d2_redis = "0.14.0"
rand = "0.8.5"
12 changes: 11 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ services:
- ./docker/db-store:/var/lib/postgresql/data
networks:
- sakura-internal
redis:
image: "redis:latest"
ports:
- "6379:6379"
volumes:
- "./docker/redis:/data"
networks:
- sakura-internal
main:
build:
context: .
Expand All @@ -28,10 +36,12 @@ services:
- .config.yaml:/app/Sakura-API
depends_on:
- db
- redis
ports:
- 8080:8080
environment:
DATABASE_URL: postgres://sakura:password@db:5432/sakura
REDIS_URL: redis://redis:6379
networks:
- sakura-internal
- sakura-external
Expand All @@ -45,4 +55,4 @@ networks:
external: false
sakura-external:
name: sakura-network
external: true
external: true
2 changes: 2 additions & 0 deletions migrations/2024-07-18-084702_create_ahth/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE auth;
7 changes: 7 additions & 0 deletions migrations/2024-07-18-084702_create_ahth/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- Your SQL goes here
CREATE TABLE auth (
id bigserial NOT NULL PRIMARY KEY,
email varchar(100) NOT NULL UNIQUE,
password varchar(255) NOT NULL,
created_at TIMESTAMPTZ NOT NULL
);
7 changes: 7 additions & 0 deletions migrations/2024-07-21-082625_add_auth_id_to_account/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- This file should undo anything in `up.sql`
ALTER TABLE account
DROP CONSTRAINT fk_auth;

ALTER TABLE account
DROP COLUMN auth_id;

8 changes: 8 additions & 0 deletions migrations/2024-07-21-082625_add_auth_id_to_account/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- Your SQL goes here
ALTER TABLE account
ADD COLUMN auth_id BIGINT NOT NULL;

ALTER TABLE account
ADD CONSTRAINT fk_auth
FOREIGN KEY (auth_id) REFERENCES auth(id);

15 changes: 12 additions & 3 deletions src/domain/object/account.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::Id;
use super::{auth::AuthId, Id};
use crate::utils::time::create_time;
use chrono::NaiveDateTime;

Expand All @@ -7,16 +7,23 @@ pub type AccountId = Id<Account>;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Account {
pub id: AccountId,
pub auth_id: AuthId,
pub username: String,
pub grade: i32,
pub expiration_date: NaiveDateTime,
pub created_at: NaiveDateTime,
}

impl Account {
pub fn new(username: String, grade: i32, expiration_date: NaiveDateTime) -> Self {
pub fn new(
auth_id: AuthId,
username: String,
grade: i32,
expiration_date: NaiveDateTime,
) -> Self {
Self {
id: Default::default(),
auth_id,
username,
grade,
expiration_date,
Expand All @@ -32,14 +39,16 @@ mod tests {

#[test]
fn test_create_account() {
let auth_id = AuthId::new(1);
let username = "test_user".to_string();
let grade = 4;
let current_time = create_time();
let expiration_date = current_time + Duration::hours(1);

let account = Account::new(username.clone(), grade, expiration_date);
let account = Account::new(auth_id, username.clone(), grade, expiration_date);

assert_eq!(account.id.get(), 0);
assert_eq!(account.auth_id.get(), 1);
assert_eq!(account.username, username);
assert_eq!(account.expiration_date, expiration_date);
}
Expand Down
48 changes: 48 additions & 0 deletions src/domain/object/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use super::Id;
use crate::utils::time::create_time;
use bcrypt::{hash, BcryptError, DEFAULT_COST};
use chrono::NaiveDateTime;
use validator::{ValidateEmail, ValidationError, ValidationErrors};

pub type AuthId = Id<Auth>;

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Auth {
pub id: AuthId,
pub email: String,
pub password: String,
pub created_at: NaiveDateTime,
}

impl Auth {
pub fn new(email: &str, password: &str) -> Self {
Self {
id: Default::default(),
email: email.to_string(),
password: password.to_string(),
created_at: create_time(),
}
}

pub fn validate(email: &str, password: &str) -> Result<(), ValidationErrors> {
let mut errors = ValidationErrors::new();
if !ValidateEmail::validate_email(&email) {
errors.add("email", ValidationError::new("Invalid email format"));
}
if password.len() < 8 {
errors.add(
"password",
ValidationError::new("Password must be at least 8 characters long"),
);
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}

pub fn hash_password(password: &str) -> Result<String, BcryptError> {
hash(password, DEFAULT_COST)
}
}
1 change: 1 addition & 0 deletions src/domain/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::marker::PhantomData;
use serde::{Deserialize, Deserializer, Serialize};

pub mod account;
pub mod auth;
pub mod card;
pub mod door;
pub mod mqtt;
Expand Down
7 changes: 7 additions & 0 deletions src/domain/repository/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use super::super::object::auth::Auth;
use anyhow;

pub trait AuthRepository {
// fn signup(&self, auth: &Auth) -> anyhow::Result<()>;
fn exist_by_email(&self, email: &str) -> anyhow::Result<bool>;
}
1 change: 1 addition & 0 deletions src/domain/repository/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod account;
pub mod auth;
pub mod card;
pub mod door;
pub mod mqtt;
Expand Down
19 changes: 19 additions & 0 deletions src/infrastructures/database/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub struct NewAccountEntity {
pub grade: i32,
pub expiration_date: NaiveDateTime,
pub created_at: NaiveDateTime,
pub auth_id: i64,
}

#[derive(Debug, Queryable, Identifiable, AsChangeset)]
Expand All @@ -19,6 +20,7 @@ pub struct AccountEntity {
pub grade: i32,
pub expiration_date: NaiveDateTime,
pub created_at: NaiveDateTime,
pub auth_id: i64,
}

#[derive(Debug, Insertable)]
Expand Down Expand Up @@ -55,3 +57,20 @@ pub struct DoorEntity {
pub door_state: bool,
pub door_switch_state: bool,
}

#[derive(Debug, Insertable)]
#[table_name = "auth"]
pub struct NewAuthEntity {
pub email: String,
pub password: String,
pub created_at: NaiveDateTime,
}

#[derive(Debug, Queryable, Identifiable, AsChangeset)]
#[table_name = "auth"]
pub struct AuthEntity {
pub id: i64,
pub email: String,
pub password: String,
pub created_at: NaiveDateTime,
}
19 changes: 18 additions & 1 deletion src/infrastructures/database/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ diesel::table! {
grade -> Int4,
expiration_date -> Timestamptz,
created_at -> Timestamptz,
auth_id -> Int8,
}
}

diesel::table! {
auth (id) {
id -> Int8,
#[max_length = 100]
email -> Varchar,
#[max_length = 255]
password -> Varchar,
created_at -> Timestamptz,
}
}

Expand All @@ -31,6 +43,11 @@ diesel::table! {
}
}

diesel::joinable!(account -> auth (auth_id));
diesel::joinable!(card -> account (account_id));

diesel::allow_tables_to_appear_in_same_query!(account, card, door,);
diesel::allow_tables_to_appear_in_same_query!(
account,
auth,
card,
door,);
6 changes: 6 additions & 0 deletions src/infrastructures/repository/account.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::super::database::models::{AccountEntity, NewAccountEntity};
use crate::domain::object::account::{Account, AccountId};
use crate::domain::object::auth::AuthId;
use crate::domain::repository::account::AccountRepository;
use anyhow;
use chrono::NaiveDateTime;
Expand All @@ -8,12 +9,14 @@ use diesel::r2d2::{ConnectionManager, Pool};

impl NewAccountEntity {
pub fn new(
auth_id: AuthId,
username: String,
grade: i32,
expiration_date: NaiveDateTime,
created_at: NaiveDateTime,
) -> Self {
Self {
auth_id: auth_id.get().to_owned(),
username,
grade,
expiration_date,
Expand All @@ -23,6 +26,7 @@ impl NewAccountEntity {

fn from(model: &Account) -> NewAccountEntity {
NewAccountEntity {
auth_id: model.auth_id.get().to_owned(),
username: model.username.to_owned(),
grade: model.grade.to_owned(),
expiration_date: model.expiration_date.to_owned(),
Expand All @@ -35,6 +39,7 @@ impl AccountEntity {
fn from(model: &Account) -> AccountEntity {
AccountEntity {
id: model.id.get(),
auth_id: model.auth_id.get().to_owned(),
username: model.username.to_owned(),
grade: model.grade.to_owned(),
expiration_date: model.expiration_date.to_owned(),
Expand All @@ -44,6 +49,7 @@ impl AccountEntity {
fn of(&self) -> Account {
Account {
id: AccountId::new(self.id),
auth_id: AuthId::new(self.auth_id),
username: self.username.to_owned(),
grade: self.grade.to_owned(),
expiration_date: self.expiration_date.to_owned(),
Expand Down
72 changes: 72 additions & 0 deletions src/infrastructures/repository/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use super::super::database::models::{AuthEntity, NewAuthEntity};
use crate::domain::object::auth::{Auth, AuthId};
use crate::domain::repository::auth::AuthRepository;
use anyhow;
use chrono::NaiveDateTime;
use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool};

impl NewAuthEntity {
pub fn new(email: String, password: String, created_at: NaiveDateTime) -> Self {
Self {
email,
password,
created_at,
}
}

fn from(model: &Auth) -> NewAuthEntity {
NewAuthEntity {
email: model.email.to_owned(),
password: model.password.to_owned(),
created_at: model.created_at.to_owned(),
}
}
}

impl AuthEntity {
fn from(model: &Auth) -> AuthEntity {
AuthEntity {
id: model.id.get(),
email: model.email.to_owned(),
password: model.password.to_owned(),
created_at: model.created_at.to_owned(),
}
}

fn of(&self) -> Auth {
Auth {
id: AuthId::new(self.id),
email: self.email.to_owned(),
password: self.password.to_owned(),
created_at: self.created_at.to_owned(),
}
}
}

pub struct AuthRepositoryImpl {
pub pool: Box<Pool<ConnectionManager<PgConnection>>>,
}

impl AuthRepository for AuthRepositoryImpl {
// fn signup(&self, auth: &Auth) -> anyhow::Result<()> {
// use super::super::database::schema::auth::dsl;

// let entity = NewAuthEntity::from(auth);
// let mut conn = self.pool.get()?;
// diesel::

// }
fn exist_by_email(&self, email: &str) -> anyhow::Result<bool> {
use super::super::database::schema::auth::dsl;

let mut conn = self.pool.get()?;
let query = dsl::auth.filter(dsl::email.eq(email));

match query.first::<AuthEntity>(&mut conn) {
Ok(_) => Ok(true),
Err(diesel::result::Error::NotFound) => Ok(false),
Err(err) => Err(anyhow::Error::new(err)),
}
}
}
1 change: 1 addition & 0 deletions src/infrastructures/repository/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod account;
pub mod auth;
pub mod card;
pub mod door;
pub mod register;
Loading