user-auth orm and meili changes
This commit is contained in:
621
backend/Cargo.lock
generated
621
backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ booksman-orm = { path = "../orm" }
|
|||||||
booksman-search = { path = "../search" }
|
booksman-search = { path = "../search" }
|
||||||
migration = { path = "../migration" }
|
migration = { path = "../migration" }
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
axum = "^0.5"
|
axum = "^0.6"
|
||||||
axum-extra = { version = "^0.3", features = ["spa"] }
|
axum-extra = { version = "^0.3", features = ["spa"] }
|
||||||
clap = { version = "^3", features = ["derive"] }
|
clap = { version = "^3", features = ["derive"] }
|
||||||
dotenvy = "0.15.0"
|
dotenvy = "0.15.0"
|
||||||
@@ -27,9 +27,15 @@ tracing = "^0.1"
|
|||||||
tracing-subscriber = "^0.3"
|
tracing-subscriber = "^0.3"
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
axum-login = "0.4"
|
||||||
|
#features = ["sqlite"]
|
||||||
|
|
||||||
|
[dependencies.rand]
|
||||||
|
version = "0.8.5"
|
||||||
|
features = ["min_const_gen"]
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
version = "^0.9.2" # sea-orm version
|
version = "^0.10.6" # sea-orm version
|
||||||
features = [
|
features = [
|
||||||
"debug-print",
|
"debug-print",
|
||||||
"runtime-tokio-native-tls",
|
"runtime-tokio-native-tls",
|
||||||
|
|||||||
@@ -31,6 +31,31 @@ use ::entity::entities::{book,book_author,book_person,book_place,book_subject,bo
|
|||||||
use std::env;
|
use std::env;
|
||||||
use migration::{Migrator, MigratorTrait};
|
use migration::{Migrator, MigratorTrait};
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
|
use axum_login::{
|
||||||
|
axum_sessions::{async_session::MemoryStore as SessionMemoryStore, SessionLayer},
|
||||||
|
memory_store::MemoryStore as AuthMemoryStore,
|
||||||
|
secrecy::SecretVec,
|
||||||
|
AuthLayer, AuthUser, RequireAuthorizationLayer,
|
||||||
|
};
|
||||||
|
use rand::Rng;
|
||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
struct User {
|
||||||
|
id: i64,
|
||||||
|
password_hash: String,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthUser for User {
|
||||||
|
fn get_id(&self) -> String {
|
||||||
|
format!("{}", self.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_password_hash(&self) -> SecretVec<u8> {
|
||||||
|
SecretVec::new(self.password_hash.clone().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
struct BookUI {
|
struct BookUI {
|
||||||
@@ -206,6 +231,8 @@ struct Opt {
|
|||||||
static_dir: String,
|
static_dir: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AuthContext = axum_login::extractors::AuthContext<User, AuthMemoryStore<User>>;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn main() {
|
pub async fn main() {
|
||||||
let opt = Opt::parse();
|
let opt = Opt::parse();
|
||||||
@@ -225,6 +252,10 @@ pub async fn main() {
|
|||||||
let meili_url = env::var("MEILI_URL").expect("MEILI_URL is not set in .env file");
|
let meili_url = env::var("MEILI_URL").expect("MEILI_URL is not set in .env file");
|
||||||
let meili_key = env::var("MEILI_KEY").expect("MEILI_KEY is not set in .env file");
|
let meili_key = env::var("MEILI_KEY").expect("MEILI_KEY is not set in .env file");
|
||||||
|
|
||||||
|
let secret = rand::thread_rng().gen::<[u8; 64]>();
|
||||||
|
|
||||||
|
let session_store = MemoryStore::new();
|
||||||
|
let session_layer = SessionLayer::new(session_store, &secret).with_secure(false);
|
||||||
|
|
||||||
let conn = Database::connect(db_url)
|
let conn = Database::connect(db_url)
|
||||||
.await
|
.await
|
||||||
@@ -232,8 +263,37 @@ pub async fn main() {
|
|||||||
// Apply all pending migrations
|
// Apply all pending migrations
|
||||||
Migrator::up(&conn, None).await.unwrap();
|
Migrator::up(&conn, None).await.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let store = Arc::new(RwLock::new(HashMap::default()));
|
||||||
|
let users : Vec<User> = get_users_seaorm(conn);
|
||||||
|
//let user = User::get_rusty_user();
|
||||||
|
for user in users.iter() {
|
||||||
|
store.write().await.insert(user.get_id(), user);
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_store = AuthMemoryStore::new(&store);
|
||||||
|
let auth_layer = AuthLayer::new(user_store, &secret);
|
||||||
|
|
||||||
let meili_client = Client::new(meili_url, meili_key);
|
let meili_client = Client::new(meili_url, meili_key);
|
||||||
|
|
||||||
|
|
||||||
|
async fn login_handler(mut auth: AuthContext, Json(user_sent): Json<User>) {
|
||||||
|
auth.login(&user_sent).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn register_handler(mut auth: AuthContext, Json(user_sent): Json<User>) {
|
||||||
|
// add to db
|
||||||
|
store.write().await.insert(user_sent.get_id(), user_sent);
|
||||||
|
auth.login(&user_sent).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn logout_handler(mut auth: AuthContext) {
|
||||||
|
dbg!("Logging out user: {}", &auth.current_user);
|
||||||
|
auth.logout().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/api/search_openlibrary", get(search_openlibrary))
|
.route("/api/search_openlibrary", get(search_openlibrary))
|
||||||
.route("/api/create_by_isbn", get(create_by_isbn))
|
.route("/api/create_by_isbn", get(create_by_isbn))
|
||||||
@@ -242,8 +302,13 @@ pub async fn main() {
|
|||||||
.route("/api/list_search", get(list_search_book))
|
.route("/api/list_search", get(list_search_book))
|
||||||
.route("/api/create", post(create_book))
|
.route("/api/create", post(create_book))
|
||||||
.route("/api/update", post(update_book))
|
.route("/api/update", post(update_book))
|
||||||
|
.route("/api/login", post(login_handler))
|
||||||
|
.route("/api/register", post(register_handler))
|
||||||
|
.route("/api/logout", post(logout_handler))
|
||||||
.nest("/images", get_service(ServeDir::new(images_dir)).handle_error(handle_error))
|
.nest("/images", get_service(ServeDir::new(images_dir)).handle_error(handle_error))
|
||||||
.merge(SpaRouter::new("/assets", opt.static_dir))
|
.merge(SpaRouter::new("/assets", opt.static_dir))
|
||||||
|
.layer(auth_layer)
|
||||||
|
.layer(session_layer)
|
||||||
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()))
|
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()))
|
||||||
.layer(Extension(conn))
|
.layer(Extension(conn))
|
||||||
.layer(Extension(meili_client))
|
.layer(Extension(meili_client))
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] }
|
|||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
version = "^0.9.2" # sea-orm version
|
version = "^0.10.6" # sea-orm version
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book")]
|
#[sea_orm(table_name = "book")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
@@ -19,12 +19,15 @@ pub struct Model {
|
|||||||
pub time_added: Option<String>,
|
pub time_added: Option<String>,
|
||||||
pub rating: Option<i32>,
|
pub rating: Option<i32>,
|
||||||
pub comments: Option<String>,
|
pub comments: Option<String>,
|
||||||
|
pub user_id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
pub enum Relation {
|
pub enum Relation {
|
||||||
#[sea_orm(has_many = "super::book_author::Entity")]
|
#[sea_orm(has_many = "super::book_author::Entity")]
|
||||||
BookAuthor,
|
BookAuthor,
|
||||||
|
#[sea_orm(has_many = "super::book_isbn::Entity")]
|
||||||
|
BookIsbn,
|
||||||
#[sea_orm(has_many = "super::book_person::Entity")]
|
#[sea_orm(has_many = "super::book_person::Entity")]
|
||||||
BookPerson,
|
BookPerson,
|
||||||
#[sea_orm(has_many = "super::book_place::Entity")]
|
#[sea_orm(has_many = "super::book_place::Entity")]
|
||||||
@@ -33,8 +36,14 @@ pub enum Relation {
|
|||||||
BookSubject,
|
BookSubject,
|
||||||
#[sea_orm(has_many = "super::book_time::Entity")]
|
#[sea_orm(has_many = "super::book_time::Entity")]
|
||||||
BookTime,
|
BookTime,
|
||||||
#[sea_orm(has_many = "super::book_isbn::Entity")]
|
#[sea_orm(
|
||||||
BookIsbn,
|
belongs_to = "super::user::Entity",
|
||||||
|
from = "Column::UserId",
|
||||||
|
to = "super::user::Column::Id",
|
||||||
|
on_update = "Cascade",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
User,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::book_author::Entity> for Entity {
|
impl Related<super::book_author::Entity> for Entity {
|
||||||
@@ -43,6 +52,12 @@ impl Related<super::book_author::Entity> for Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::book_isbn::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::BookIsbn.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Related<super::book_person::Entity> for Entity {
|
impl Related<super::book_person::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
Relation::BookPerson.def()
|
Relation::BookPerson.def()
|
||||||
@@ -67,9 +82,9 @@ impl Related<super::book_time::Entity> for Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::book_isbn::Entity> for Entity {
|
impl Related<super::user::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
Relation::BookIsbn.def()
|
Relation::User.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book_author")]
|
#[sea_orm(table_name = "book_author")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book_isbn")]
|
#[sea_orm(table_name = "book_isbn")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book_person")]
|
#[sea_orm(table_name = "book_person")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book_place")]
|
#[sea_orm(table_name = "book_place")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book_subject")]
|
#[sea_orm(table_name = "book_subject")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "book_time")]
|
#[sea_orm(table_name = "book_time")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
||||||
@@ -9,3 +9,4 @@ pub mod book_person;
|
|||||||
pub mod book_place;
|
pub mod book_place;
|
||||||
pub mod book_subject;
|
pub mod book_subject;
|
||||||
pub mod book_time;
|
pub mod book_time;
|
||||||
|
pub mod user;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.9.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
pub use super::book::Entity as Book;
|
pub use super::book::Entity as Book;
|
||||||
pub use super::book_author::Entity as BookAuthor;
|
pub use super::book_author::Entity as BookAuthor;
|
||||||
@@ -7,3 +7,4 @@ pub use super::book_person::Entity as BookPerson;
|
|||||||
pub use super::book_place::Entity as BookPlace;
|
pub use super::book_place::Entity as BookPlace;
|
||||||
pub use super::book_subject::Entity as BookSubject;
|
pub use super::book_subject::Entity as BookSubject;
|
||||||
pub use super::book_time::Entity as BookTime;
|
pub use super::book_time::Entity as BookTime;
|
||||||
|
pub use super::user::Entity as User;
|
||||||
|
|||||||
26
backend/entity/src/entities/user.rs
Normal file
26
backend/entity/src/entities/user.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
|
#[sea_orm(table_name = "user")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub user_name: Option<String>,
|
||||||
|
pub password_hash: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::book::Entity")]
|
||||||
|
Book,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::book::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Book.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -13,7 +13,7 @@ async-std = { version = "^1", features = ["attributes", "tokio1"] }
|
|||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
|
||||||
[dependencies.sea-orm-migration]
|
[dependencies.sea-orm-migration]
|
||||||
version = "^0.9.2"
|
version = "^0.10.6"
|
||||||
features = [
|
features = [
|
||||||
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
|
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
|
||||||
# View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
|
# View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
|
||||||
|
|||||||
@@ -10,6 +10,26 @@ impl MigrationTrait for Migration {
|
|||||||
// Replace the sample below with your own migration scripts
|
// Replace the sample below with your own migration scripts
|
||||||
//todo!();
|
//todo!();
|
||||||
|
|
||||||
|
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(User::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(User::Id)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.auto_increment()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(User::UserName).string().unique_key().not_null())
|
||||||
|
.col(ColumnDef::new(User::PasswordHash).string().not_null())
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await.expect("Migration failed");
|
||||||
|
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.create_table(
|
.create_table(
|
||||||
Table::create()
|
Table::create()
|
||||||
@@ -34,6 +54,15 @@ impl MigrationTrait for Migration {
|
|||||||
.col(ColumnDef::new(Book::TimeAdded).time())
|
.col(ColumnDef::new(Book::TimeAdded).time())
|
||||||
.col(ColumnDef::new(Book::Rating).integer())
|
.col(ColumnDef::new(Book::Rating).integer())
|
||||||
.col(ColumnDef::new(Book::Comments).string())
|
.col(ColumnDef::new(Book::Comments).string())
|
||||||
|
.col(ColumnDef::new(Book::UserId).integer().not_null())
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("FK_2e303c3a712662f1fc2a4d0aavc")
|
||||||
|
.from(Book::Table, Book::UserId)
|
||||||
|
.to(User::Table, User::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.on_update(ForeignKeyAction::Cascade),
|
||||||
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
.await.expect("Migration failed");
|
.await.expect("Migration failed");
|
||||||
@@ -246,6 +275,7 @@ enum Book {
|
|||||||
TimeAdded,
|
TimeAdded,
|
||||||
Rating,
|
Rating,
|
||||||
Comments,
|
Comments,
|
||||||
|
UserId
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Iden)]
|
#[derive(Iden)]
|
||||||
@@ -295,3 +325,11 @@ enum BookISBN {
|
|||||||
ISBN,
|
ISBN,
|
||||||
BookId,
|
BookId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
enum User {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
UserName,
|
||||||
|
PasswordHash,
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ entity = { path = "../entity" }
|
|||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
version = "^0.9.2" # sea-orm version
|
version = "^0.10.6" # sea-orm version
|
||||||
features = [
|
features = [
|
||||||
"debug-print",
|
"debug-print",
|
||||||
"runtime-tokio-native-tls",
|
"runtime-tokio-native-tls",
|
||||||
|
|||||||
@@ -1,14 +1,37 @@
|
|||||||
//use ::entity::entities::prelude::Book;
|
//use ::entity::entities::prelude::Book;
|
||||||
//use ::entity::entities::{prelude::*, *};
|
//use ::entity::entities::{prelude::*, *};
|
||||||
use ::entity::entities::{book::Entity as Book};
|
use ::entity::entities::user::Entity as User;
|
||||||
|
use ::entity::entities::book::Entity as Book;
|
||||||
//, book_author::Entity as Author, book_person::Entity as Person, book_place::Entity as Place, book_subject::Entity as Subject, book_time::Entity as Time, book_isbn::Entity as ISBN};
|
//, book_author::Entity as Author, book_person::Entity as Person, book_place::Entity as Place, book_subject::Entity as Subject, book_time::Entity as Time, book_isbn::Entity as ISBN};
|
||||||
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn};
|
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user};
|
||||||
use sea_orm::*;
|
use sea_orm::*;
|
||||||
//use ::entity::entities::prelude::Book;
|
//use ::entity::entities::prelude::Book;
|
||||||
|
|
||||||
pub struct Mutation;
|
pub struct Mutation;
|
||||||
|
|
||||||
impl Mutation {
|
impl Mutation {
|
||||||
|
pub async fn create_user(
|
||||||
|
db: &DbConn,
|
||||||
|
form_data: user::Model,
|
||||||
|
) -> Result<InsertResult<user::ActiveModel>, DbErr> {
|
||||||
|
let record = user::ActiveModel {
|
||||||
|
user_name: Set(form_data.user_name.to_owned()),
|
||||||
|
password_hash: Set(form_data.password_hash.to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
User::insert(record).exec(db).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_user(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||||
|
let user: user::ActiveModel = User::find_by_id(id)
|
||||||
|
.one(db)
|
||||||
|
.await?
|
||||||
|
.ok_or(DbErr::Custom("Cannot find user.".to_owned()))
|
||||||
|
.map(Into::into)?;
|
||||||
|
|
||||||
|
user.delete(db).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_book(
|
pub async fn create_book(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
form_data: book::Model,
|
form_data: book::Model,
|
||||||
@@ -26,6 +49,7 @@ impl Mutation {
|
|||||||
time_added: Set(form_data.time_added.to_owned()),
|
time_added: Set(form_data.time_added.to_owned()),
|
||||||
rating: Set(form_data.rating.to_owned()),
|
rating: Set(form_data.rating.to_owned()),
|
||||||
comments: Set(form_data.comments.to_owned()),
|
comments: Set(form_data.comments.to_owned()),
|
||||||
|
user_id: Set(form_data.user_id.to_owned()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
Book::insert(record).exec(db).await
|
Book::insert(record).exec(db).await
|
||||||
@@ -134,6 +158,7 @@ impl Mutation {
|
|||||||
time_added: Set(form_data.time_added.to_owned()),
|
time_added: Set(form_data.time_added.to_owned()),
|
||||||
rating: Set(form_data.rating.to_owned()),
|
rating: Set(form_data.rating.to_owned()),
|
||||||
comments: Set(form_data.comments.to_owned()),
|
comments: Set(form_data.comments.to_owned()),
|
||||||
|
user_id: Set(form_data.user_id.to_owned()),
|
||||||
}.update(db).await
|
}.update(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,11 +59,13 @@ impl Query {
|
|||||||
/// If ok, returns (post models, num pages).
|
/// If ok, returns (post models, num pages).
|
||||||
pub async fn find_books_in_page(
|
pub async fn find_books_in_page(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
page: usize,
|
page: u64,
|
||||||
posts_per_page: usize,
|
posts_per_page: u64,
|
||||||
) -> Result<(Vec<book::Model>, usize), DbErr> {
|
userid: i32,
|
||||||
|
) -> Result<(Vec<book::Model>, u64), DbErr> {
|
||||||
// Setup paginator
|
// Setup paginator
|
||||||
let paginator = Book::find()
|
let paginator = Book::find()
|
||||||
|
.filter(book::Column::UserId.eq(userid))
|
||||||
.order_by_asc(book::Column::Id)
|
.order_by_asc(book::Column::Id)
|
||||||
.paginate(db, posts_per_page);
|
.paginate(db, posts_per_page);
|
||||||
let num_pages = paginator.num_pages().await?;
|
let num_pages = paginator.num_pages().await?;
|
||||||
@@ -76,9 +78,10 @@ pub async fn find_books_plus_meta_in_page(
|
|||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
page: usize,
|
page: usize,
|
||||||
posts_per_page: usize,
|
posts_per_page: usize,
|
||||||
) -> Result<(Vec<BookAndMetaV2>, usize), DbErr> {
|
userid: i32,
|
||||||
|
) -> Result<(Vec<BookAndMetaV2>, u64), DbErr> {
|
||||||
// Setup paginator
|
// Setup paginator
|
||||||
let books = Self::find_books_in_page(db,page,posts_per_page).await?;
|
let books = Self::find_books_in_page(db,page.try_into().unwrap(),posts_per_page.try_into().unwrap(),userid).await?;
|
||||||
let book_ids: Vec<i32> = books.0.clone().into_iter().map(|b| b.id).collect();
|
let book_ids: Vec<i32> = books.0.clone().into_iter().map(|b| b.id).collect();
|
||||||
let mut resbooks: Vec<BookAndMetaV2> = Vec::with_capacity(book_ids.len());
|
let mut resbooks: Vec<BookAndMetaV2> = Vec::with_capacity(book_ids.len());
|
||||||
for book in books.0.iter() {
|
for book in books.0.iter() {
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ pub struct BookMeili {
|
|||||||
pub isbn: Vec<String>,
|
pub isbn: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_or_update_book(book: BookMeili, client: &Client) {
|
pub async fn create_or_update_book(book: BookMeili, userid: i32, client: &Client) {
|
||||||
// An index is where the documents are stored.
|
// An index is where the documents are stored.
|
||||||
let books = client.index("books");
|
let books = client.index(format!("books{}",userid));
|
||||||
// Add some movies in the index. If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
|
// Add some movies in the index. If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
|
||||||
books.add_or_replace(&[
|
books.add_or_replace(&[
|
||||||
book
|
book
|
||||||
@@ -35,16 +35,16 @@ pub async fn create_or_update_book(book: BookMeili, client: &Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn delete_book(bookid: i32, client: &Client) {
|
pub async fn delete_book(bookid: i32, userid: i32, client: &Client) {
|
||||||
// An index is where the documents are stored.
|
// An index is where the documents are stored.
|
||||||
let books = client.index("books");
|
let books = client.index(format!("books{}",userid));
|
||||||
books.delete_document(bookid).await.unwrap();
|
books.delete_document(bookid).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn search_book(search: &str, page: usize, client: &Client) -> Result<(Vec<BookMeili>, usize), meilisearch_sdk::errors::Error> {
|
pub async fn search_book(search: &str, page: usize, userid: i32, client: &Client) -> Result<(Vec<BookMeili>, usize), meilisearch_sdk::errors::Error> {
|
||||||
// An index is where the documents are stored.
|
// An index is where the documents are stored.
|
||||||
let books = client.index("books");
|
let books = client.index(format!("books{}",userid));
|
||||||
let results : SearchResults<BookMeili> = books.search().with_query(search).with_offset((page-1)*12)
|
let results : SearchResults<BookMeili> = books.search().with_query(search).with_offset((page-1)*12)
|
||||||
.execute::<BookMeili>().await.unwrap();
|
.execute::<BookMeili>().await.unwrap();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user