Skip to content

Commit

Permalink
backend: Use newtypes for ids
Browse files Browse the repository at this point in the history
Ids are now typed to avoid type confusion

Rerun actions
  • Loading branch information
mads256h committed Apr 5, 2024
1 parent df47303 commit 645284d
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 42 deletions.
35 changes: 35 additions & 0 deletions backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ serde = "1.0"
serde_with = "3.7"
dotenv = "0.15"
argon2 = { version = "0.5", features = ["std"] }
derive_more = "0.99"

[dev-dependencies]
tower = { version = "0.4", features = ["util"] }
Expand Down
1 change: 1 addition & 0 deletions backend/src/data_model.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod account;
pub mod device;
mod event;
pub mod task;
Expand Down
6 changes: 6 additions & 0 deletions backend/src/data_model/account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use derive_more::{From, Into};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug, sqlx::Type, PartialEq, Eq, From, Into)]
#[sqlx(transparent)]
pub struct AccountId(i64);
11 changes: 9 additions & 2 deletions backend/src/data_model/device.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use derive_more::{From, Into};
use serde::{Deserialize, Serialize};

use super::account::AccountId;

#[derive(Deserialize, Serialize, Debug, sqlx::Type, PartialEq, Eq, From, Into, Clone, Copy)]
#[sqlx(transparent)]
pub struct DeviceId(i64);

#[derive(Serialize, Deserialize)]
pub struct Device {
pub id: i64,
pub id: DeviceId,
pub effect: f64,
pub account_id: i64,
pub account_id: AccountId,
}
10 changes: 7 additions & 3 deletions backend/src/data_model/event.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use serde::{Deserialize, Serialize};

use super::time::DateTimeUtc;
use super::{device::DeviceId, time::DateTimeUtc};

#[derive(Deserialize, Serialize, Debug, sqlx::Type, PartialEq, Eq)]
#[sqlx(transparent)]
struct EventId(i64);

#[derive(Serialize, Deserialize)]
struct Event {
id: i64,
device_id: i64,
id: EventId,
device_id: DeviceId,
version_nr: i64,
start_time: DateTimeUtc,
}
15 changes: 12 additions & 3 deletions backend/src/data_model/task.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
use serde::{Deserialize, Serialize};

use super::time::{Milliseconds, Timespan};
use super::{
device::DeviceId,
time::{Milliseconds, Timespan},
};

use derive_more::{From, Into};

#[derive(Deserialize, Serialize, Debug, sqlx::Type, PartialEq, Eq, From, Into, Clone, Copy)]
#[sqlx(transparent)]
pub struct TaskId(i64);

#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Task {
pub id: i64,
pub id: TaskId,
pub timespan: Timespan,
pub duration: Milliseconds,
pub device_id: i64,
pub device_id: DeviceId,
}
2 changes: 1 addition & 1 deletion backend/src/data_model/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};

pub type DateTimeUtc = DateTime<Utc>;

#[derive(Serialize, Deserialize, sqlx::Type, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, sqlx::Type, Debug, PartialEq, Eq, Clone, Copy)]
#[sqlx(transparent)]
pub struct Milliseconds(i64);

Expand Down
10 changes: 6 additions & 4 deletions backend/src/extractors/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use serde::{Deserialize, Serialize};
use sqlx::SqlitePool;
use uuid::Uuid;

use crate::data_model::account::AccountId;

#[derive(Deserialize, Serialize, sqlx::Type)]
#[sqlx(transparent)]
pub struct AuthToken(Uuid);
Expand All @@ -23,7 +25,7 @@ impl AuthToken {
}

// Account id
pub struct Authentication(pub i64);
pub struct Authentication(pub AccountId);

