From 2b9fcd2729c41a86a82d135ac2ee61d2f48bcc34 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Thu, 29 Dec 2022 16:40:19 +0530 Subject: [PATCH] feat: read and delete form submissions with authentication --- Cargo.lock | 10 +++ Cargo.toml | 1 + src/ctx/api/v1/forms.rs | 147 ++++++++++++++++++++++++++++++++++++++++ src/ctx/api/v1/mod.rs | 1 + 4 files changed, 159 insertions(+) create mode 100644 src/ctx/api/v1/forms.rs diff --git a/Cargo.lock b/Cargo.lock index 38ad22e..ca21040 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,6 +1418,15 @@ dependencies = [ "serde", ] +[[package]] +name = "libforms" +version = "0.1.0" +source = "git+https://git.batsense.net/librepages/forms/#7e50f9be0db184b1b9c551912137ad63106d64ce" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "libgit2-sys" version = "0.13.4+1.4.2" @@ -1454,6 +1463,7 @@ dependencies = [ "lazy_static", "libconductor", "libconfig", + "libforms", "mime", "mime_guess", "mktemp", diff --git a/Cargo.toml b/Cargo.toml index 5ac3ad2..17f7984 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ sqlx = { version = "0.6.2", features = ["runtime-actix-rustls", "postgres", "tim clap = { version = "3.2.20", features = ["derive"]} libconfig = { version = "0.1.0", git = "https://git.batsense.net/librepages/libconfig" } libconductor = { version = "0.1.0", git = "https://git.batsense.net/librepages/conductor/" } +libforms = { version = "0.1.0", git = "https://git.batsense.net/librepages/forms/" } config = "0.13" git2 = "0.14.2" diff --git a/src/ctx/api/v1/forms.rs b/src/ctx/api/v1/forms.rs new file mode 100644 index 0000000..60302ce --- /dev/null +++ b/src/ctx/api/v1/forms.rs @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +//! Account management utility datastructures and methods +use libforms::*; + +pub use super::auth; +use crate::ctx::Ctx; +use crate::errors::*; + +impl Ctx { + /// Delete form submission + pub async fn delete_form_submission( + &self, + owner: &str, + sub_id: usize, + payload: &Table, + ) -> ServiceResult<()> { + let _site = self.db.get_site(owner, &payload.host).await?; + let mut form_url = self.settings.form.url.clone(); + form_url.set_path(&format!("/api/v1/forms/delete/{sub_id}")); + self.client + .post(form_url) + .bearer_auth(&self.settings.form.api_key) + .json(payload) + .send() + .await + .unwrap(); + Ok(()) + } + + /// Delete form submission + pub async fn get_all_form_submission( + &self, + owner: &str, + page: usize, + payload: &Table, + ) -> ServiceResult> { + let _site = self.db.get_site(owner, &payload.host).await?; + let mut form_url = self.settings.form.url.clone(); + form_url.set_path("/api/v1/forms/list"); + form_url.set_query(Some(&format!("page={}", page))); + + let res = self + .client + .post(form_url) + .bearer_auth(&self.settings.form.api_key) + .json(payload) + .send() + .await + .unwrap(); + + println!("{:?}", res); + let res = res.json().await.unwrap(); + Ok(res) + } +} + +#[cfg(test)] +mod tests { + use actix_web::{http::StatusCode, test}; + + use crate::tests; + use crate::*; + + use super::*; + + impl Ctx { + /// Delete form submission + pub async fn add_form_submission( + &self, + owner: &str, + site_info: &Table, + payload: &serde_json::Value, + ) -> ServiceResult<()> { + let _site = self.db.get_site(owner, &site_info.host).await?; + let mut form_url = self.settings.form.url.clone(); + form_url.set_path("/api/v1/forms/submit"); + form_url.set_query(Some(&format!( + "host={}&path={}", + site_info.host, site_info.path + ))); + self.client + .post(form_url) + .json(payload) + .send() + .await + .unwrap(); + Ok(()) + } + } + + #[actix_rt::test] + async fn test_ctx_forms_work() { + const NAME: &str = "testctxformswork"; + const PASSWORD: &str = "longpasswordasdfa2"; + const EMAIL: &str = "testctxformswork@a.com"; + + let (_dir, ctx) = tests::get_ctx().await; + let _ = ctx.delete_user(NAME, PASSWORD).await; + let (_, _signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await; + let page = ctx.add_test_site(NAME.into()).await; + let site_info = Table { + host: page.domain.clone(), + path: format!("/foo/{NAME}"), + }; + + if let Ok(subs) = ctx.get_all_form_submission(NAME, 0, &site_info).await { + for s in subs.iter() { + let _ = ctx.delete_form_submission(NAME, s.id, &site_info).await; + } + } + ctx.add_form_submission(NAME, &site_info, &serde_json::to_value(&site_info).unwrap()) + .await + .unwrap(); + let subs = ctx + .get_all_form_submission(NAME, 0, &site_info) + .await + .unwrap(); + assert_eq!(subs.len(), 1); + assert_eq!( + subs[0].value, + Some(serde_json::to_value(&site_info).unwrap()) + ); + ctx.delete_form_submission(NAME, subs[0].id, &site_info) + .await + .unwrap(); + let subs = ctx + .get_all_form_submission(NAME, 0, &site_info) + .await + .unwrap(); + assert!(subs.is_empty()); + } +} diff --git a/src/ctx/api/v1/mod.rs b/src/ctx/api/v1/mod.rs index abc7bf1..fa713ef 100644 --- a/src/ctx/api/v1/mod.rs +++ b/src/ctx/api/v1/mod.rs @@ -17,6 +17,7 @@ pub mod account; pub mod auth; pub mod forgejo; +pub mod forms; pub mod pages; #[cfg(test)]