Skip to content
Open
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
673 changes: 429 additions & 244 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ async-trait = "0.1.89"
base64 = "0.22.1"
chrono = { version = "0.4", features = ["serde"] }
futures-util = "0.3"
mairie360_api_lib = "0.6.0"
lettre = { version = "0.11", default-features = false, features = ["smtp-transport", "tokio1-rustls", "ring", "webpki-roots", "builder"] }
mairie360_api_lib = "0.7.0"
rand = "0.10"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
Expand All @@ -24,7 +25,6 @@ uuid = { version = "1.0", features = ["v4", "serde"] }
serial_test = "3.3.1"
once_cell = "1.21.3"


[profile.dev]
opt-level = 0

Expand Down
25 changes: 22 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ x-service: &service-template

services:
postgres:
image: ghcr.io/mairie360/database:dev-c3cce15
image: ghcr.io/mairie360/database:dev-e9990d6
restart: always
container_name: mairie360-db-core-api
environment:
Expand All @@ -62,7 +62,7 @@ services:
retries: 5

liquibase:
image: ghcr.io/mairie360/liquibase-migrations:dev-c3cce15
image: ghcr.io/mairie360/liquibase-migrations:dev-e9990d6
container_name: mairie360-liquibase-core-api
depends_on:
postgres:
Expand Down Expand Up @@ -100,6 +100,7 @@ services:
build:
context: .
dockerfile: development.Dockerfile
restart: always
develop:
watch:
- action: sync
Expand All @@ -125,6 +126,11 @@ services:
PUBLIC_URL: http://core.development.mairie360.fr
JWT_SECRET: b"secret"
JWT_TIMEOUT: 3600
SMTP_HOST: "mailpit" # Nom du service docker
SMTP_PORT: "1025" # Port SMTP de mailpit
SMTP_USERNAME: "" # Pas besoin d'authentification en local
SMTP_PASSWORD: "" # Pas besoin d'authentification en local
EMAIL_FROM: "noreply.mairie360@dev.local"
depends_on:
liquibase:
condition: service_completed_successfully
Expand All @@ -137,6 +143,19 @@ services:
retries: 5
start_period: 90s

mailpit:
image: axllent/mailpit:v1.15
container_name: mairie360-mailpit
restart: always
ports:
- "8025:8025" # Interface Web pour voir les mails (http://localhost:8025)
- "1025:1025" # Le port SMTP pour ton code Rust
networks:
- backend
depends_on:
core:
condition: service_healthy

nginx:
image: nginx:1.29.1-bookworm
restart: always
Expand All @@ -147,5 +166,5 @@ services:
networks:
- backend
depends_on:
core:
mailpit:
condition: service_healthy
Comment thread
Quentintnrl marked this conversation as resolved.
2 changes: 1 addition & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ set -e
cd /usr/src/core

# Lancer cargo watch
exec cargo watch -w src -i target -x run
exec cargo watch --poll -w src -i target -x run
5 changes: 5 additions & 0 deletions src/database/auth/change_password/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod query;
pub use query::change_password_query;

mod view;
pub use view::ChangePasswordQueryView;
18 changes: 18 additions & 0 deletions src/database/auth/change_password/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use mairie360_api_lib::database::db_interface::DatabaseQueryView;
use mairie360_api_lib::database::errors::DatabaseError;
use sqlx::PgPool;

use crate::database::auth::change_password::ChangePasswordQueryView;

pub async fn change_password_query(
view: ChangePasswordQueryView,
pool: PgPool,
) -> Result<(), DatabaseError> {
sqlx::query(&view.get_request())
.bind(view.get_password())
.bind(view.get_user_id() as i32)
.execute(&pool)
.await?;

Ok(())
}
68 changes: 68 additions & 0 deletions src/database/auth/change_password/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use mairie360_api_lib::database::db_interface::DatabaseQueryView;
use std::fmt::Display;

pub struct ChangePasswordQueryView {
password: String,
user_id: u64,
}

impl ChangePasswordQueryView {
pub fn new(password: &str, user_id: u64) -> Self {
Self {
password: password.to_string(),
user_id,
}
}

pub fn get_password(&self) -> &str {
&self.password
}

pub fn get_user_id(&self) -> u64 {
self.user_id
}
}

impl DatabaseQueryView for ChangePasswordQueryView {
fn get_request(&self) -> String {
"UPDATE users SET password = $1 WHERE id = $2".to_string()
}
}

impl Display for ChangePasswordQueryView {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ChangePasswordQueryView: password = [PROTECTED]")
}
}

#[derive(Debug, sqlx::FromRow, PartialEq, Eq)]
pub struct LoginUserQueryResultView {
#[sqlx(rename = "id")]
user_id: i32,
#[sqlx(rename = "password")]
password: String,
#[sqlx(rename = "first_connect")]
first_connect: bool,
}

impl LoginUserQueryResultView {
pub fn new(user_id: i32, password: String, first_connect: bool) -> Self {
Self {
user_id,
password,
first_connect,
}
}

pub fn password(&self) -> &str {
&self.password
}

pub fn user_id(&self) -> i32 {
self.user_id
}

pub fn first_connect(&self) -> bool {
self.first_connect
}
}
Comment thread
Quentintnrl marked this conversation as resolved.
5 changes: 5 additions & 0 deletions src/database/auth/is_first_time/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod query;
pub use query::is_first_time_query;

mod view;
pub use view::IsFirstTimeQueryView;
16 changes: 16 additions & 0 deletions src/database/auth/is_first_time/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::database::auth::is_first_time::IsFirstTimeQueryView;
use mairie360_api_lib::database::db_interface::DatabaseQueryView;
use mairie360_api_lib::database::errors::DatabaseError;
use sqlx::PgPool;

pub async fn is_first_time_query(
view: IsFirstTimeQueryView,
pool: PgPool,
) -> Result<bool, DatabaseError> {
let result = sqlx::query_scalar::<_, bool>(&view.get_request())
.bind(view.user_id() as i32)
.fetch_one(&pool)
.await?;

Ok(result)
}
28 changes: 28 additions & 0 deletions src/database/auth/is_first_time/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use mairie360_api_lib::database::db_interface::DatabaseQueryView;
use std::fmt::Display;

pub struct IsFirstTimeQueryView {
user_id: u64,
}

impl IsFirstTimeQueryView {
pub fn new(user_id: u64) -> Self {
Self { user_id }
}

pub fn user_id(&self) -> u64 {
self.user_id
}
}

impl DatabaseQueryView for IsFirstTimeQueryView {
fn get_request(&self) -> String {
"SELECT EXISTS(SELECT 1 FROM users WHERE id = $1) AS first_connect".to_string()
Comment thread
Quentintnrl marked this conversation as resolved.
}
}

impl Display for IsFirstTimeQueryView {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "IsFirstTimeQueryView: user_id = {}", self.user_id)
}
}
5 changes: 1 addition & 4 deletions src/database/auth/login/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@ mod query;
pub use query::login_query;

mod view;
pub use view::LoginUserQueryView;

mod result_view;
pub use result_view::LoginUserQueryResultView;
pub use view::{LoginUserQueryResultView, LoginUserQueryView};
21 changes: 0 additions & 21 deletions src/database/auth/login/result_view.rs

This file was deleted.

34 changes: 33 additions & 1 deletion src/database/auth/login/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl LoginUserQueryView {

impl DatabaseQueryView for LoginUserQueryView {
fn get_request(&self) -> String {
"SELECT id, password FROM users WHERE email = $1".to_string()
"SELECT id, password, first_connect FROM users WHERE email = $1".to_string()
}
}

Expand All @@ -35,3 +35,35 @@ impl Display for LoginUserQueryView {
)
}
}

#[derive(Debug, sqlx::FromRow, PartialEq, Eq)]
pub struct LoginUserQueryResultView {
#[sqlx(rename = "id")]
user_id: i32,
#[sqlx(rename = "password")]
password: String,
#[sqlx(rename = "first_connect")]
first_connect: bool,
}

impl LoginUserQueryResultView {
pub fn new(user_id: i32, password: String, first_connect: bool) -> Self {
Self {
user_id,
password,
first_connect,
}
}

pub fn password(&self) -> &str {
&self.password
}

pub fn user_id(&self) -> i32 {
self.user_id
}

pub fn first_connect(&self) -> bool {
self.first_connect
}
}
3 changes: 3 additions & 0 deletions src/database/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
pub mod change_password;
pub mod is_first_time;
pub mod login;
pub mod register;
pub mod unset_first_connection;
5 changes: 5 additions & 0 deletions src/database/auth/unset_first_connection/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod query;
pub use query::unset_first_connection_query;

mod view;
pub use view::UnsetFirstConnectionQueryView;
16 changes: 16 additions & 0 deletions src/database/auth/unset_first_connection/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::database::auth::unset_first_connection::UnsetFirstConnectionQueryView;
use mairie360_api_lib::database::{db_interface::DatabaseQueryView, errors::DatabaseError};
use sqlx::PgPool;

pub async fn unset_first_connection_query(
view: UnsetFirstConnectionQueryView,
pool: PgPool,
) -> Result<(), DatabaseError> {
sqlx::query(&view.get_request())
.bind(view.password())
.bind(view.user_id() as i32)
.execute(&pool)
.await?;

Comment thread
Quentintnrl marked this conversation as resolved.
Ok(())
}
40 changes: 40 additions & 0 deletions src/database/auth/unset_first_connection/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use mairie360_api_lib::database::db_interface::DatabaseQueryView;
use std::fmt::Display;

pub struct UnsetFirstConnectionQueryView {
user_id: u64,
password: String,
}

impl UnsetFirstConnectionQueryView {
pub fn new(user_id: u64, password: &str) -> Self {
Self {
user_id,
password: password.to_string(),
}
}

pub fn user_id(&self) -> u64 {
self.user_id
}

pub fn password(&self) -> &str {
&self.password
}
}

impl DatabaseQueryView for UnsetFirstConnectionQueryView {
fn get_request(&self) -> String {
"UPDATE users SET first_connect = false AND password = $1 WHERE id = $2".to_string()
Comment thread
Quentintnrl marked this conversation as resolved.
}
}

impl Display for UnsetFirstConnectionQueryView {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"UnsetFirstConnectionQueryView: user_id = {}, password = [PROTECTED]",
self.user_id
)
}
}
5 changes: 5 additions & 0 deletions src/database/get_user_id/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod query;
pub use query::get_user_id_query;

mod view;
pub use view::GetUserIdQueryView;
Loading
Loading