actix test

This commit is contained in:
Nicolai Van der Storm 2025-02-21 09:10:11 +01:00
parent 598125abae
commit fbf2dd89dc
25 changed files with 765 additions and 1290 deletions

929
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,15 +4,8 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.95"
async-trait = "0.1.86"
axum = { version = "0.8.1", features = ["json"] }
diesel = { version = "2.2.7", features = ["postgres", "r2d2", "serde_json"] }
dotenvy = "0.15.7"
r2d2 = "0.8.10"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.138"
tokio = { version = "1.43.0", features = ["full"] }
tower = "0.5.2"
utoipa = { version = "5.3.1", features = ["axum_extras"] }
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
actix-web = "4.9.0"
diesel = { version = "2.2.7", features = ["postgres", "r2d2"] }
dotenv = "0.15.0"
serde = { version = "1.0.218", features = ["derive"] }
serde_json = "1.0.139"

516
log
View File

@ -1,516 +0,0 @@
Compiling openlayerhub v0.1.0 (/home/nicolaivds/GIT/OpenLayerHub)
error[E0277]: the trait bound `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>` is not satisfied
--> src/base/service.rs:60:25
|
60 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `AsQuery` is not implemented for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>`, which is required by `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: required for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>` to implement `LoadQuery<'_, _, _>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
|
54 | i32: diesel::deserialize::FromSql<diesel::sql_types::Integer, Conn::Backend>, InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: AsQuery
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0277]: the trait bound `Conn: LoadConnection` is not satisfied
--> src/base/service.rs:60:25
|
60 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `LoadConnection` is not implemented for `Conn`, which is required by `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: required for `PooledConnection<ConnectionManager<Conn>>` to implement `LoadConnection`
= note: required for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
help: consider further restricting this bound
|
50 | Conn: diesel::Connection + R2D2Connection + 'static + diesel::connection::LoadConnection,
| ++++++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `<T as HasTable>::Table: SingleValue` is not satisfied
--> src/base/service.rs:60:25
|
60 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `SingleValue` is not implemented for `<T as HasTable>::Table`, which is required by `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: required for `<T as HasTable>::Table` to implement `SqlTypeOrSelectable`
= note: required for `T` to implement `FromSqlRow<<T as HasTable>::Table, <Conn as Connection>::Backend>`
= note: required for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
error[E0275]: overflow evaluating the requirement `_: Sized`
--> src/base/service.rs:67:14
|
67 | .filter(T::primary_key().eq(id))
| ^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`openlayerhub`)
= note: required for `<<T as HasTable>::Table as AsQuery>::Query` to implement `FilterDsl<_>`
error[E0277]: `<<T as HasTable>::Table as AsQuery>::Query` is no valid SQL fragment for the `_` backend
--> src/base/service.rs:77:24
|
77 | .load::<T>(&mut conn)
| ---- ^^^^^^^^^ the trait `QueryFragment<_>` is not implemented for `<<T as HasTable>::Table as AsQuery>::Query`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
| |
| required by a bound introduced by this call
|
= note: this usually means that the `_` database system does not support
this SQL syntax
= help: the following other types implement trait `QueryFragment<DB, SP>`:
`&T` implements `QueryFragment<DB>`
`()` implements `QueryFragment<DB>`
`(T0, T1)` implements `QueryFragment<__DB>`
`(T0, T1, T2)` implements `QueryFragment<__DB>`
`(T0, T1, T2, T3)` implements `QueryFragment<__DB>`
`(T0, T1, T2, T3, T4)` implements `QueryFragment<__DB>`
`(T0, T1, T2, T3, T4, T5)` implements `QueryFragment<__DB>`
`(T0, T1, T2, T3, T4, T5, T6)` implements `QueryFragment<__DB>`
and 278 others
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ---- required by a bound in this associated function
1541 | where
1542 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
error[E0277]: the trait bound `<<T as HasTable>::Table as AsQuery>::Query: QueryId` is not satisfied
--> src/base/service.rs:77:24
|
77 | .load::<T>(&mut conn)
| ---- ^^^^^^^^^ the trait `QueryId` is not implemented for `<<T as HasTable>::Table as AsQuery>::Query`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
| |
| required by a bound introduced by this call
|
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ---- required by a bound in this associated function
1541 | where
1542 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
error[E0277]: the trait bound `<<T as HasTable>::Table as AsQuery>::SqlType: SingleValue` is not satisfied
--> src/base/service.rs:77:24
|
77 | .load::<T>(&mut conn)
| ---- ^^^^^^^^^ the trait `SingleValue` is not implemented for `<<T as HasTable>::Table as AsQuery>::SqlType`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
| |
| required by a bound introduced by this call
|
= note: required for `<<T as HasTable>::Table as AsQuery>::SqlType` to implement `load_dsl::private::CompatibleType<T, _>`
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ---- required by a bound in this associated function
1541 | where
1542 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
error[E0277]: the trait bound `T: diesel::Queryable<<<T as HasTable>::Table as AsQuery>::SqlType, _>` is not satisfied
--> src/base/service.rs:77:24
|
77 | .load::<T>(&mut conn)
| ---- ^^^^^^^^^ the trait `diesel::Queryable<<<T as HasTable>::Table as AsQuery>::SqlType, _>` is not implemented for `T`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `diesel::Queryable<ST, DB>`:
`(T0, T1)` implements `diesel::Queryable<(ST0, ST1), __DB>`
`(T0, T1)` implements `diesel::Queryable<Record<(ST0, ST1)>, Pg>`
`(T0, T1, T2)` implements `diesel::Queryable<(ST0, ST1, ST2), __DB>`
`(T0, T1, T2)` implements `diesel::Queryable<Record<(ST0, ST1, ST2)>, Pg>`
`(T0, T1, T2, T3)` implements `diesel::Queryable<(ST0, ST1, ST2, ST3), __DB>`
`(T0, T1, T2, T3)` implements `diesel::Queryable<Record<(ST0, ST1, ST2, ST3)>, Pg>`
`(T0, T1, T2, T3, T4)` implements `diesel::Queryable<(ST0, ST1, ST2, ST3, ST4), __DB>`
`(T0, T1, T2, T3, T4)` implements `diesel::Queryable<Record<(ST0, ST1, ST2, ST3, ST4)>, Pg>`
and 116 others
= note: required for `T` to implement `FromSqlRow<<<T as HasTable>::Table as AsQuery>::SqlType, _>`
= note: required for `<<T as HasTable>::Table as AsQuery>::SqlType` to implement `load_dsl::private::CompatibleType<T, _>`
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ---- required by a bound in this associated function
1541 | where
1542 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
error[E0277]: the trait bound `Conn: LoadConnection` is not satisfied
--> src/base/service.rs:77:24
|
77 | .load::<T>(&mut conn)
| ---- ^^^^^^^^^ the trait `LoadConnection` is not implemented for `Conn`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
| |
| required by a bound introduced by this call
|
= note: required for `PooledConnection<ConnectionManager<Conn>>` to implement `LoadConnection`
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ---- required by a bound in this associated function
1541 | where
1542 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
help: consider further restricting this bound
|
50 | Conn: diesel::Connection + R2D2Connection + 'static + diesel::connection::LoadConnection,
| ++++++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `<Conn as Connection>::Backend: QueryMetadata<<<T as HasTable>::Table as AsQuery>::SqlType>` is not satisfied
--> src/base/service.rs:77:24
|
77 | .load::<T>(&mut conn)
| ---- ^^^^^^^^^ the trait `HasSqlType<<<T as HasTable>::Table as AsQuery>::SqlType>` is not implemented for `<Conn as Connection>::Backend`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
| |
| required by a bound introduced by this call
|
= note: required for `<Conn as Connection>::Backend` to implement `QueryMetadata<<<T as HasTable>::Table as AsQuery>::SqlType>`
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
note: required by a bound in `diesel::RunQueryDsl::load`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ---- required by a bound in this associated function
1541 | where
1542 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
error[E0277]: the trait bound `<T as HasTable>::Table: IntoUpdateTarget` is not satisfied
--> src/base/service.rs:83:24
|
83 | diesel::update(<T as HasTable>::table())
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
| |
| required by a bound introduced by this call
|
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
note: required by a bound in `update`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/functions.rs:80:18
|
80 | pub fn update<T: IntoUpdateTarget>(source: T) -> UpdateStatement<T::Table, T::WhereClause> {
| ^^^^^^^^^^^^^^^^ required by this bound in `update`
error[E0277]: the trait bound `<T as HasTable>::Table: HasTable` is not satisfied
--> src/base/service.rs:83:9
|
83 | diesel::update(<T as HasTable>::table())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasTable` is not implemented for `<T as HasTable>::Table`
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
--> src/base/service.rs:84:14
|
84 | .filter(T::primary_key().eq(id))
| ^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `UpdateStatement<_, _>: FilterDsl<_>`
|
= help: the following other types implement trait `AppearsOnTable<QS>`:
`&'a T` implements `AppearsOnTable<QS>`
`(T0, T1)` implements `AppearsOnTable<QS>`
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
and 131 others
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
= note: 1 redundant requirement hidden
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
= note: required for `UpdateStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
--> src/base/service.rs:84:21
|
84 | .filter(T::primary_key().eq(id))
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `UpdateStatement<_, _>: FilterDsl<_>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `AppearsOnTable<QS>`:
`&'a T` implements `AppearsOnTable<QS>`
`(T0, T1)` implements `AppearsOnTable<QS>`
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
and 131 others
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
= note: 1 redundant requirement hidden
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
= note: required for `UpdateStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
note: required by a bound in `UpdateStatement::<T, U, V, Ret>::filter`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/update_statement/mod.rs:98:15
|
96 | pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
| ------ required by a bound in this associated function
97 | where
98 | Self: FilterDsl<Predicate>,
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `UpdateStatement::<T, U, V, Ret>::filter`
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0277]: the trait bound `&T: diesel::AsChangeset` is not satisfied
--> src/base/service.rs:85:18
|
85 | .set(&entity)
| --- ^^^^^^^ the trait `diesel::AsChangeset` is not implemented for `&T`
| |
| required by a bound introduced by this call
|
note: required by a bound in `UpdateStatement::<T, U>::set`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/update_statement/mod.rs:38:12
|
35 | pub fn set<V>(self, values: V) -> UpdateStatement<T, U, V::Changeset>
| --- required by a bound in this associated function
...
38 | V: changeset::AsChangeset<Target = T>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UpdateStatement::<T, U>::set`
help: consider removing the leading `&`-reference
|
85 - .set(&entity)
85 + .set(entity)
|
error[E0277]: the trait bound `<Conn as Connection>::Backend: DieselReserveSpecialization` is not satisfied
--> src/base/service.rs:86:25
|
86 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `DieselReserveSpecialization` is not implemented for `<Conn as Connection>::Backend`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: required for `UpdateStatement<_, _, _, ReturningClause<_>>` to implement `QueryFragment<<Conn as Connection>::Backend>`
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
error[E0277]: `ReturningClause<_>` is no valid SQL fragment for the `<Conn as Connection>::Backend` backend
--> src/base/service.rs:86:25
|
86 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `QueryFragment<<Conn as Connection>::Backend, <<Conn as Connection>::Backend as SqlDialect>::ReturningClause>` is not implemented for `ReturningClause<_>`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: this usually means that the `<Conn as Connection>::Backend` database system does not support
this SQL syntax
= help: the following other types implement trait `QueryFragment<DB, SP>`:
`ReturningClause<Expr>` implements `QueryFragment<DB, PgLikeReturningClause>`
`ReturningClause<Expr>` implements `QueryFragment<DB>`
= note: required for `ReturningClause<_>` to implement `QueryFragment<<Conn as Connection>::Backend>`
= note: 1 redundant requirement hidden
= note: required for `UpdateStatement<_, _, _, ReturningClause<_>>` to implement `QueryFragment<<Conn as Connection>::Backend>`
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
error[E0277]: the trait bound `Conn: LoadConnection` is not satisfied
--> src/base/service.rs:86:25
|
86 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `LoadConnection` is not implemented for `Conn`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: required for `PooledConnection<ConnectionManager<Conn>>` to implement `LoadConnection`
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
help: consider further restricting this bound
|
50 | Conn: diesel::Connection + R2D2Connection + 'static + diesel::connection::LoadConnection,
| ++++++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `<T as HasTable>::Table: SingleValue` is not satisfied
--> src/base/service.rs:86:25
|
86 | .get_result(&mut conn)
| ---------- ^^^^^^^^^ the trait `SingleValue` is not implemented for `<T as HasTable>::Table`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
| |
| required by a bound introduced by this call
|
= note: required for `<T as HasTable>::Table` to implement `SqlTypeOrSelectable`
= note: required for `T` to implement `FromSqlRow<<T as HasTable>::Table, <Conn as Connection>::Backend>`
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
note: required by a bound in `get_result`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
| ---------- required by a bound in this associated function
1721 | where
1722 | Self: LoadQuery<'query, Conn, U>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
error[E0277]: the trait bound `<T as HasTable>::Table: diesel::Identifiable` is not satisfied
--> src/base/service.rs:83:9
|
83 | diesel::update(<T as HasTable>::table())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
|
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
error[E0277]: the trait bound `<T as HasTable>::Table: IntoUpdateTarget` is not satisfied
--> src/base/service.rs:92:24
|
92 | diesel::delete(<T as HasTable>::table())
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
| |
| required by a bound introduced by this call
|
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
note: required by a bound in `delete`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/functions.rs:132:18
|
132 | pub fn delete<T: IntoUpdateTarget>(source: T) -> DeleteStatement<T::Table, T::WhereClause> {
| ^^^^^^^^^^^^^^^^ required by this bound in `delete`
error[E0277]: the trait bound `<T as HasTable>::Table: HasTable` is not satisfied
--> src/base/service.rs:92:9
|
92 | diesel::delete(<T as HasTable>::table())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasTable` is not implemented for `<T as HasTable>::Table`
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
--> src/base/service.rs:93:14
|
93 | .filter(T::primary_key().eq(id))
| ^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `DeleteStatement<_, _>: FilterDsl<_>`
|
= help: the following other types implement trait `AppearsOnTable<QS>`:
`&'a T` implements `AppearsOnTable<QS>`
`(T0, T1)` implements `AppearsOnTable<QS>`
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
and 131 others
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
= note: 1 redundant requirement hidden
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
= note: required for `DeleteStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
--> src/base/service.rs:93:21
|
93 | .filter(T::primary_key().eq(id))
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `DeleteStatement<_, _>: FilterDsl<_>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `AppearsOnTable<QS>`:
`&'a T` implements `AppearsOnTable<QS>`
`(T0, T1)` implements `AppearsOnTable<QS>`
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
and 131 others
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
= note: 1 redundant requirement hidden
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
= note: required for `DeleteStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
note: required by a bound in `DeleteStatement::<T, U>::filter`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/delete_statement/mod.rs:113:15
|
111 | pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
| ------ required by a bound in this associated function
112 | where
113 | Self: FilterDsl<Predicate>,
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `DeleteStatement::<T, U>::filter`
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0277]: the trait bound `<Conn as Connection>::Backend: DieselReserveSpecialization` is not satisfied
--> src/base/service.rs:94:22
|
94 | .execute(&mut conn)
| ------- ^^^^^^^^^ the trait `DieselReserveSpecialization` is not implemented for `<Conn as Connection>::Backend`, which is required by `DeleteStatement<_, _>: ExecuteDsl<_, _>`
| |
| required by a bound introduced by this call
|
= note: required for `DeleteStatement<_, _>` to implement `QueryFragment<<Conn as Connection>::Backend>`
= note: required for `DeleteStatement<_, _>` to implement `ExecuteDsl<PooledConnection<ConnectionManager<Conn>>, <Conn as Connection>::Backend>`
note: required by a bound in `diesel::RunQueryDsl::execute`
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1431:15
|
1428 | fn execute(self, conn: &mut Conn) -> QueryResult<usize>
| ------- required by a bound in this associated function
...
1431 | Self: methods::ExecuteDsl<Conn>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::execute`
error[E0277]: the trait bound `<T as HasTable>::Table: diesel::Identifiable` is not satisfied
--> src/base/service.rs:92:9
|
92 | diesel::delete(<T as HasTable>::table())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
|
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
Some errors have detailed explanations: E0275, E0277.
For more information about an error, try `rustc --explain E0275`.
error: could not compile `openlayerhub` (bin "openlayerhub") due to 26 previous errors

View File

@ -1,78 +0,0 @@
use crate::base::{entity::BaseEntity, i_service::IBaseService};
use anyhow::Result;
use axum::{extract::{Path, State}, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
use diesel::Identifiable;
use serde::Serialize;
use std::{marker::PhantomData, ops::Deref, sync::Arc};
pub struct BaseController<T, S>
where
T: BaseEntity + Identifiable<Id = i32> + Serialize + Send + Sync + 'static,
S: IBaseService<T> + Send + Sync + 'static,
{
service: S,
_marker: PhantomData<T>,
}
impl<T, S> BaseController<T, S>
where
T: BaseEntity + Identifiable<Id = i32> + Serialize + Send + Sync + 'static,
S: IBaseService<T> + Send + Sync + 'static,
{
pub fn new(service: S) -> Self {
Self {
service,
_marker: PhantomData,
}
}
pub async fn get_all(&self) -> Result<impl IntoResponse, String> {
let entities = self
.service
.get_all()
.await
.map_err(|err| err.to_string())?;
Ok((StatusCode::OK, Json(entities)))
}
pub async fn get_by_id(&self, id: i32) -> Result<impl IntoResponse, String> {
let entity = self
.service
.get_by_id(id)
.await
.map_err(|err| err.to_string())?;
match entity {
Some(entity) => Ok((StatusCode::OK, Json(entity))),
None => Err(format!("Entity with id {} not found.", id))
}
}
pub fn default_routes<C>(controller: Arc<C>, base_path: &str) -> Router
where
C: Deref<Target = Self> + Send + Sync + 'static,
{
Router::new()
.route(
&format!("{}", base_path),
get(|State(controller): State<Arc<C>>| async move {
controller
.get_all()
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, Json(err)))
}),
)
.route(
// Add route for getting by ID (e.g., /:id)
&format!("{}/{{id}}", base_path),
get(|State(controller): State<Arc<C>>, Path(id): Path<i32>| async move {
controller
.get_by_id(id)
.await
.map_err(|err| (StatusCode::NOT_FOUND, Json(err)))
}),
)
.with_state(controller)
}
}

View File

@ -1,16 +0,0 @@
use serde::{Deserialize, Serialize};
pub trait BaseEntity {
fn id(&self) -> i32;
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Entity {
pub id: i32,
}
impl BaseEntity for Entity {
fn id(&self) -> i32 {
self.id
}
}

View File

@ -1,11 +0,0 @@
use anyhow::{Error, Result};
use async_trait::async_trait;
#[async_trait]
pub trait IBaseService<T> {
async fn get_all(&self) -> Result<Vec<T>, Error>;
async fn get_by_id(&self, id: i32) -> Result<Option<T>, Error>;
async fn update(&self, entity: T) -> Result<T, Error>;
//async fn create(&self, entity: T) -> Result<i32, Error>;
async fn delete(&self, id: i32) -> Result<bool, Error>;
}

View File

@ -1,4 +0,0 @@
pub mod i_service;
pub mod service;
pub mod controller;
pub mod entity;

View File

@ -1,89 +0,0 @@
use std::marker::PhantomData;
use anyhow::Error;
use async_trait::async_trait;
use diesel::prelude::*;
use diesel::associations::HasTable;
use diesel::query_dsl::methods::{FindDsl, LoadQuery};
use crate::config::db::{get_connection, DbPool};
use super::i_service::IBaseService;
pub struct BaseService<T, U>
where
T: Identifiable<Id = i32> + Queryable<U::SqlType, diesel::pg::Pg> + Send + Sync + 'static,
U: Table + HasTable<Table = U> + LoadQuery<'static, PgConnection, T> + Send + Sync + 'static,
{
pool: DbPool,
_marker: PhantomData<(T, U)>,
}
impl<T, U> BaseService<T, U>
where
T: Identifiable<Id = i32> + Queryable<U::SqlType, diesel::pg::Pg> + Send + Sync + 'static,
U: Table
+ HasTable<Table = U>
+ LoadQuery<'static, PgConnection, T>
+ Send
+ Sync
+ 'static,
{
pub fn new(pool: DbPool) -> Self {
Self {
pool,
_marker: PhantomData,
}
}
}
#[async_trait]
impl<T, U> IBaseService<T> for BaseService<T, U>
where
T: Identifiable<Id = i32> + Queryable<U::SqlType, diesel::pg::Pg> + Send + Sync + 'static,
U: Table
+ HasTable<Table = U>
+ LoadQuery<'static, PgConnection, T>
+ FindDsl<i32>
+ Send
+ Sync
+ 'static,
<U as FindDsl<i32>>::Output: LoadQuery<'static, PgConnection, T>,
{
async fn get_all(&self) -> Result<Vec<T>, Error> {
let pool = self.pool.clone();
let result = tokio::task::spawn_blocking(move || {
let mut conn = get_connection(&pool).expect("Failed to get DB connection");
U::table().load::<T>(&mut conn)
})
.await??;
Ok(result)
}
async fn get_by_id(&self, id: i32) -> Result<Option<T>, Error> {
let pool = self.pool.clone();
let result = tokio::task::spawn_blocking(move || {
let mut conn = get_connection(&pool).expect("Failed to get DB connection");
U::table()
.find(id)
.get_result::<T>(&mut conn)
.optional()
})
.await??;
Ok(result)
}
async fn update(&self, entity: T) -> Result<T, Error> {
todo!()
}
// async fn create(&self, entity: T) -> Result<T, Error> {
// todo!()
// }
async fn delete(&self, id: i32) -> Result<bool, Error> {
todo!()
}
}

View File

@ -1,23 +0,0 @@
use diesel::pg::PgConnection;
use diesel::r2d2::{self, ConnectionManager, Pool, PoolError};
use std::env;
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
pub fn establish_connection_pool() -> Result<DbPool, PoolError> {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let manager = ConnectionManager::<PgConnection>::new(database_url);
Pool::builder().build(manager)
}
pub fn get_connection(
pool: &DbPool,
) -> Result<r2d2::PooledConnection<ConnectionManager<PgConnection>>, PoolError> {
pool.get()
}
pub fn init_db() -> DbPool {
establish_connection_pool().expect("Failed to create connection pool")
}

View File

@ -1 +0,0 @@
pub mod db;

88
src/crud/handlers.rs Normal file
View File

@ -0,0 +1,88 @@
use actix_web::{web, HttpResponse, Responder};
use diesel::pg::PgConnection;
use diesel::r2d2::{self, ConnectionManager};
use serde::Deserialize;
use super::r#trait::CrudEntity;
type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;
#[derive(Deserialize)]
struct Pagination {
limit: Option<i64>,
offset: Option<i64>,
}
pub async fn get_all<T: CrudEntity>(
pool: web::Data<DbPool>,
query: web::Query<Pagination>,
) -> impl Responder {
let mut conn = match pool.get() {
Ok(conn) => conn,
Err(_) => return HttpResponse::InternalServerError().finish(),
};
match T::find_all(&mut conn, query.limit, query.offset) {
Ok(items) => HttpResponse::Ok().json(items),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
pub async fn get_one<T: CrudEntity>(
pool: web::Data<DbPool>,
id: web::Path<T::Id>,
) -> impl Responder {
let mut conn = match pool.get() {
Ok(conn) => conn,
Err(_) => return HttpResponse::InternalServerError().finish(),
};
match T::find_by_id(&mut conn, id.into_inner()) {
Ok(item) => HttpResponse::Ok().json(item),
Err(diesel::result::Error::NotFound) => HttpResponse::NotFound().finish(),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
pub async fn create<T: CrudEntity>(
pool: web::Data<DbPool>,
item: web::Json<T::CreateInput>,
) -> impl Responder {
let mut conn = match pool.get() {
Ok(conn) => conn,
Err(_) => return HttpResponse::InternalServerError().finish(),
};
match T::insert(&mut conn, item.into_inner()) {
Ok(created) => HttpResponse::Created().json(created),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
pub async fn update<T: CrudEntity>(
pool: web::Data<DbPool>,
id: web::Path<T::Id>,
item: web::Json<T::UpdateInput>,
) -> impl Responder {
let mut conn = match pool.get() {
Ok(conn) => conn,
Err(_) => return HttpResponse::InternalServerError().finish(),
};
match T::update(&mut conn, id.into_inner(), item.into_inner()) {
Ok(updated) => HttpResponse::Ok().json(updated),
Err(diesel::result::Error::NotFound) => HttpResponse::NotFound().finish(),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
pub async fn delete<T: CrudEntity>(
pool: web::Data<DbPool>,
id: web::Path<T::Id>,
) -> impl Responder {
let mut conn = match pool.get() {
Ok(conn) => conn,
Err(_) => return HttpResponse::InternalServerError().finish(),
};
match T::delete(&mut conn, id.into_inner()) {
Ok(_) => HttpResponse::NoContent().finish(),
Err(diesel::result::Error::NotFound) => HttpResponse::NotFound().finish(),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}

2
src/crud/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod r#trait;
pub mod handlers;

14
src/crud/trait.rs Normal file
View File

@ -0,0 +1,14 @@
use diesel::prelude::*;
use serde::{de::DeserializeOwned, Serialize};
pub trait CrudEntity: Sized + Serialize {
type Id: Serialize + DeserializeOwned + 'static;
type CreateInput: DeserializeOwned + 'static;
type UpdateInput: DeserializeOwned + 'static;
fn find_all(conn: &mut PgConnection, limit: Option<i64>, offset: Option<i64>) -> Result<Vec<Self>, diesel::result::Error>;
fn find_by_id(conn: &mut PgConnection, id: Self::Id) -> Result<Self, diesel::result::Error>;
fn insert(conn: &mut PgConnection, item: Self::CreateInput) -> Result<Self, diesel::result::Error>;
fn update(conn: &mut PgConnection, id: Self::Id, item: Self::UpdateInput) -> Result<Self, diesel::result::Error>;
fn delete(conn: &mut PgConnection, id: Self::Id) -> Result<usize, diesel::result::Error>;
}

14
src/db/connection.rs Normal file
View File

@ -0,0 +1,14 @@
use diesel::pg::PgConnection;
use diesel::r2d2::{self, ConnectionManager};
use std::env;
pub type Pool = r2d2::Pool<ConnectionManager<PgConnection>>;
pub fn establish_connection_pool() -> Pool {
dotenv::dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let manager = ConnectionManager::<PgConnection>::new(database_url);
r2d2::Pool::builder()
.build(manager)
.expect("Failed to create pool")
}

1
src/db/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod connection;

View File

@ -1,51 +1,24 @@
use std::sync::Arc;
use actix_web::{web, App, HttpServer};
use db::connection::establish_connection_pool;
use models::user::User;
use routes::crud::add_crud_routes;
use crate::routes::user::controller::UserController;
use crate::routes::user::model::{User, UserResponse};
use crate::routes::user::service::UserService;
use axum::http::StatusCode;
use axum::routing::get;
use axum::{serve, Router};
use config::db::init_db;
use dotenvy::dotenv;
use tokio::net::TcpListener;
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;
mod base;
mod config;
mod crud;
mod models;
mod db;
mod routes;
mod schema;
#[tokio::main]
async fn main() {
dotenv().ok();
let pool = init_db();
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let pool = establish_connection_pool();
let hc_router = Router::new().route("/", get(health_check));
let user_service = UserService::new(pool);
let user_controller = Arc::new(UserController::new(user_service));
let app = Router::new()
.merge(UserController::routes(user_controller.clone()))
.merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
.nest("/hc", hc_router);
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
serve(listener, app).await.unwrap();
async fn health_check() -> StatusCode {
StatusCode::OK
}
#[derive(OpenApi)]
#[openapi(
components(
schemas(User, UserResponse)
),
tags(
(name = "users", description = "User management endpoints")
)
)]
struct ApiDoc;
HttpServer::new(move || {
let mut app = App::new().app_data(web::Data::new(pool.clone()));
app = add_crud_routes::<User>(app, "/users");
app
})
.bind("0.0.0.0:3000")?
.run()
.await
}

1
src/models/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod user;

63
src/models/user.rs Normal file
View File

@ -0,0 +1,63 @@
use diesel::prelude::*;
use serde::{Serialize, Deserialize};
use crate::{crud::r#trait::CrudEntity, schema::users};
#[derive(Serialize, Deserialize, Queryable, Insertable)]
#[diesel(table_name = users)]
pub struct User {
id: i32,
name: String,
email: String,
}
#[derive(Deserialize, Insertable)]
#[diesel(table_name = users)]
pub struct NewUser {
name: String,
email: String,
}
#[derive(Deserialize, AsChangeset)]
#[diesel(table_name = users)]
pub struct UpdateUser {
name: String,
email: String,
}
impl CrudEntity for User {
type Id = i32;
type CreateInput = NewUser;
type UpdateInput = UpdateUser; // Changed from User to UpdateUser
fn find_all(conn: &mut PgConnection, limit: Option<i64>, offset: Option<i64>) -> Result<Vec<Self>, diesel::result::Error> {
use crate::schema::users::dsl::*;
let mut query = users.into_boxed();
if let Some(l) = limit {
query = query.limit(l);
}
if let Some(o) = offset {
query = query.offset(o);
}
query.load::<Self>(conn)
}
fn find_by_id(conn: &mut PgConnection, id: Self::Id) -> Result<Self, diesel::result::Error> {
use crate::schema::users::dsl::*;
users.filter(id.eq(id)).first::<Self>(conn)
}
fn insert(conn: &mut PgConnection, item: Self::CreateInput) -> Result<Self, diesel::result::Error> {
use crate::schema::users;
diesel::insert_into(users::table).values(&item).get_result(conn)
}
fn update(conn: &mut PgConnection, id: Self::Id, item: Self::UpdateInput) -> Result<Self, diesel::result::Error> {
use crate::schema::users::dsl::*;
diesel::update(users.filter(id.eq(id))).set(&item).get_result(conn)
}
fn delete(conn: &mut PgConnection, id: Self::Id) -> Result<usize, diesel::result::Error> {
use crate::schema::users::dsl::*;
diesel::delete(users.filter(id.eq(id))).execute(conn)
}
}

24
src/routes/crud.rs Normal file
View File

@ -0,0 +1,24 @@
use actix_web::{dev::{ServiceFactory, ServiceRequest}, web, App};
use crate::crud::{handlers, r#trait::CrudEntity};
pub fn add_crud_routes<T: CrudEntity + 'static>(mut app: App<T>, path: &str) -> App<T>
where
T::Id: serde::de::DeserializeOwned + serde::Serialize + 'static,
T::CreateInput: serde::de::DeserializeOwned + 'static,
T::UpdateInput: serde::de::DeserializeOwned + 'static,
T: ServiceFactory<ServiceRequest, Config = (), Error = actix_web::Error, InitError = ()>
{
app = app.service(
web::resource(path)
.route(web::get().to(handlers::get_all::<T>))
.route(web::post().to(handlers::create::<T>)),
);
app.service(
web::resource(&format!("{}/{{id}}", path))
.route(web::get().to(handlers::get_one::<T>))
.route(web::put().to(handlers::update::<T>))
.route(web::delete().to(handlers::delete::<T>)),
)
}

View File

@ -1 +1 @@
pub mod user;
pub mod crud;

View File

@ -1,44 +0,0 @@
use std::ops::Deref;
use std::sync::Arc;
use crate::base::controller::BaseController;
use axum::Router;
use super::model::User;
use super::service::UserService;
pub struct UserController {
base_controller: BaseController<User, UserService>,
}
impl Deref for UserController {
type Target = BaseController<User, UserService>;
fn deref(&self) -> &Self::Target {
&self.base_controller
}
}
impl UserController {
pub fn new(service: UserService) -> Self {
Self {
base_controller: BaseController::new(service),
}
}
pub fn routes(controller: Arc<Self>) -> Router {
BaseController::default_routes(controller, "/users")
}
/*
async fn get_users(
State(controller): State<Arc<UserController>>,
) -> Result<impl IntoResponse, (StatusCode, Json<String>)> {
controller
.base_controller
.get_all()
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, Json(err)))
}
*/
}

View File

@ -1,4 +0,0 @@
pub mod model;
pub mod schema;
pub mod service;
pub mod controller;

View File

@ -1,35 +0,0 @@
use super::schema::users;
use crate::base::entity::BaseEntity;
use diesel::prelude::*;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, ToSchema)]
#[diesel(table_name = users, primary_key(id))]
pub struct User {
pub id: i32,
pub name: String,
pub email: String,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct UserResponse {
pub id: i32,
pub name: String,
pub email: String,
}
impl BaseEntity for User {
fn id(&self) -> i32 {
self.id
}
}
impl Identifiable for User {
type Id = i32;
fn id(self) -> Self::Id {
self.id
}
}

View File

@ -1,9 +0,0 @@
use diesel::table;
table! {
users (id) {
id -> Integer,
name -> Varchar,
email -> Varchar,
}
}

View File

@ -1,5 +0,0 @@
use crate::base::service::BaseService;
use super::model::User;
use super::schema::users;
pub type UserService = BaseService<User, users::table>;