Compare commits
No commits in common. "8a627243345e6d69277a2ebb33402ed5b4c56cb1" and "bab52687c7619f3ab67c1ab61c726a6a89f20326" have entirely different histories.
8a62724334
...
bab52687c7
12 changed files with 1 additions and 373 deletions
92
koucha/Cargo.lock
generated
92
koucha/Cargo.lock
generated
|
|
@ -73,70 +73,6 @@ dependencies = [
|
||||||
"fs_extra",
|
"fs_extra",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum"
|
|
||||||
version = "0.8.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
|
|
||||||
dependencies = [
|
|
||||||
"axum-core",
|
|
||||||
"axum-macros",
|
|
||||||
"bytes",
|
|
||||||
"form_urlencoded",
|
|
||||||
"futures-util",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"http-body-util",
|
|
||||||
"hyper",
|
|
||||||
"hyper-util",
|
|
||||||
"itoa",
|
|
||||||
"matchit",
|
|
||||||
"memchr",
|
|
||||||
"mime",
|
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
|
||||||
"serde_core",
|
|
||||||
"serde_json",
|
|
||||||
"serde_path_to_error",
|
|
||||||
"serde_urlencoded",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tokio",
|
|
||||||
"tower",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum-core"
|
|
||||||
version = "0.5.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-core",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"http-body-util",
|
|
||||||
"mime",
|
|
||||||
"pin-project-lite",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum-macros"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
|
|
@ -790,12 +726,6 @@ version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "httpdate"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
|
@ -810,7 +740,6 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
|
|
@ -1070,12 +999,9 @@ dependencies = [
|
||||||
name = "koucha"
|
name = "koucha"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
|
||||||
"chrono",
|
"chrono",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rss",
|
"rss",
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
@ -1150,12 +1076,6 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "matchit"
|
|
||||||
version = "0.8.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
|
@ -1788,17 +1708,6 @@ dependencies = [
|
||||||
"zmij",
|
"zmij",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_path_to_error"
|
|
||||||
version = "0.1.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"serde",
|
|
||||||
"serde_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
|
@ -2312,7 +2221,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,3 @@ rss = "2.0.12"
|
||||||
tokio = { version = "1.49.0", features = ["full"] }
|
tokio = { version = "1.49.0", features = ["full"] }
|
||||||
sqlx = { version = "0.8.6", features = [ "runtime-tokio", "sqlite" ] }
|
sqlx = { version = "0.8.6", features = [ "runtime-tokio", "sqlite" ] }
|
||||||
chrono = "0.4.43"
|
chrono = "0.4.43"
|
||||||
axum = { version= "0.8.8", features = [ "macros" ] }
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0.149"
|
|
||||||
|
|
|
||||||
0
koucha/src/bin/server.rs
Normal file
0
koucha/src/bin/server.rs
Normal file
|
|
@ -1,43 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use koucha::{
|
|
||||||
Adapter, AdapterBuilder, db::{User, UserKey as DbUserKey}
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::types::UserKey;
|
|
||||||
|
|
||||||
mod routes;
|
|
||||||
mod types;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct AppState {
|
|
||||||
pub adapter: Adapter,
|
|
||||||
// TODO: Set up UserKey expirations
|
|
||||||
auth_map: HashMap<UserKey, DbUserKey>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppState {
|
|
||||||
fn create_user_key(&mut self, db_user_key: DbUserKey) -> UserKey {
|
|
||||||
let key = UserKey::new();
|
|
||||||
self.auth_map.insert(key.clone(), db_user_key);
|
|
||||||
key
|
|
||||||
}
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn user_from_key(&self, key: &UserKey) -> Option<DbUserKey> {
|
|
||||||
self.auth_map.get(key).map(DbUserKey::clone)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
let db_url = std::env::var("DATABASE_URL").unwrap();
|
|
||||||
let adapter = AdapterBuilder::new()
|
|
||||||
.database_url(&db_url)
|
|
||||||
.create().await.unwrap();
|
|
||||||
let auth_map = HashMap::new();
|
|
||||||
|
|
||||||
let app = routes::router().with_state(AppState { adapter, auth_map });
|
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:4142").await.unwrap();
|
|
||||||
axum::serve(listener, app).await.unwrap();
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
use axum::{Json, extract::State};
|
|
||||||
use koucha::db::User as DbUser;
|
|
||||||
use reqwest::StatusCode;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
AppState, routes::{ApiError, ApiResult, ApiResponse}, types::UserKey
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct Input {
|
|
||||||
pub user_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Output {
|
|
||||||
user_key: UserKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handler(
|
|
||||||
State(mut state): State<AppState>,
|
|
||||||
Json(body): Json<Input>,
|
|
||||||
) -> ApiResult<Output> {
|
|
||||||
let dbuser = DbUser::temporary_auth(
|
|
||||||
state.adapter.get_pool(),
|
|
||||||
&body.user_name
|
|
||||||
).await.map_err(|_e| {
|
|
||||||
// TODO: Logging
|
|
||||||
ApiError {
|
|
||||||
status: StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
error: "InternalError",
|
|
||||||
message: String::from(
|
|
||||||
"Error authentiating user ".to_owned() + &body.user_name
|
|
||||||
),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let key = state.create_user_key(dbuser.key());
|
|
||||||
|
|
||||||
Ok(ApiResponse(StatusCode::OK, Output { user_key: key }))
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
use axum::{Json, extract::State, http::HeaderMap};
|
|
||||||
use koucha::db::User as DbUser;
|
|
||||||
use reqwest::StatusCode;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
AppState, routes::{ApiError, ApiResult, ApiResponse}, types::User
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct Input { }
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Output {
|
|
||||||
users: Vec<User>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handler(
|
|
||||||
headers: HeaderMap,
|
|
||||||
State(state): State<AppState>,
|
|
||||||
Json(_body): Json<Input>,
|
|
||||||
) -> ApiResult<Output> {
|
|
||||||
let dbusers = DbUser::get_all(state.adapter.get_pool())
|
|
||||||
.await.map_err(|_e| {
|
|
||||||
// TODO: Logging
|
|
||||||
ApiError {
|
|
||||||
status: StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
error: "InternalError",
|
|
||||||
message: "Error getting all users from DB.".to_string(),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let users: Vec<User> = dbusers.iter().map(|u| User {
|
|
||||||
name: u.name().to_string(),
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
Ok(ApiResponse(StatusCode::OK, Output { users }))
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
use axum::{Json, extract::State};
|
|
||||||
use koucha::db::User as DbUser;
|
|
||||||
use reqwest::StatusCode;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
AppState, routes::{ApiError, ApiResult, ApiResponse}, types::User
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct Input { }
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Output {
|
|
||||||
users: Vec<User>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handler(
|
|
||||||
State(state): State<AppState>,
|
|
||||||
Json(_body): Json<Input>,
|
|
||||||
) -> ApiResult<Output> {
|
|
||||||
let dbusers = DbUser::get_all(state.adapter.get_pool())
|
|
||||||
.await.map_err(|_e| {
|
|
||||||
// TODO: Logging
|
|
||||||
ApiError {
|
|
||||||
status: StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
error: "InternalError",
|
|
||||||
message: "Error getting all users from DB.".to_string(),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let users: Vec<User> = dbusers.iter().map(|u| User {
|
|
||||||
name: u.name().to_string(),
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
Ok(ApiResponse(StatusCode::OK, Output { users }))
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
use serde::Serialize;
|
|
||||||
use serde_json::json;
|
|
||||||
use axum::{
|
|
||||||
Json,
|
|
||||||
Router,
|
|
||||||
response::IntoResponse,
|
|
||||||
routing::{
|
|
||||||
get,
|
|
||||||
post,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use reqwest::StatusCode;
|
|
||||||
|
|
||||||
mod get_feeds;
|
|
||||||
mod create_session;
|
|
||||||
mod get_users;
|
|
||||||
mod new_user;
|
|
||||||
|
|
||||||
use crate::AppState;
|
|
||||||
|
|
||||||
pub type ApiResult<T> = Result<ApiResponse<T>, ApiError>;
|
|
||||||
|
|
||||||
pub struct ApiResponse<T>(pub StatusCode, pub T);
|
|
||||||
|
|
||||||
pub struct ApiError {
|
|
||||||
pub status: StatusCode,
|
|
||||||
pub error: &'static str,
|
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn router() -> Router<AppState> {
|
|
||||||
Router::new()
|
|
||||||
.route("/create_session", post(create_session::handler))
|
|
||||||
.route("/get_feeds", get(get_feeds::handler))
|
|
||||||
.route("/get_users", get(get_users::handler))
|
|
||||||
.route("/new_user", post(new_user::handler))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoResponse for ApiError {
|
|
||||||
fn into_response(self) -> axum::response::Response {
|
|
||||||
let body = json!({ "error": self.error, "message": self.message });
|
|
||||||
(self.status, Json(body)).into_response()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: Serialize> IntoResponse for ApiResponse<T> {
|
|
||||||
fn into_response(self) -> axum::response::Response {
|
|
||||||
(self.0, Json(self.1)).into_response()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
use axum::{Json, extract::State};
|
|
||||||
use koucha::db::User as DbUser;
|
|
||||||
use reqwest::StatusCode;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
AppState, routes::{ApiError, ApiResult, ApiResponse}, types::User
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct Input {
|
|
||||||
user_name: String,
|
|
||||||
}
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Output {
|
|
||||||
user: User,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn handler(
|
|
||||||
State(state): State<AppState>,
|
|
||||||
Json(body): Json<Input>,
|
|
||||||
) -> ApiResult<Output> {
|
|
||||||
let dbuser = DbUser::create(
|
|
||||||
state.adapter.get_pool(),
|
|
||||||
&body.user_name
|
|
||||||
).await.map_err(|_e| {
|
|
||||||
// TODO: Logging
|
|
||||||
ApiError {
|
|
||||||
status: StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
error: "InternalError",
|
|
||||||
message: String::from(
|
|
||||||
"Error creating user ".to_owned() + &body.user_name
|
|
||||||
),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let user = User { name: dbuser.name().to_string() };
|
|
||||||
|
|
||||||
Ok(ApiResponse(StatusCode::OK, Output { user }))
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
use chrono::Utc;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct User {
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
||||||
pub struct UserKey(String);
|
|
||||||
impl UserKey {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
UserKey(
|
|
||||||
Utc::now().to_rfc3339()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -29,17 +29,6 @@ pub struct User {
|
||||||
impl User {
|
impl User {
|
||||||
pub fn key(&self) -> UserKey { self.key }
|
pub fn key(&self) -> UserKey { self.key }
|
||||||
pub fn name(&self) -> &str { &self.name }
|
pub fn name(&self) -> &str { &self.name }
|
||||||
|
|
||||||
pub async fn temporary_auth(
|
|
||||||
pool: &AdapterPool,
|
|
||||||
name: &str,
|
|
||||||
) -> Result<Self> {
|
|
||||||
sqlx::query_as!(
|
|
||||||
UnparsedUser,
|
|
||||||
"SELECT id as `id!`, name FROM users WHERE name = ?",
|
|
||||||
name
|
|
||||||
).fetch_one(&pool.0).await?.parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get(pool: &AdapterPool, key: UserKey) -> Result<Self> {
|
pub async fn get(pool: &AdapterPool, key: UserKey) -> Result<Self> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||||
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod fetch;
|
pub mod fetch;
|
||||||
|
|
@ -9,9 +9,7 @@ pub mod score;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test_utils;
|
pub mod test_utils;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct AdapterPool(sqlx::SqlitePool);
|
pub struct AdapterPool(sqlx::SqlitePool);
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct AdapterClient(reqwest::Client);
|
pub struct AdapterClient(reqwest::Client);
|
||||||
|
|
||||||
pub struct AdapterBuilder {
|
pub struct AdapterBuilder {
|
||||||
|
|
@ -40,7 +38,6 @@ impl AdapterBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Adapter {
|
pub struct Adapter {
|
||||||
db: AdapterPool,
|
db: AdapterPool,
|
||||||
client: AdapterClient,
|
client: AdapterClient,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue