Skip to content

Commit

Permalink
feat: add cache to question and page
Browse files Browse the repository at this point in the history
  • Loading branch information
zrll12 committed Aug 17, 2024
1 parent f67e449 commit 9054d2f
Show file tree
Hide file tree
Showing 21 changed files with 433 additions and 24 deletions.
45 changes: 45 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ migration = {path = "migration"}
sea-orm = { version = "0.12.15", features = ["macros", "sqlx-postgres", "runtime-tokio-rustls"] }
futures = "0.3.30"
chrono = "0.4.38"
uuid = { version = "1.9.1", features = ["v4"] }
ciborium = "0.2.2"


[build-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod m20240814_153908_create_survey_table;
mod m20240816_073728_create_answer_table;
mod m20240817_030711_add_required_to_question;
mod m20240817_035143_add_control_to_survey;
mod m20240817_100708_create_admin_table;

pub struct Migrator;

Expand All @@ -19,6 +20,7 @@ impl MigratorTrait for Migrator {
Box::new(m20240816_073728_create_answer_table::Migration),
Box::new(m20240817_030711_add_required_to_question::Migration),
Box::new(m20240817_035143_add_control_to_survey::Migration),
Box::new(m20240817_100708_create_admin_table::Migration),
]
}
}
2 changes: 1 addition & 1 deletion migration/src/m20240811_145111_create_page_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl MigrationTrait for Migration {
)
.col(ColumnDef::new(Page::Title).string().not_null())
.col(ColumnDef::new(Page::Content).array(ColumnType::Char(Some(36))).not_null())
.col(ColumnDef::new(Page::Next).integer().null())
.col(ColumnDef::new(Page::Next).char_len(36).null())
.to_owned(),
)
.await
Expand Down
2 changes: 1 addition & 1 deletion migration/src/m20240814_153908_create_survey_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl MigrationTrait for Migration {
.col(ColumnDef::new(Survey::Budge).char_len(10).not_null())
.col(ColumnDef::new(Survey::Description).string().not_null())
.col(ColumnDef::new(Survey::Image).string().not_null())
.col(ColumnDef::new(Survey::Page).string().not_null())
.col(ColumnDef::new(Survey::Page).char_len(36).not_null())
.col(ColumnDef::new(Survey::StartDate).timestamp().not_null())
.col(ColumnDef::new(Survey::EndDate).timestamp().not_null())
.to_owned(),
Expand Down
40 changes: 40 additions & 0 deletions migration/src/m20240817_100708_create_admin_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Admin::Table)
.if_not_exists()
.col(
ColumnDef::new(Admin::Id)
.big_unsigned()
.not_null()
.primary_key(),
)
.col(ColumnDef::new(Admin::Username).string().not_null())
.col(ColumnDef::new(Admin::Disabled).boolean().not_null().default(false))
.to_owned(),
)
.await
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Admin::Table).to_owned())
.await
}
}

#[derive(DeriveIden)]
enum Admin {
Table,
Id,
Username,
Disabled,
}
5 changes: 3 additions & 2 deletions src/controller/question/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use axum::Router;
use axum::routing::get;
use axum::Router;

mod page;
mod question;
mod modify;

pub fn get_question_routers() -> Router {
Router::new()
.route("/", get(page::get_page))
.route("/", get(page::get_page).post(modify::new_question))
.route("/:question", get(question::get_question))
}
19 changes: 19 additions & 0 deletions src/controller/question/modify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::model::question::QuestionType;
use crate::service::questions::save_question;
use axum::Json;
use sea_orm::JsonValue;
use serde::Serialize;

