some quick documentation

This commit is contained in:
Sebastian Hugentobler 2024-07-10 14:48:42 +02:00
parent 8d297920fb
commit 87cfccb4f7
Signed by: shu
GPG Key ID: BB32CF3CA052C2F0
6 changed files with 40 additions and 0 deletions

View File

@ -1,3 +1,5 @@
//! Koreader Progress Sync API.
use poem::{
error::ResponseError,
http::StatusCode,
@ -19,17 +21,20 @@ use crate::{
error_response,
};
/// Data for registering a new user.
#[derive(Object, Deserialize)]
struct RegisterRequest {
username: String,
password: String,
}
/// Answer after registering a new user.
#[derive(Object, Serialize)]
struct UserCreated {
username: String,
}
/// Datafor pushing progress.
#[derive(Debug, Clone, Object, Deserialize)]
pub struct DocumentUpdate {
pub device: String,
@ -39,6 +44,7 @@ pub struct DocumentUpdate {
pub progress: String,
}
/// Answer when pulling progress.
#[derive(Debug, Clone, Object, Deserialize)]
pub struct DocumentProgress {
pub device: String,
@ -70,6 +76,9 @@ pub struct Api;
#[OpenApi]
impl Api {
/// Register a new user.
///
/// If a user of that id already exist, return a conflict.
#[oai(path = "/users/create", method = "post")]
async fn register(
&self,
@ -88,11 +97,13 @@ impl Api {
}
}
/// Return OK if a user authenticated successfully.
#[oai(path = "/users/auth", method = "get", transform = "authorize")]
async fn login(&self) -> Result<payload::Response<()>> {
Ok(payload::Response::new(()).status(StatusCode::OK))
}
/// Push new progress.
#[oai(path = "/syncs/progress", method = "put", transform = "authorize")]
async fn push_progress(
&self,
@ -108,6 +119,7 @@ impl Api {
Ok(payload::Response::new(()).status(StatusCode::OK))
}
/// Pull progress for document with id `doc_id`.
#[oai(
path = "/syncs/progress/:doc_id",
method = "get",

View File

@ -1,6 +1,10 @@
//! Global application state.
use crate::{cli::Config, db::Db};
pub struct AppState {
/// Application configuration.
pub config: Config,
/// Database connection.
pub db: Db,
}

View File

@ -1,3 +1,9 @@
//! Poem middleware for koreader progress sync authentication.
//!
//! Authentication works with two headers:
//! - x-auth-user: username
//! - x-auth-key: md5 hashed password
use poem::{
error::ResponseError, http::StatusCode, Endpoint, EndpointExt, Error, Middleware, Request,
Result,

View File

@ -1,3 +1,5 @@
//! Data access and persistence.
use ::entity::{document, user};
use migration::{Migrator, MigratorTrait};
use sea_orm::{
@ -16,6 +18,7 @@ pub enum DataStoreError {
DatabaseError(#[from] DbErr),
}
/// Document progress to insert/update.
#[derive(Debug)]
pub struct DocumentInsert {
id: String,
@ -44,6 +47,7 @@ pub struct Db {
}
impl Db {
/// Add a new user and return an error if one with `id` already exists.
pub async fn add_user(&self, id: &str, key: &str) -> Result<user::Model, DataStoreError> {
let user = user::ActiveModel {
id: Set(id.to_owned()),
@ -53,10 +57,13 @@ impl Db {
Ok(user.insert(&self.connection).await?)
}
/// Get user with id `id` or None if they do not exist.
pub async fn get_user(&self, id: &str) -> Result<Option<user::Model>, DataStoreError> {
Ok(user::Entity::find_by_id(id).one(&self.connection).await?)
}
/// Get the progress for document with id `doc_id` from user with id `user_id` or None if that
/// combination does not exist.
pub async fn get_position(
&self,
user_id: &str,
@ -69,6 +76,9 @@ impl Db {
.await?)
}
/// Update progress for document with id `doc_id` from user with id `user_id`.
///
/// Set the progress timestamp to now.
pub async fn update_position(&self, doc: &DocumentInsert) -> Result<(), DataStoreError> {
let now = OffsetDateTime::now_utc();
let now = PrimitiveDateTime::new(now.date(), now.time());
@ -93,6 +103,7 @@ impl Db {
}
}
/// Connect to the database and return the opened connectoin pool.
pub async fn connect(connection_string: &str) -> Result<Db, DataStoreError> {
let connection: DatabaseConnection = Database::connect(connection_string).await?;
Migrator::up(&connection, None).await?;

View File

@ -1,3 +1,5 @@
//! Error handling for the sync service.
use poem::{http::StatusCode, Body, Response};
use poem_openapi::Object;
use serde::Serialize;
@ -11,6 +13,8 @@ struct ErrorResponse {
message: String,
}
/// Log `error` on the server side with a generated id and send back a sanitized error message with
/// the same id.
pub fn create_and_log<F>(error: impl Error, cb: F) -> Response
where
F: Fn() -> (String, StatusCode),

View File

@ -1,3 +1,5 @@
//! Implementation of a koreader progress sync server.
use anyhow::Result;
use api::Api;
use app_state::AppState;
@ -18,6 +20,7 @@ pub mod cli;
pub mod db;
pub mod error_response;
/// Run the progress sync server.
pub async fn run(args: &Config, db_url: &str) -> Result<()> {
let db = db::connect(db_url).await?;
let app_state = Arc::new(AppState {