From e2778be3ee9eb1a992b8540eb0c9111d161e4ddd Mon Sep 17 00:00:00 2001 From: Kent Tristan Yves Sarmiento Date: Tue, 2 Jan 2024 17:23:26 +0800 Subject: [PATCH] refactor: setup common types for service (#45) --- .cargo/config.toml | 2 + .github/dependabot.yml | 43 +++-- .github/workflows/development.yml | 16 ++ .github/workflows/lambda.yml | 8 + .github/workflows/shuttle.yml | 7 +- .vscode/settings.json | 2 +- Cargo.lock | 11 ++ link-for-later/Cargo.toml | 1 + link-for-later/src/{dto => }/auth.rs | 0 link-for-later/src/controller/extractors.rs | 2 +- link-for-later/src/controller/routes/links.rs | 8 +- link-for-later/src/controller/routes/users.rs | 8 +- link-for-later/src/dto.rs | 12 -- link-for-later/src/dto/request.rs | 2 - link-for-later/src/dto/request/links.rs | 108 ------------- link-for-later/src/dto/request/users.rs | 55 ------- link-for-later/src/dto/response.rs | 14 -- link-for-later/src/entity.rs | 5 - link-for-later/src/entity/links.rs | 148 ------------------ link-for-later/src/entity/users.rs | 86 ---------- link-for-later/src/lib.rs | 4 +- link-for-later/src/repository.rs | 6 +- link-for-later/src/repository/inmemory.rs | 9 +- link-for-later/src/repository/mongodb.rs | 7 +- link-for-later/src/service.rs | 4 +- link-for-later/src/service/analysis.rs | 5 +- link-for-later/src/service/links.rs | 4 +- link-for-later/src/service/users.rs | 4 +- link-for-later/src/types.rs | 8 + link-for-later/tests/entity/mod.rs | 27 ---- link-for-later/tests/links.rs | 53 ++++--- link-for-later/tests/repository/inmemory.rs | 6 +- link-for-later/tests/repository/mod.rs | 2 +- link-for-later/tests/repository/mongodb.rs | 30 +--- link-for-later/tests/users.rs | 5 +- 35 files changed, 131 insertions(+), 581 deletions(-) create mode 100644 .cargo/config.toml rename link-for-later/src/{dto => }/auth.rs (100%) delete mode 100644 link-for-later/src/dto.rs delete mode 100644 link-for-later/src/dto/request.rs delete mode 100644 link-for-later/src/dto/request/links.rs delete mode 100644 link-for-later/src/dto/request/users.rs delete mode 100644 link-for-later/src/dto/response.rs delete mode 100644 link-for-later/src/entity.rs delete mode 100644 link-for-later/src/entity/links.rs delete mode 100644 link-for-later/src/entity/users.rs delete mode 100644 link-for-later/tests/entity/mod.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..c91c3f3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[net] +git-fetch-with-cli = true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bd8e5ba..22e7cb3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,30 +1,23 @@ version: 2 updates: -- package-ecosystem: "cargo" - directory: "/link-for-later" - schedule: - interval: weekly - time: "00:00" - open-pull-requests-limit: 15 + - package-ecosystem: "cargo" + directory: "/link-for-later" + schedule: + interval: weekly + time: "00:00" + open-pull-requests-limit: 15 -- package-ecosystem: "cargo" - directory: "/link-for-later-axum" - schedule: - interval: weekly - time: "00:00" - open-pull-requests-limit: 15 + - package-ecosystem: "cargo" + directory: "/link-for-later-lambda" + schedule: + interval: weekly + time: "00:00" + open-pull-requests-limit: 15 -- package-ecosystem: "cargo" - directory: "/link-for-later-lambda" - schedule: - interval: weekly - time: "00:00" - open-pull-requests-limit: 15 - -- package-ecosystem: "cargo" - directory: "/link-for-later-shuttle" - schedule: - interval: weekly - time: "00:00" - open-pull-requests-limit: 15 + - package-ecosystem: "cargo" + directory: "/link-for-later-shuttle" + schedule: + interval: weekly + time: "00:00" + open-pull-requests-limit: 15 diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 635b056..ac0f92e 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -22,6 +22,10 @@ jobs: steps: - uses: actions/checkout@v3 + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -43,6 +47,10 @@ jobs: steps: - uses: actions/checkout@v3 + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -68,6 +76,10 @@ jobs: steps: - uses: actions/checkout@v3 + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -100,6 +112,10 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + - name: Install Rust uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/lambda.yml b/.github/workflows/lambda.yml index 22f4bcd..f0e10ed 100644 --- a/.github/workflows/lambda.yml +++ b/.github/workflows/lambda.yml @@ -13,6 +13,10 @@ jobs: steps: - uses: actions/checkout@v3 + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -31,6 +35,10 @@ jobs: steps: - uses: actions/checkout@v3 + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + - name: Install Rust uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/shuttle.yml b/.github/workflows/shuttle.yml index 5f0f2d9..0690e38 100644 --- a/.github/workflows/shuttle.yml +++ b/.github/workflows/shuttle.yml @@ -8,7 +8,12 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: shuttle-hq/deploy-action@main + - uses: de-vri-es/setup-git-credentials@v2 + with: + credentials: "https://${{ github.repository_owner }}:${{ secrets.GIT_CREDENTIALS }}@github.com" + + - name: Deploy using shuttle + uses: shuttle-hq/deploy-action@main with: deploy-key: ${{ secrets.SHUTTLE_API_KEY }} no-test: "true" diff --git a/.vscode/settings.json b/.vscode/settings.json index 5dd7f56..4a24871 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,6 @@ "rust-analyzer.linkedProjects": [ "./link-for-later/Cargo.toml", "./link-for-later-lambda/Cargo.toml", - "./link-for-later-shuttle/Cargo.toml", + "./link-for-later-shuttle/Cargo.toml" ] } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 66576a4..7a67641 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1384,6 +1384,7 @@ dependencies = [ "futures", "http-body-util", "jsonwebtoken", + "link-for-later-types", "mockall", "mockito", "mongodb", @@ -1425,6 +1426,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "link-for-later-types" +version = "0.1.0" +source = "git+https://github.com/kentSarmiento/link-for-later-types?tag=v0.1.0#d0f536b3135865cb78b5678b86884b1733871eb4" +dependencies = [ + "chrono", + "serde", + "validator", +] + [[package]] name = "linked-hash-map" version = "0.5.6" diff --git a/link-for-later/Cargo.toml b/link-for-later/Cargo.toml index 652c717..c8f722c 100644 --- a/link-for-later/Cargo.toml +++ b/link-for-later/Cargo.toml @@ -19,6 +19,7 @@ chrono = { version = "0.4.31", default-features = false, features=["clock", "ser futures = "0.3.29" http-body-util = "0.1.0" jsonwebtoken = "9.2.0" +link-for-later-types = { git = "https://github.com/kentSarmiento/link-for-later-types", tag = "v0.1.0" } mongodb = "2.8.0" reqwest = { version = "0.11.23", default-features = false, features = ["json", "rustls-tls"] } serde = { version = "1.0.193", features = ["derive"] } diff --git a/link-for-later/src/dto/auth.rs b/link-for-later/src/auth.rs similarity index 100% rename from link-for-later/src/dto/auth.rs rename to link-for-later/src/auth.rs diff --git a/link-for-later/src/controller/extractors.rs b/link-for-later/src/controller/extractors.rs index 3f4547d..164c905 100644 --- a/link-for-later/src/controller/extractors.rs +++ b/link-for-later/src/controller/extractors.rs @@ -5,7 +5,7 @@ use axum_extra::{ }; use jsonwebtoken::{decode, DecodingKey, Validation}; -use crate::{dto::Claims, types::AppError}; +use crate::types::{AppError, Claims}; const JWT_SECRET_KEY: &str = "JWT_SECRET"; diff --git a/link-for-later/src/controller/routes/links.rs b/link-for-later/src/controller/routes/links.rs index 866b00d..a9d72d9 100644 --- a/link-for-later/src/controller/routes/links.rs +++ b/link-for-later/src/controller/routes/links.rs @@ -6,10 +6,8 @@ use axum::{ }; use validator::Validate; -use crate::{ - dto::{Claims, LinkItemRequest, LinkQueryBuilder}, - entity::LinkItemBuilder, - types::{AppError, AppState}, +use crate::types::{ + AppError, AppState, Claims, LinkItemBuilder, LinkItemRequest, LinkQueryBuilder, }; pub fn router(state: AppState) -> Router { @@ -149,13 +147,13 @@ mod tests { use serde_json::json; use crate::{ - entity::LinkItem, repository::{MockLinks as MockLinksRepo, MockUsers as MockUsersRepo}, service::DynLinks as DynLinksService, service::{ MockAnalysis as MockAnalysisService, MockLinks as MockLinksService, MockUsers as MockUsersService, }, + types::LinkItem, }; use super::*; diff --git a/link-for-later/src/controller/routes/users.rs b/link-for-later/src/controller/routes/users.rs index 03f1991..3f77e3f 100644 --- a/link-for-later/src/controller/routes/users.rs +++ b/link-for-later/src/controller/routes/users.rs @@ -1,11 +1,7 @@ use axum::{extract::State, http::StatusCode, response::IntoResponse, routing, Json, Router}; use validator::Validate; -use crate::{ - dto::{LoginResponse, UserInfoRequest}, - entity::UserInfoBuilder, - types::{AppError, AppState}, -}; +use crate::types::{AppError, AppState, LoginResponse, UserInfoBuilder, UserInfoRequest}; pub fn router(state: AppState) -> Router { Router::new() @@ -78,13 +74,13 @@ mod tests { use serde_json::json; use crate::{ - dto::Token, repository::{MockLinks as MockLinksRepo, MockUsers as MockUsersRepo}, service::DynUsers as DynUsersService, service::{ MockAnalysis as MockAnalysisService, MockLinks as MockLinksService, MockUsers as MockUsersService, }, + types::Token, }; use super::*; diff --git a/link-for-later/src/dto.rs b/link-for-later/src/dto.rs deleted file mode 100644 index 6beaf49..0000000 --- a/link-for-later/src/dto.rs +++ /dev/null @@ -1,12 +0,0 @@ -pub use auth::{Claims, Token}; -pub use request::links::{ - Item as LinkItemRequest, Query as LinkQuery, QueryBuilder as LinkQueryBuilder, -}; -pub use request::users::{ - Info as UserInfoRequest, Query as UserQuery, QueryBuilder as UserQueryBuilder, -}; -pub use response::Login as LoginResponse; - -mod auth; -mod request; -mod response; diff --git a/link-for-later/src/dto/request.rs b/link-for-later/src/dto/request.rs deleted file mode 100644 index 0f971ee..0000000 --- a/link-for-later/src/dto/request.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod links; -pub mod users; diff --git a/link-for-later/src/dto/request/links.rs b/link-for-later/src/dto/request/links.rs deleted file mode 100644 index 3387774..0000000 --- a/link-for-later/src/dto/request/links.rs +++ /dev/null @@ -1,108 +0,0 @@ -use serde::{Deserialize, Serialize}; -use validator::Validate; - -#[derive(Default, Serialize, Deserialize, Validate)] -pub struct Item { - #[validate(url)] - url: String, - #[serde(default)] - title: String, - #[serde(default)] - description: String, - #[serde(default)] - word_count: usize, - #[serde(default)] - reading_time: usize, - #[serde(default)] - summary: String, - #[serde(default)] - label: String, -} - -impl Item { - pub fn url(&self) -> &str { - &self.url - } - - pub fn title(&self) -> &str { - &self.title - } - - pub fn description(&self) -> &str { - &self.description - } - - pub const fn word_count(&self) -> usize { - self.word_count - } - - pub const fn reading_time(&self) -> usize { - self.reading_time - } - - pub fn summary(&self) -> &str { - &self.summary - } - - pub fn label(&self) -> &str { - &self.label - } - - #[cfg(test)] - pub fn new(url: &str) -> Self { - Self { - url: url.to_owned(), - ..Default::default() - } - } -} - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct Query { - #[serde(skip_serializing_if = "String::is_empty")] - id: String, - #[serde(skip_serializing_if = "String::is_empty")] - owner: String, -} - -impl Query { - pub fn id(&self) -> &str { - &self.id - } - - pub fn owner(&self) -> &str { - &self.owner - } -} - -#[derive(Default)] -pub struct QueryBuilder { - id: String, - owner: String, -} - -impl QueryBuilder { - pub fn new(id: &str, owner: &str) -> Self { - Self { - id: id.to_owned(), - owner: owner.to_owned(), - } - } - - pub fn id(mut self, id: &str) -> Self { - self.id = id.to_owned(); - self - } - - pub fn owner(mut self, owner: &str) -> Self { - self.owner = owner.to_owned(); - self - } - - pub fn build(self) -> Query { - Query { - id: self.id, - owner: self.owner, - } - } -} diff --git a/link-for-later/src/dto/request/users.rs b/link-for-later/src/dto/request/users.rs deleted file mode 100644 index 1eb7cfd..0000000 --- a/link-for-later/src/dto/request/users.rs +++ /dev/null @@ -1,55 +0,0 @@ -use serde::{Deserialize, Serialize}; -use validator::Validate; - -#[derive(Serialize, Deserialize, Validate)] -pub struct Info { - #[validate(email)] - email: String, - password: String, -} - -impl Info { - pub fn email(&self) -> &str { - &self.email - } - - pub fn password(&self) -> &str { - &self.password - } - - #[cfg(test)] - pub fn new(email: &str, password: &str) -> Self { - Self { - email: email.to_owned(), - password: password.to_owned(), - } - } -} - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct Query { - email: String, -} - -impl Query { - pub fn email(&self) -> &str { - &self.email - } -} - -#[derive(Default)] -pub struct QueryBuilder { - email: String, -} - -impl QueryBuilder { - pub fn new(email: &str) -> Self { - Self { - email: email.to_owned(), - } - } - - pub fn build(self) -> Query { - Query { email: self.email } - } -} diff --git a/link-for-later/src/dto/response.rs b/link-for-later/src/dto/response.rs deleted file mode 100644 index c1e7c4f..0000000 --- a/link-for-later/src/dto/response.rs +++ /dev/null @@ -1,14 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct Login { - token: String, -} - -impl Login { - pub fn new(token: &str) -> Self { - Self { - token: token.to_owned(), - } - } -} diff --git a/link-for-later/src/entity.rs b/link-for-later/src/entity.rs deleted file mode 100644 index 6697dda..0000000 --- a/link-for-later/src/entity.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub use links::{Item as LinkItem, ItemBuilder as LinkItemBuilder}; -pub use users::{Info as UserInfo, InfoBuilder as UserInfoBuilder}; - -mod links; -mod users; diff --git a/link-for-later/src/entity/links.rs b/link-for-later/src/entity/links.rs deleted file mode 100644 index fedf944..0000000 --- a/link-for-later/src/entity/links.rs +++ /dev/null @@ -1,148 +0,0 @@ -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct Item { - id: String, - owner: String, - url: String, - title: String, - description: String, - word_count: usize, - reading_time: usize, - summary: String, - label: String, - created_at: DateTime, - updated_at: DateTime, -} - -impl Item { - pub fn id(&self) -> &str { - &self.id - } - - pub fn owner(&self) -> &str { - &self.owner - } - - pub fn url(&self) -> &str { - &self.url - } - - pub const fn created_at(&self) -> &DateTime { - &self.created_at - } -} - -#[derive(Default)] -pub struct ItemBuilder { - id: String, - owner: String, - url: String, - title: String, - description: String, - word_count: usize, - reading_time: usize, - summary: String, - label: String, - created_at: DateTime, - updated_at: DateTime, -} - -impl ItemBuilder { - pub fn new(url: &str) -> Self { - Self { - url: url.to_owned(), - ..Default::default() - } - } - - pub fn id(mut self, id: &str) -> Self { - self.id = id.to_owned(); - self - } - - pub fn owner(mut self, owner: &str) -> Self { - self.owner = owner.to_owned(); - self - } - - pub fn url(mut self, url: &str) -> Self { - self.url = url.to_owned(); - self - } - - pub fn title(mut self, title: &str) -> Self { - self.title = title.to_owned(); - self - } - - pub fn description(mut self, description: &str) -> Self { - self.description = description.to_owned(); - self - } - - pub const fn word_count(mut self, word_count: usize) -> Self { - self.word_count = word_count; - self - } - - pub const fn reading_time(mut self, reading_time: usize) -> Self { - self.reading_time = reading_time; - self - } - - pub fn summary(mut self, summary: &str) -> Self { - self.summary = summary.to_owned(); - self - } - - pub fn label(mut self, label: &str) -> Self { - self.label = label.to_owned(); - self - } - - pub fn created_at(mut self, created_at: &DateTime) -> Self { - self.created_at = created_at.to_owned(); - self - } - - pub fn updated_at(mut self, updated_at: &DateTime) -> Self { - self.updated_at = updated_at.to_owned(); - self - } - - pub fn build(self) -> Item { - Item { - id: self.id, - owner: self.owner, - url: self.url, - title: self.title, - description: self.description, - word_count: self.word_count, - reading_time: self.reading_time, - summary: self.summary, - label: self.label, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -impl From for ItemBuilder { - fn from(item: Item) -> Self { - Self { - id: item.id, - owner: item.owner, - url: item.url, - title: item.title, - description: item.description, - word_count: item.word_count, - reading_time: item.reading_time, - summary: item.summary, - label: item.label, - created_at: item.created_at, - updated_at: item.updated_at, - } - } -} diff --git a/link-for-later/src/entity/users.rs b/link-for-later/src/entity/users.rs deleted file mode 100644 index dbff955..0000000 --- a/link-for-later/src/entity/users.rs +++ /dev/null @@ -1,86 +0,0 @@ -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct Info { - id: String, - email: String, - password: String, - verified: bool, - created_at: DateTime, - updated_at: DateTime, -} - -impl Info { - pub fn email(&self) -> &str { - &self.email - } - - pub fn password(&self) -> &str { - &self.password - } -} - -#[derive(Default)] -pub struct InfoBuilder { - id: String, - email: String, - password: String, - verified: bool, - created_at: DateTime, - updated_at: DateTime, -} - -impl InfoBuilder { - pub fn new(email: &str, password: &str) -> Self { - Self { - email: email.to_owned(), - password: password.to_owned(), - ..Default::default() - } - } - - pub fn id(mut self, id: &str) -> Self { - self.id = id.to_owned(); - self - } - - pub const fn verified(mut self, verified: bool) -> Self { - self.verified = verified; - self - } - - pub fn created_at(mut self, created_at: &DateTime) -> Self { - self.created_at = created_at.to_owned(); - self - } - - pub fn updated_at(mut self, updated_at: &DateTime) -> Self { - self.updated_at = updated_at.to_owned(); - self - } - - pub fn build(self) -> Info { - Info { - id: self.id, - email: self.email, - password: self.password, - verified: self.verified, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -impl From for InfoBuilder { - fn from(info: Info) -> Self { - Self { - id: info.id, - email: info.email, - password: info.password, - verified: info.verified, - created_at: info.created_at, - updated_at: info.updated_at, - } - } -} diff --git a/link-for-later/src/lib.rs b/link-for-later/src/lib.rs index 6da5a15..b31147a 100644 --- a/link-for-later/src/lib.rs +++ b/link-for-later/src/lib.rs @@ -2,7 +2,6 @@ clippy::all, clippy::pedantic, clippy::nursery, - clippy::cargo, clippy::style, clippy::suspicious, @@ -33,9 +32,8 @@ pub use types::Database as DatabaseType; pub mod app; +mod auth; mod controller; -mod dto; -mod entity; mod repository; mod service; mod types; diff --git a/link-for-later/src/repository.rs b/link-for-later/src/repository.rs index df2010c..1238a3a 100644 --- a/link-for-later/src/repository.rs +++ b/link-for-later/src/repository.rs @@ -4,11 +4,7 @@ use axum::async_trait; #[cfg(test)] use mockall::{automock, predicate::*}; -use crate::{ - dto::{LinkQuery, UserQuery}, - entity::{LinkItem, UserInfo}, - types::Result, -}; +use crate::types::{LinkItem, LinkQuery, Result, UserInfo, UserQuery}; pub type DynLinks = Arc; pub type DynUsers = Arc; diff --git a/link-for-later/src/repository/inmemory.rs b/link-for-later/src/repository/inmemory.rs index 1d9fc0c..11c48d0 100644 --- a/link-for-later/src/repository/inmemory.rs +++ b/link-for-later/src/repository/inmemory.rs @@ -2,10 +2,9 @@ use std::sync::Mutex; use axum::async_trait; -use crate::{ - dto::{LinkQuery, LinkQueryBuilder, UserQuery}, - entity::{LinkItem, LinkItemBuilder, UserInfo, UserInfoBuilder}, - types::{AppError, Result}, +use crate::types::{ + AppError, LinkItem, LinkItemBuilder, LinkQuery, LinkQueryBuilder, Result, UserInfo, + UserInfoBuilder, UserQuery, }; use super::{Links as LinksRepository, Users as UsersRepository}; @@ -150,7 +149,7 @@ impl UsersRepository for UsersRepositoryProvider { #[cfg(test)] mod tests { - use crate::dto::UserQueryBuilder; + use crate::types::UserQueryBuilder; use super::*; diff --git a/link-for-later/src/repository/mongodb.rs b/link-for-later/src/repository/mongodb.rs index a2c9816..0323db5 100644 --- a/link-for-later/src/repository/mongodb.rs +++ b/link-for-later/src/repository/mongodb.rs @@ -3,10 +3,9 @@ use bson::{doc, to_document}; use futures::TryStreamExt; use mongodb::{options::ReplaceOptions, Collection, Database}; -use crate::{ - dto::{LinkQuery, LinkQueryBuilder, UserQuery}, - entity::{LinkItem, LinkItemBuilder, UserInfo, UserInfoBuilder}, - types::{AppError, Result}, +use crate::types::{ + AppError, LinkItem, LinkItemBuilder, LinkQuery, LinkQueryBuilder, Result, UserInfo, + UserInfoBuilder, UserQuery, }; use super::{Links as LinksRepository, Users as UsersRepository}; diff --git a/link-for-later/src/service.rs b/link-for-later/src/service.rs index ba1aab3..abd4ade 100644 --- a/link-for-later/src/service.rs +++ b/link-for-later/src/service.rs @@ -5,10 +5,8 @@ use axum::async_trait; use mockall::{automock, predicate::*}; use crate::{ - dto::{LinkQuery, Token}, - entity::{LinkItem, UserInfo}, repository, service, - types::Result, + types::{LinkItem, LinkQuery, Result, Token, UserInfo}, }; pub type DynLinks = Arc; diff --git a/link-for-later/src/service/analysis.rs b/link-for-later/src/service/analysis.rs index 9ca5208..729b780 100644 --- a/link-for-later/src/service/analysis.rs +++ b/link-for-later/src/service/analysis.rs @@ -1,9 +1,8 @@ use axum::async_trait; use crate::{ - entity::LinkItem, service::Analysis as AnalysisService, - types::{AppError, Result}, + types::{AppError, LinkItem, Result}, }; const ANALYSIS_SERVICE_URL: &str = "ANALYSIS_SERVICE_URL"; @@ -43,7 +42,7 @@ impl Default for ServiceProvider { #[cfg(test)] mod tests { - use crate::entity::LinkItemBuilder; + use crate::types::LinkItemBuilder; use super::*; diff --git a/link-for-later/src/service/links.rs b/link-for-later/src/service/links.rs index 2981a15..2c008f6 100644 --- a/link-for-later/src/service/links.rs +++ b/link-for-later/src/service/links.rs @@ -2,11 +2,9 @@ use axum::async_trait; use chrono::Utc; use crate::{ - dto::{LinkQuery, LinkQueryBuilder}, - entity::{LinkItem, LinkItemBuilder}, repository, service, service::Links as LinksService, - types::{AppError, Result}, + types::{AppError, LinkItem, LinkItemBuilder, LinkQuery, LinkQueryBuilder, Result}, }; #[derive(Default)] diff --git a/link-for-later/src/service/users.rs b/link-for-later/src/service/users.rs index 16754b3..2b1fd07 100644 --- a/link-for-later/src/service/users.rs +++ b/link-for-later/src/service/users.rs @@ -8,11 +8,9 @@ use jsonwebtoken::{encode, EncodingKey, Header}; use std::convert::TryInto; use crate::{ - dto::{Claims, Token, UserQueryBuilder}, - entity::{UserInfo, UserInfoBuilder}, repository, service::Users as UsersService, - types::{AppError, Result}, + types::{AppError, Claims, Result, Token, UserInfo, UserInfoBuilder, UserQueryBuilder}, }; const JWT_SECRET_KEY: &str = "JWT_SECRET"; diff --git a/link-for-later/src/types.rs b/link-for-later/src/types.rs index 7ad21e2..fb01bb8 100644 --- a/link-for-later/src/types.rs +++ b/link-for-later/src/types.rs @@ -1,5 +1,13 @@ pub type Result = std::result::Result; +pub use link_for_later_types::dto::{ + LinkItemRequest, LinkQuery, LinkQueryBuilder, LoginResponse, UserInfoRequest, UserQuery, + UserQueryBuilder, +}; +pub use link_for_later_types::entity::{LinkItem, LinkItemBuilder, UserInfo, UserInfoBuilder}; + +pub use crate::auth::{Claims, Token}; + pub type AppState = crate::app::State; pub type AppError = crate::app::Error; diff --git a/link-for-later/tests/entity/mod.rs b/link-for-later/tests/entity/mod.rs deleted file mode 100644 index 85e0abf..0000000 --- a/link-for-later/tests/entity/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct LinkItem { - pub id: String, - pub owner: String, - pub url: String, - pub title: String, - pub description: String, - pub word_count: usize, - pub reading_time: usize, - pub summary: String, - pub label: String, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct UserInfo { - pub id: String, - pub email: String, - pub password: String, - pub verified: bool, - pub created_at: DateTime, - pub updated_at: DateTime, -} diff --git a/link-for-later/tests/links.rs b/link-for-later/tests/links.rs index 7e02cd9..1755ad3 100644 --- a/link-for-later/tests/links.rs +++ b/link-for-later/tests/links.rs @@ -9,11 +9,12 @@ use rstest::rstest; use serde_json::json; use tower::ServiceExt; -use crate::{entity::LinkItem, repository::DatabaseType}; +use link_for_later_types::entity::LinkItem; + +use crate::repository::DatabaseType; mod app; mod auth; -mod entity; mod repository; #[rstest] @@ -69,11 +70,11 @@ async fn test_get_links_non_empty(#[values(DatabaseType::MongoDb)] db_type: Data let body = response.into_body().collect().await.unwrap().to_bytes(); let body = std::str::from_utf8(&body).unwrap(); - let body: Vec = serde_json::from_str(body).unwrap(); + let body: Vec = serde_json::from_str(body).unwrap(); assert!(body.len() == 1); - assert!(body[0].id == id); - assert!(body[0].owner == "user@test.com"); - assert!(body[0].url == "http://test"); + assert!(body[0].id() == id); + assert!(body[0].owner() == "user@test.com"); + assert!(body[0].url() == "http://test"); } #[rstest] @@ -102,9 +103,9 @@ async fn test_get_link_item_found(#[values(DatabaseType::MongoDb)] db_type: Data let body = response.into_body().collect().await.unwrap().to_bytes(); let body = std::str::from_utf8(&body).unwrap(); let body: LinkItem = serde_json::from_str(body).unwrap(); - assert!(body.id == id); - assert!(body.owner == "user@test.com"); - assert!(body.url == "http://test"); + assert!(body.id() == id); + assert!(body.owner() == "user@test.com"); + assert!(body.url() == "http://test"); } #[rstest] @@ -165,15 +166,15 @@ async fn test_post_link(#[values(DatabaseType::MongoDb)] db_type: DatabaseType) let body = std::str::from_utf8(&body).unwrap(); let body: LinkItem = serde_json::from_str(body).unwrap(); - assert!(body.owner == "user@test.com"); - assert!(body.url == "http://test"); + assert!(body.owner() == "user@test.com"); + assert!(body.url() == "http://test"); let db_count = repository.count_links().await; assert!(db_count == 1); - let db_item = repository.get_link(&body.id).await; - assert!(db_item.owner == "user@test.com"); - assert!(db_item.url == "http://test"); + let db_item = repository.get_link(body.id()).await; + assert!(db_item.owner() == "user@test.com"); + assert!(db_item.url() == "http://test"); } #[rstest] @@ -241,17 +242,17 @@ async fn test_put_link(#[values(DatabaseType::MongoDb)] db_type: DatabaseType) { let body = std::str::from_utf8(&body).unwrap(); let body: LinkItem = serde_json::from_str(body).unwrap(); - assert!(body.id == id); - assert!(body.owner == "user@test.com"); - assert!(body.url == "http://update"); + assert!(body.id() == id); + assert!(body.owner() == "user@test.com"); + assert!(body.url() == "http://update"); let db_count = repository.count_links().await; assert!(db_count == 1); let db_item = repository.get_link(&id).await; - assert!(db_item.id == id); - assert!(db_item.owner == "user@test.com"); - assert!(db_item.url == "http://update"); + assert!(db_item.id() == id); + assert!(db_item.owner() == "user@test.com"); + assert!(db_item.url() == "http://update"); } #[rstest] @@ -324,9 +325,9 @@ async fn test_put_link_item_not_found(#[values(DatabaseType::MongoDb)] db_type: assert!(db_count == 1); let db_item = repository.get_link(&id).await; - assert!(db_item.id == id); - assert!(db_item.owner == "user@test.com"); - assert!(db_item.url == "http://test"); // not updated + assert!(db_item.id() == id); + assert!(db_item.owner() == "user@test.com"); + assert!(db_item.url() == "http://test"); // not updated } #[rstest] @@ -392,9 +393,9 @@ async fn test_delete_link_item_not_found(#[values(DatabaseType::MongoDb)] db_typ assert!(db_count == 1); let db_item = repository.get_link(&id).await; - assert!(db_item.id == id); - assert!(db_item.owner == "user@test.com"); - assert!(db_item.url == "http://test"); // not updated + assert!(db_item.id() == id); + assert!(db_item.owner() == "user@test.com"); + assert!(db_item.url() == "http://test"); // not updated } #[rstest] diff --git a/link-for-later/tests/repository/inmemory.rs b/link-for-later/tests/repository/inmemory.rs index 568303c..8dcd2c8 100644 --- a/link-for-later/tests/repository/inmemory.rs +++ b/link-for-later/tests/repository/inmemory.rs @@ -1,12 +1,14 @@ use axum::async_trait; -use crate::entity::{LinkItem, UserInfo}; +use link_for_later_types::entity::{LinkItem, UserInfo}; + +use super::Repository; #[derive(Default)] pub struct RepositoryProvider {} #[async_trait] -impl super::Repository for RepositoryProvider { +impl Repository for RepositoryProvider { async fn count_links(&self) -> u64 { unimplemented!() } diff --git a/link-for-later/tests/repository/mod.rs b/link-for-later/tests/repository/mod.rs index 4bd20ba..002d222 100644 --- a/link-for-later/tests/repository/mod.rs +++ b/link-for-later/tests/repository/mod.rs @@ -1,6 +1,6 @@ use axum::async_trait; -use crate::entity::{LinkItem, UserInfo}; +use link_for_later_types::entity::{LinkItem, UserInfo}; pub mod inmemory; pub mod mongodb; diff --git a/link-for-later/tests/repository/mongodb.rs b/link-for-later/tests/repository/mongodb.rs index ccb8c0f..7486333 100644 --- a/link-for-later/tests/repository/mongodb.rs +++ b/link-for-later/tests/repository/mongodb.rs @@ -2,11 +2,12 @@ use std::str::FromStr; use axum::async_trait; use bson::doc; -use chrono::Utc; use mongodb::{options::ClientOptions, Client, Database}; use rand::Rng; -use crate::entity::{LinkItem, UserInfo}; +use link_for_later_types::entity::{LinkItem, LinkItemBuilder, UserInfo, UserInfoBuilder}; + +use super::Repository; const MONGODB_URI_KEY: &str = "MONGODB_URI"; const MONGODB_DATABASE_NAME_KEY: &str = "MONGODB_DATABASE_NAME"; @@ -18,7 +19,7 @@ const USERS_COLLECTION_NAME_KEY: &str = "USERS_COLLECTION_NAME"; pub struct RepositoryProvider {} #[async_trait] -impl super::Repository for RepositoryProvider { +impl Repository for RepositoryProvider { async fn count_links(&self) -> u64 { database() .await @@ -44,19 +45,7 @@ impl super::Repository for RepositoryProvider { .await .collection(&std::env::var(LINKS_COLLECTION_NAME_KEY).unwrap()); - let item = LinkItem { - id: "1".to_owned(), - owner: owner.to_owned(), - url: url.to_owned(), - title: "".to_owned(), - description: "".to_owned(), - word_count: 0, - reading_time: 0, - summary: "".to_owned(), - label: "".to_owned(), - created_at: Utc::now(), - updated_at: Utc::now(), - }; + let item = LinkItemBuilder::new(url).id("1").owner(owner).build(); let result = collection.insert_one(item, None).await.unwrap(); let id = result.inserted_id.as_object_id().unwrap().to_hex(); @@ -92,14 +81,7 @@ impl super::Repository for RepositoryProvider { .await .collection(&std::env::var(USERS_COLLECTION_NAME_KEY).unwrap()); - let info = UserInfo { - id: "1".to_owned(), - email: email.to_owned(), - password: password.to_owned(), - verified: true, - created_at: Utc::now(), - updated_at: Utc::now(), - }; + let info = UserInfoBuilder::new(email, password).id("1").build(); let result = collection.insert_one(info, None).await.unwrap(); let id = result.inserted_id.as_object_id().unwrap().to_hex(); diff --git a/link-for-later/tests/users.rs b/link-for-later/tests/users.rs index bd2120e..323c8ff 100644 --- a/link-for-later/tests/users.rs +++ b/link-for-later/tests/users.rs @@ -17,7 +17,6 @@ use crate::repository::DatabaseType; mod app; mod auth; -mod entity; mod repository; #[rstest] @@ -52,8 +51,8 @@ async fn test_register_user(#[values(DatabaseType::MongoDb)] db_type: DatabaseTy assert!(db_count == 1); let db_item = repository.get_user("user@test.com").await; - assert!(db_item.email == "user@test.com"); - assert!(db_item.password != "test"); // verify password is not saved in plaintext + assert!(db_item.email() == "user@test.com"); + assert!(db_item.password() != "test"); // verify password is not saved in plaintext } #[rstest]