pub async fn new_question(Json(question): Json<NewQuestionRequest>) -> String {
let id = save_question(question.content, question.r#type, question.values, question.condition, question.required, None).await;
id.to_string()
}

#[derive(serde::Deserialize, Serialize)]
pub struct NewQuestionRequest {
pub content: JsonValue,
pub r#type: QuestionType,
pub values: Option<Vec<JsonValue>>,
pub condition: Option<String>,
pub required: bool,
}
14 changes: 5 additions & 9 deletions src/controller/question/page.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
use axum::extract::Query;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use sea_orm::prelude::Uuid;
use serde::{Deserialize, Serialize};
use tracing::info;
use crate::controller::error::ErrorMessage;
use crate::DATABASE;
use crate::model::generated::page;
use crate::model::generated::prelude::Page;
use crate::service::questions::get_page_by_id;
use crate::service::token::TokenInfo;
use axum::extract::Query;
use serde::Deserialize;
use tracing::info;

pub async fn get_page(Query(query): Query<GetPageQuery>, TokenInfo(user): TokenInfo) -> Result<String, ErrorMessage> {
info!("User {} is trying to get page {}", user.uid, query.page);

let Some(page) = Page::find().filter(page::Column::Id.eq(query.page)).one(&*DATABASE).await.unwrap()
let Some(page) = get_page_by_id(query.page).await
else {
return Err(ErrorMessage::NotFound);
};
Expand Down
10 changes: 3 additions & 7 deletions src/controller/question/question.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
use crate::controller::error::ErrorMessage;
use crate::model::generated::prelude::Question;
use crate::model::generated::question;
use crate::DATABASE;
use crate::service::questions::get_question_by_id;
use crate::service::token::TokenInfo;
use axum::extract::Path;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use sea_orm::prelude::Uuid;
use tracing::info;
use crate::service::token::TokenInfo;

pub async fn get_question(Path(question): Path<String>, TokenInfo(user): TokenInfo) -> Result<String, ErrorMessage> {
info!("User {} is trying to get question {}", user.uid, question);

let Some(page) = Question::find().filter(question::Column::Id.eq(question)).one(&*DATABASE).await.unwrap()
let Some(page) = get_question_by_id(question).await
else {
return Err(ErrorMessage::NotFound);
};
Expand Down
30 changes: 29 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ use tracing_subscriber::fmt::time::ChronoLocal;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{fmt, EnvFilter, Registry};

use uuid::Uuid;
use migration::{Migrator, MigratorTrait};

use crate::config::core::CoreConfig;
use crate::config::get_config;
use crate::config::oauth::OAuthConfig;
use crate::model::generated::prelude::Question;
use crate::model::generated::question;
use crate::model::question::{Condition, ConditionInner, ConditionType, QuestionType};
use crate::model::ValueWithTitle;
use crate::service::questions::save_question;

mod config;
mod controller;
Expand Down Expand Up @@ -71,6 +74,31 @@ async fn main() {

Migrator::up(&*DATABASE, None).await.unwrap();

// let question = crate::model::question::Question {
// id: Uuid::new_v4(),
// content: ValueWithTitle {
// title: "title".to_string(),
// content: "content".to_string()
// },
// r#type: QuestionType::SingleChoice,
// values: Some(vec![ValueWithTitle {
// title: "title".to_string(),
// content: "content".to_string()
// }]),
// condition: Some(vec![Condition {
// r#type: ConditionType::And,
// conditions: vec![ConditionInner {
// id: Uuid::new_v4(),
// value: "value".to_string()
// }]
// }]),
// required: false
// };
//
// println!("{}", serde_json::to_string(&question).unwrap());

// save_question(question, None).await;

let origins = CORE_CONFIG.origins.clone().iter().map(|x| x.parse().unwrap()).collect::<Vec<HeaderValue>>();
let app = Router::new()
.nest("/api", controller::all_routers())
Expand Down
52 changes: 52 additions & 0 deletions src/model/admin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::controller::error::ErrorMessage;
use crate::model::generated::admin;
use crate::model::generated::prelude::Admin;
use axum::extract::FromRequestParts;
use axum::http::request::Parts;
use lazy_static::lazy_static;
use migration::async_trait::async_trait;
use moka::future::Cache;
use sea_orm::ColumnTrait;
use sea_orm::{EntityTrait, QueryFilter};
use std::time::Duration;

lazy_static! {
static ref ADMIN_TOKEN_CACHE: Cache<String, admin::Model> = Cache::builder()
.time_to_idle(Duration::from_secs(60 * 60 * 24 * 7)) //if the key is not accessed for 7 days, it will be removed
.build();
}

pub async fn get_admin_by_id(id: i32) -> Option<admin::Model> {
Admin::find()
.filter(admin::Column::Id.eq(id))
.one(&*crate::DATABASE).await.unwrap()
}

pub async fn register_admin_token(token: &str, user: i32) {
let admin = get_admin_by_id(user).await.unwrap();
ADMIN_TOKEN_CACHE.insert(token.to_string(), admin).await;
}

pub async fn get_admin_by_token(token: &str) -> Option<admin::Model> {
ADMIN_TOKEN_CACHE.get(token).await
}

pub struct AdminTokenInfo(pub admin::Model);

#[async_trait]
impl<S> FromRequestParts<S> for AdminTokenInfo
where S: Send + Sync {
type Rejection = ErrorMessage;

async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let headers = &parts.headers;
let token = headers.get("token")
.ok_or(ErrorMessage::InvalidToken)?
.to_str()
.map_err(|_| ErrorMessage::InvalidToken)?;
let user = get_admin_by_token(token).await
.ok_or(ErrorMessage::TokenNotActivated)?;

Ok(AdminTokenInfo(user))
}
}
17 changes: 17 additions & 0 deletions src/model/generated/admin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15
use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "admin")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: i32,
pub username: String,
pub disabled: bool,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}
1 change: 1 addition & 0 deletions src/model/generated/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod prelude;

pub mod admin;
pub mod answer;
pub mod page;
pub mod question;
Expand Down
2 changes: 1 addition & 1 deletion src/model/generated/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Model {
pub id: String,
pub title: String,
pub content: Vec<String>,
pub next: Option<i32>,
pub next: Option<String>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand Down
1 change: 1 addition & 0 deletions src/model/generated/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15
pub use super::admin::Entity as Admin;
pub use super::answer::Entity as Answer;
pub use super::page::Entity as Page;
pub use super::question::Entity as Question;
Expand Down
Loading

0 comments on commit 9054d2f

Please sign in to comment.