#[async_trait]
impl FromRequestParts<SqlitePool> for Authentication {
Expand Down Expand Up @@ -57,10 +59,10 @@ fn get_auth_token(headers: &HeaderMap) -> Option<AuthToken> {
AuthToken::try_parse(string).ok()
}

async fn get_account_id_from_token(token: AuthToken, pool: &SqlitePool) -> Option<i64> {
async fn get_account_id_from_token(token: AuthToken, pool: &SqlitePool) -> Option<AccountId> {
sqlx::query_scalar!(
r#"
SELECT account_id
SELECT account_id as "id: AccountId"
FROM AuthTokens
WHERE id = ?
"#,
Expand All @@ -72,7 +74,7 @@ async fn get_account_id_from_token(token: AuthToken, pool: &SqlitePool) -> Optio
}

pub async fn create_auth_token(
account_id: i64,
account_id: AccountId,
pool: &SqlitePool,
) -> Result<AuthToken, sqlx::Error> {
let auth_token = AuthToken::new();
Expand Down
8 changes: 3 additions & 5 deletions backend/src/handlers/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use axum::{debug_handler, extract::State, http::StatusCode, Json};
use sqlx::SqlitePool;

use crate::{
extractors::auth::create_auth_token,
handlers::util::internal_error,
protocol::accounts::{RegisterOrLoginRequest, RegisterOrLoginResponse},
data_model::account::AccountId, extractors::auth::create_auth_token, handlers::util::internal_error, protocol::accounts::{RegisterOrLoginRequest, RegisterOrLoginResponse}
};

#[debug_handler]
Expand All @@ -31,7 +29,7 @@ pub async fn register_account(
r#"
INSERT INTO Accounts (username, password_hash)
VALUES (?, ?)
RETURNING id
RETURNING id as "id: AccountId"
"#,
register_request.username,
password_hash
Expand All @@ -54,7 +52,7 @@ pub async fn login_to_account(
) -> Result<Json<RegisterOrLoginResponse>, (StatusCode, String)> {
let account = sqlx::query!(
r#"
SELECT id, password_hash
SELECT id as "id: AccountId", password_hash
FROM Accounts
WHERE username = ?
"#,
Expand Down
18 changes: 5 additions & 13 deletions backend/src/handlers/devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use axum::{debug_handler, extract::State, http::StatusCode, Json};
use sqlx::SqlitePool;

use crate::{
data_model::device::Device, extractors::auth::Authentication, handlers::util::internal_error,
data_model::device::{Device, DeviceId}, extractors::auth::Authentication, handlers::util::internal_error,
protocol::devices::CreateDeviceRequest,
};

Expand All @@ -11,7 +11,8 @@ pub async fn get_devices(
State(pool): State<SqlitePool>,
Authentication(account_id): Authentication,
) -> Result<Json<Vec<Device>>, (StatusCode, String)> {
let devices = sqlx::query!(
let devices = sqlx::query_as!(
Device,
r#"
SELECT id, effect, account_id
FROM Devices
Expand All @@ -23,16 +24,7 @@ pub async fn get_devices(
.await
.map_err(internal_error)?;

Ok(Json(
devices
.iter()
.map(|d| Device {
id: d.id,
effect: d.effect,
account_id: d.account_id,
})
.collect(),
))
Ok(Json(devices))
}

#[debug_handler]
Expand All @@ -45,7 +37,7 @@ pub async fn create_device(
r#"
INSERT INTO Devices (effect, account_id)
VALUES (?, ?)
RETURNING id
RETURNING id as "id: DeviceId"
"#,
create_device_request.effect,
account_id
Expand Down
9 changes: 5 additions & 4 deletions backend/src/handlers/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use axum::{debug_handler, extract::State, http::StatusCode, Json};
use sqlx::SqlitePool;

use crate::{
data_model::{task::Task, time::Timespan},
data_model::{device::DeviceId, task::{Task, TaskId}, time::{Milliseconds, Timespan}},
extractors::auth::Authentication,
handlers::util::internal_error,
protocol::tasks::{CreateTaskRequest, DeleteTaskRequest},
Expand All @@ -15,7 +15,7 @@ pub async fn get_tasks(
) -> Result<Json<Vec<Task>>, (StatusCode, String)> {
let tasks = sqlx::query!(
r#"
SELECT Tasks.id, Tasks.timespan_start, Tasks.timespan_end, Tasks.duration, Tasks.device_id
SELECT Tasks.id as "id: TaskId", Tasks.timespan_start, Tasks.timespan_end, Tasks.duration as "duration: Milliseconds", Tasks.device_id as "device_id: DeviceId"
FROM Tasks
JOIN Devices ON Tasks.device_id == Devices.id
WHERE Devices.account_id = ?
Expand All @@ -26,12 +26,13 @@ pub async fn get_tasks(
.await
.map_err(internal_error)?;


let my_tasks = tasks
.iter()
.map(|t| Task {
id: t.id,
timespan: Timespan::new_from_naive(t.timespan_start, t.timespan_end),
duration: t.duration.into(),
duration: t.duration,
device_id: t.device_id,
})
.collect();
Expand All @@ -49,7 +50,7 @@ pub async fn create_task(
r#"
INSERT INTO Tasks (timespan_start, timespan_end, duration, device_id)
VALUES (?, ?, ?, ?)
RETURNING id
RETURNING id as "id: TaskId"
"#,
create_task_request.timespan.start,
create_task_request.timespan.end,
Expand Down
6 changes: 3 additions & 3 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ mod tests {
.header("X-Auth-Token", auth_token.clone())
.body(Body::from(
serde_json::to_vec(&Task {
id: -1,
id: (-1).into(),
timespan: Timespan::new(
Utc::now(),
Utc::now().checked_add_days(Days::new(1)).unwrap(),
Expand Down Expand Up @@ -244,7 +244,7 @@ mod tests {
let body = response.into_body().collect().await.unwrap().to_bytes();
let response: Task = serde_json::from_slice(&body).unwrap();

assert_ne!(response.id, -1);
assert_ne!(response.id, (-1).into());
assert_eq!(response.duration, 3600.into());
}

Expand All @@ -264,7 +264,7 @@ mod tests {
.header("X-Auth-Token", auth_token.clone())
.body(Body::from(
serde_json::to_vec(&Task {
id: -1,
id: (-1).into(),
timespan: Timespan::new(
Utc::now(),
Utc::now().checked_add_days(Days::new(1)).unwrap(),
Expand Down
4 changes: 3 additions & 1 deletion backend/src/protocol/devices.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use serde::{Deserialize, Serialize};

use crate::data_model::device::DeviceId;

#[derive(Deserialize, Serialize)]
pub struct CreateDeviceRequest {
pub effect: f64,
}

#[derive(Deserialize, Serialize)]
pub struct DeleteDeviceRequest {
pub id: i64,
pub id: DeviceId,
}
9 changes: 6 additions & 3 deletions backend/src/protocol/tasks.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use serde::{Deserialize, Serialize};

use crate::data_model::time::{Milliseconds, Timespan};
use crate::data_model::{
device::DeviceId,
time::{Milliseconds, Timespan},
};

#[derive(Deserialize, Serialize)]
pub struct CreateTaskRequest {
pub timespan: Timespan,
pub duration: Milliseconds,
pub device_id: i64,
pub device_id: DeviceId,
}

#[derive(Deserialize, Serialize)]
pub struct DeleteTaskRequest {
pub id: i64,
pub id: DeviceId,
}

0 comments on commit 645284d

Please sign in to comment.