aboutsummaryrefslogtreecommitdiff
path: root/server/src/api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/api.rs')
-rw-r--r--server/src/api.rs105
1 files changed, 105 insertions, 0 deletions
diff --git a/server/src/api.rs b/server/src/api.rs
new file mode 100644
index 0000000..f246eab
--- /dev/null
+++ b/server/src/api.rs
@@ -0,0 +1,105 @@
+/*
+ This file is part of jellything (https://codeberg.org/metamuffin/jellything)
+ which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
+ Copyright (C) 2025 metamuffin <metamuffin.org>
+*/
+use super::ui::{account::login_logic, error::MyResult};
+use crate::{
+ database::Database,
+ logic::session::{AdminSession, Session},
+};
+use jellybase::assetfed::AssetInner;
+use jellycommon::{user::CreateSessionParams, NodeID, Visibility};
+use rocket::{
+ get,
+ http::MediaType,
+ outcome::Outcome,
+ post,
+ request::{self, FromRequest},
+ response::Redirect,
+ serde::json::Json,
+ Request, State,
+};
+use serde_json::{json, Value};
+use std::ops::Deref;
+
+#[get("/api")]
+pub fn r_api_root() -> Redirect {
+ Redirect::moved("https://jellything.metamuffin.org/book/api.html#jellything-http-api")
+}
+
+#[get("/api/version")]
+pub fn r_api_version() -> &'static str {
+ env!("CARGO_PKG_VERSION")
+}
+
+#[post("/api/create_session", data = "<data>")]
+pub fn r_api_account_login(
+ database: &State<Database>,
+ data: Json<CreateSessionParams>,
+) -> MyResult<Value> {
+ let token = login_logic(
+ database,
+ &data.username,
+ &data.password,
+ data.expire,
+ data.drop_permissions.clone(),
+ )?;
+ Ok(json!(token))
+}
+
+#[get("/api/asset_token_raw/<token>")]
+pub fn r_api_asset_token_raw(_admin: AdminSession, token: &str) -> MyResult<Json<AssetInner>> {
+ Ok(Json(AssetInner::deser(token)?))
+}
+
+#[get("/api/nodes_modified?<since>")]
+pub fn r_api_nodes_modified_since(
+ _session: Session,
+ database: &State<Database>,
+ since: u64,
+) -> MyResult<Json<Vec<NodeID>>> {
+ let mut nodes = database.get_nodes_modified_since(since)?;
+ nodes.retain(|id| {
+ database.get_node(*id).is_ok_and(|n| {
+ n.as_ref()
+ .is_some_and(|n| n.visibility >= Visibility::Reduced)
+ })
+ });
+ Ok(Json(nodes))
+}
+
+pub struct AcceptJson(bool);
+impl Deref for AcceptJson {
+ type Target = bool;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<'r> FromRequest<'r> for AcceptJson {
+ type Error = ();
+
+ fn from_request<'life0, 'async_trait>(
+ request: &'r Request<'life0>,
+ ) -> ::core::pin::Pin<
+ Box<
+ dyn ::core::future::Future<Output = request::Outcome<Self, Self::Error>>
+ + ::core::marker::Send
+ + 'async_trait,
+ >,
+ >
+ where
+ 'r: 'async_trait,
+ 'life0: 'async_trait,
+ Self: 'async_trait,
+ {
+ Box::pin(async move {
+ Outcome::Success(AcceptJson(
+ request
+ .accept()
+ .map(|a| a.preferred().exact_eq(&MediaType::JSON))
+ .unwrap_or(false),
+ ))
+ })
+ }
+}