other: temp save
This commit is contained in:
parent
8f76e92804
commit
97b7bfb7fb
372
Cargo.lock
generated
372
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,11 @@ resolver = "2"
|
||||
|
||||
[patch.crates-io]
|
||||
testcontainers = { git = "https://github.com/testcontainers/testcontainers-rs.git", rev = "af21727" }
|
||||
loco-rs = { git = "https://github.com/lonelyhentxi/loco.git", rev = "beb890e" }
|
||||
# loco-rs = { git = "https://github.com/lonelyhentxi/loco.git", rev = "beb890e" }
|
||||
# loco-rs = { git = "https://github.com/loco-rs/loco.git" }
|
||||
async-graphql = { git = "https://github.com/aumetra/async-graphql.git", rev = "690ece7" }
|
||||
async-graphql-axum = { git = "https://github.com/aumetra/async-graphql.git", rev = "690ece7" }
|
||||
jwt-authorizer = { git = "https://github.com/blablacio/jwt-authorizer.git", rev = "e956774" }
|
||||
|
||||
# [patch."https://github.com/lonelyhentxi/qbit.git"]
|
||||
# qbit-rs = { path = "./patches/qbit-rs" }
|
||||
|
@ -1,2 +1,2 @@
|
||||
^https://konobangu.com/*** http://127.0.0.1:5000/$1
|
||||
^wss://konobangu.com/*** ws://127.0.0.1:5000/$1
|
||||
^https://konobangu.com/*** http://127.0.0.1:5000/$1 excludeFilter://^https://konobangu.com/api/***
|
||||
^wss://konobangu.com/*** ws://127.0.0.1:5000/$1 ^excludeFilter://^wss://konobangu.com/api/***
|
@ -1 +1 @@
|
||||
^https://recorder.konobangu.com/*** http://127.0.0.1:7600/$1
|
||||
^https://konobangu.com/api/*** http://127.0.0.1:5001/api/$1
|
@ -22,7 +22,7 @@ testcontainers = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
loco-rs = { version = "0.13" }
|
||||
loco-rs = { version = "0.14" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1.42", features = ["macros", "fs", "rt-multi-thread"] }
|
||||
@ -42,7 +42,13 @@ axum = "0.8"
|
||||
uuid = { version = "1.6.0", features = ["v4"] }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
||||
sea-orm-migration = { version = "1", features = ["runtime-tokio-rustls"] }
|
||||
reqwest = { version = "0.12.9" }
|
||||
reqwest = { version = "0.12", features = [
|
||||
"charset",
|
||||
"http2",
|
||||
"json",
|
||||
"macos-system-configuration",
|
||||
"rustls-tls",
|
||||
] }
|
||||
thiserror = "2"
|
||||
rss = "2"
|
||||
bytes = "1.9"
|
||||
@ -91,8 +97,10 @@ fastrand = "2.3.0"
|
||||
seaography = "1.1.2"
|
||||
quirks_path = "0.1.0"
|
||||
base64 = "0.22.1"
|
||||
tower = "0.5.2"
|
||||
axum-extra = "0.10.0"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "3"
|
||||
loco-rs = { version = "0.13", features = ["testing"] }
|
||||
loco-rs = { version = "0.14", features = ["testing"] }
|
||||
insta = { version = "1", features = ["redactions", "yaml", "filters"] }
|
||||
|
@ -13,10 +13,9 @@ use loco_rs::{
|
||||
task::Tasks,
|
||||
Result,
|
||||
};
|
||||
use sea_orm::DatabaseConnection;
|
||||
|
||||
use crate::{
|
||||
auth::service::AppAuthService,
|
||||
auth::service::{AppAuthService, AppAuthServiceInitializer},
|
||||
controllers::{self},
|
||||
dal::{AppDalClient, AppDalInitalizer},
|
||||
extract::mikan::{client::AppMikanClientInitializer, AppMikanClient},
|
||||
@ -75,6 +74,7 @@ impl Hooks for App {
|
||||
Box::new(AppDalInitalizer),
|
||||
Box::new(AppMikanClientInitializer),
|
||||
Box::new(AppGraphQLServiceInitializer),
|
||||
Box::new(AppAuthServiceInitializer),
|
||||
];
|
||||
|
||||
Ok(initializers)
|
||||
@ -101,8 +101,8 @@ impl Hooks for App {
|
||||
fn routes(ctx: &AppContext) -> AppRoutes {
|
||||
AppRoutes::with_default_routes()
|
||||
.prefix("/api")
|
||||
.add_route(controllers::subscribers::routes())
|
||||
.add_route(controllers::graphql::routes(ctx.get_graphql_service()))
|
||||
.add_route(controllers::auth::routes())
|
||||
.add_route(controllers::graphql::routes(ctx.clone()))
|
||||
}
|
||||
|
||||
async fn connect_workers(ctx: &AppContext, queue: &Queue) -> Result<()> {
|
||||
@ -119,12 +119,12 @@ impl Hooks for App {
|
||||
|
||||
fn register_tasks(_tasks: &mut Tasks) {}
|
||||
|
||||
async fn truncate(db: &DatabaseConnection) -> Result<()> {
|
||||
truncate_table(db, subscribers::Entity).await?;
|
||||
async fn truncate(ctx: &AppContext) -> Result<()> {
|
||||
truncate_table(&ctx.db, subscribers::Entity).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn seed(_db: &DatabaseConnection, _base: &Path) -> Result<()> {
|
||||
async fn seed(_ctx: &AppContext, _base: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response},
|
||||
Json,
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
@ -30,6 +31,6 @@ pub enum AuthError {
|
||||
|
||||
impl IntoResponse for AuthError {
|
||||
fn into_response(self) -> Response {
|
||||
(StatusCode::UNAUTHORIZED, self.to_string()).into_response()
|
||||
(StatusCode::UNAUTHORIZED, Json(self.to_string())).into_response()
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ use axum::{
|
||||
extract::FromRequestParts,
|
||||
http::request::Parts,
|
||||
response::{IntoResponse as _, Response},
|
||||
Extension,
|
||||
};
|
||||
use jwt_authorizer::{JwtAuthorizer, Validation};
|
||||
use loco_rs::app::{AppContext, Initializer};
|
||||
@ -22,21 +21,17 @@ pub struct AuthUserInfo {
|
||||
pub auth_type: AuthType,
|
||||
}
|
||||
|
||||
impl<S> FromRequestParts<S> for AuthUserInfo
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
impl FromRequestParts<AppContext> for AuthUserInfo {
|
||||
type Rejection = Response;
|
||||
|
||||
async fn from_request_parts(req: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||
let Extension(ctx) = Extension::<AppContext>::from_request_parts(req, state)
|
||||
.await
|
||||
.expect("AppContext should be present");
|
||||
|
||||
let auth_service = ctx.get_auth_service();
|
||||
async fn from_request_parts(
|
||||
parts: &mut Parts,
|
||||
state: &AppContext,
|
||||
) -> Result<Self, Self::Rejection> {
|
||||
let auth_service = state.get_auth_service();
|
||||
|
||||
auth_service
|
||||
.extract_user_info(req)
|
||||
.extract_user_info(parts)
|
||||
.await
|
||||
.map_err(|err| err.into_response())
|
||||
}
|
||||
|
@ -1,25 +1,40 @@
|
||||
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
|
||||
use async_graphql_axum::GraphQL;
|
||||
use async_graphql_axum::{GraphQLRequest, GraphQLResponse};
|
||||
use axum::{
|
||||
extract::State,
|
||||
middleware::from_extractor_with_state,
|
||||
response::{Html, IntoResponse},
|
||||
routing::{get, post_service},
|
||||
routing::{get, post},
|
||||
};
|
||||
use loco_rs::prelude::Routes;
|
||||
use loco_rs::{app::AppContext, prelude::Routes};
|
||||
|
||||
use crate::graphql::service::AppGraphQLService;
|
||||
use crate::{app::AppContextExt, auth::AuthUserInfo};
|
||||
|
||||
pub async fn graphql_playground() -> impl IntoResponse {
|
||||
async fn graphql_playground() -> impl IntoResponse {
|
||||
Html(playground_source(GraphQLPlaygroundConfig::new(
|
||||
"/api/graphql",
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn routes(graphql_service: &AppGraphQLService) -> Routes {
|
||||
async fn graphql_handler(
|
||||
State(ctx): State<AppContext>,
|
||||
auth_user_info: AuthUserInfo,
|
||||
req: GraphQLRequest,
|
||||
) -> GraphQLResponse {
|
||||
let graphql_service = ctx.get_graphql_service();
|
||||
let mut req = req.into_inner();
|
||||
req = req.data(auth_user_info);
|
||||
|
||||
graphql_service.schema.execute(req).await.into()
|
||||
}
|
||||
|
||||
pub fn routes(state: AppContext) -> Routes {
|
||||
Routes::new()
|
||||
.prefix("/graphql")
|
||||
.add("/playground", get(graphql_playground))
|
||||
.add(
|
||||
"/",
|
||||
post_service(GraphQL::new(graphql_service.schema.clone())),
|
||||
post(graphql_handler)
|
||||
.layer(from_extractor_with_state::<AuthUserInfo, AppContext>(state)),
|
||||
)
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod auth;
|
||||
pub mod graphql;
|
||||
pub mod subscribers;
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod config;
|
||||
pub mod query_root;
|
||||
pub mod service;
|
||||
pub mod config;
|
||||
|
||||
pub use query_root::schema;
|
||||
pub use query_root::schema;
|
||||
|
@ -2,7 +2,11 @@ use async_graphql::dynamic::*;
|
||||
use sea_orm::DatabaseConnection;
|
||||
use seaography::{Builder, BuilderContext};
|
||||
|
||||
lazy_static::lazy_static! { static ref CONTEXT : BuilderContext = BuilderContext :: default () ; }
|
||||
lazy_static::lazy_static! { static ref CONTEXT : BuilderContext = {
|
||||
BuilderContext {
|
||||
..Default::default()
|
||||
}
|
||||
}; }
|
||||
|
||||
pub fn schema(
|
||||
database: DatabaseConnection,
|
||||
@ -34,6 +38,7 @@ pub fn schema(
|
||||
}
|
||||
|
||||
let schema = builder.schema_builder();
|
||||
|
||||
let schema = if let Some(depth) = depth {
|
||||
schema.limit_depth(depth)
|
||||
} else {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use async_graphql::SimpleObject;
|
||||
use async_trait::async_trait;
|
||||
use loco_rs::app::AppContext;
|
||||
use sea_orm::{entity::prelude::*, sea_query::OnConflict, ActiveValue, FromJsonQueryResult};
|
||||
@ -5,13 +6,19 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::subscription_bangumi;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
|
||||
#[derive(
|
||||
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult, SimpleObject,
|
||||
)]
|
||||
#[graphql(name = "BangumiFilter")]
|
||||
pub struct BangumiFilter {
|
||||
pub name: Option<Vec<String>>,
|
||||
pub group: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
|
||||
#[derive(
|
||||
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult, SimpleObject,
|
||||
)]
|
||||
#[graphql(name = "BangumiExtra")]
|
||||
pub struct BangumiExtra {
|
||||
pub name_zh: Option<String>,
|
||||
pub s_name_zh: Option<String>,
|
||||
@ -21,14 +28,16 @@ pub struct BangumiExtra {
|
||||
pub s_name_jp: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize, SimpleObject)]
|
||||
#[sea_orm(table_name = "bangumi")]
|
||||
#[graphql(name = "Bangumi")]
|
||||
pub struct Model {
|
||||
pub created_at: DateTime,
|
||||
pub updated_at: DateTime,
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
pub mikan_bangumi_id: Option<String>,
|
||||
#[graphql(default_with = "default_subscriber_id")]
|
||||
pub subscriber_id: i32,
|
||||
pub display_name: String,
|
||||
pub raw_name: String,
|
||||
|
@ -1,3 +1,4 @@
|
||||
use async_graphql::SimpleObject;
|
||||
use async_trait::async_trait;
|
||||
use loco_rs::{
|
||||
app::AppContext,
|
||||
@ -8,7 +9,9 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const SEED_SUBSCRIBER: &str = "konobangu";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
|
||||
#[derive(
|
||||
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult, SimpleObject,
|
||||
)]
|
||||
pub struct SubscriberBangumiConfig {
|
||||
pub leading_group_tag: Option<bool>,
|
||||
}
|
||||
@ -104,11 +107,6 @@ impl ActiveModelBehavior for ActiveModel {
|
||||
}
|
||||
|
||||
impl Model {
|
||||
/// finds a user by the provided pid
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When could not find user or DB query error
|
||||
pub async fn find_by_pid(ctx: &AppContext, pid: &str) -> ModelResult<Self> {
|
||||
let db = &ctx.db;
|
||||
let parse_uuid = Uuid::parse_str(pid).map_err(|e| ModelError::Any(e.into()))?;
|
||||
@ -148,12 +146,6 @@ impl Model {
|
||||
Self::find_by_pid(ctx, SEED_SUBSCRIBER).await
|
||||
}
|
||||
|
||||
/// Asynchronously creates a user with a password and saves it to the
|
||||
/// database.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// When could not save the user into the DB
|
||||
pub async fn create_root(ctx: &AppContext) -> ModelResult<Self> {
|
||||
let db = &ctx.db;
|
||||
let txn = db.begin().await?;
|
||||
|
Loading…
Reference in New Issue
Block a user