diff --git a/src/pages/dash/gitea/add.rs b/src/pages/dash/gitea/add.rs new file mode 100644 index 0000000..779a426 --- /dev/null +++ b/src/pages/dash/gitea/add.rs @@ -0,0 +1,193 @@ +/* + * 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 . + */ +use std::cell::RefCell; + +use actix_identity::Identity; +use actix_web::http::header::ContentType; +use tera::Context; +use tracing::info; + +use super::get_auth_middleware; +use crate::api::v1::gitea::AddWebhook; +use crate::pages::errors::*; +use crate::settings::Settings; +use crate::AppCtx; + +pub use super::*; + +pub const DASH_GITEA_WEBHOOK_ADD: TemplateFile = + TemplateFile::new("dash_gitea_webhook_add", "pages/dash/gitea/add.html"); + +pub struct Add { + ctx: RefCell, +} + +impl CtxError for Add { + fn with_error(&self, e: &ReadableError) -> String { + self.ctx.borrow_mut().insert(ERROR_KEY, e); + self.render() + } +} + +impl Add { + pub fn new(settings: &Settings) -> Self { + let ctx = RefCell::new(context(settings)); + Self { ctx } + } + + pub fn render(&self) -> String { + TEMPLATES + .render(DASH_GITEA_WEBHOOK_ADD.name, &self.ctx.borrow()) + .unwrap() + } +} + +#[actix_web_codegen_const_routes::get( + path = "PAGES.dash.gitea_webhook.add", + wrap = "get_auth_middleware()" +)] +#[tracing::instrument(name = "Dashboard add gitea webhook webpage", skip(ctx))] +pub async fn get_add_gitea_webhook(ctx: AppCtx) -> PageResult { + let add = Add::new(&ctx.settings).render(); + let html = ContentType::html(); + Ok(HttpResponse::Ok().content_type(html).body(add)) +} + +#[actix_web_codegen_const_routes::post( + path = "PAGES.dash.gitea_webhook.add", + wrap = "get_auth_middleware()" +)] +#[tracing::instrument( + name = "Post Dashboard add Gitea webhook webpage", + skip(ctx, id, payload) +)] +pub async fn post_add_gitea_webhook( + ctx: AppCtx, + id: Identity, + payload: web::Form, +) -> PageResult { + let owner = id.identity().unwrap(); + let payload = payload.into_inner(); + + info!( + "Adding webhook for Gitea instance: {}", + payload.gitea_url.as_str() + ); + let hook = ctx + .db + .new_webhook(payload.gitea_url, &owner) + .await + .map_err(|e| PageError::new(Add::new(&ctx.settings), e))?; + + Ok(HttpResponse::Found() + .append_header(( + http::header::LOCATION, + PAGES.dash.gitea_webhook.get_view(&hook.auth_token), + )) + .finish()) +} + +pub fn services(cfg: &mut web::ServiceConfig) { + cfg.service(get_add_gitea_webhook); + cfg.service(post_add_gitea_webhook); +} + +#[cfg(test)] +mod tests { + use actix_web::http::StatusCode; + use actix_web::test; + use url::Url; + + use crate::api::v1::gitea::AddWebhook; + use crate::ctx::ArcCtx; + use crate::tests; + use crate::*; + + use super::PAGES; + + #[actix_rt::test] + async fn postgres_dashboadr_add_gitea_webhook_works() { + let (_, ctx) = tests::get_ctx().await; + dashboadr_add_gitea_webhook_works(ctx.clone()).await; + } + + async fn dashboadr_add_gitea_webhook_works(ctx: ArcCtx) { + const NAME: &str = "testdashwebhookgiteaadduser"; + const EMAIL: &str = "testdashwebhookgiteaadduser@foo.com"; + const PASSWORD: &str = "longpassword"; + + let _ = ctx.delete_user(NAME, PASSWORD).await; + let (_, signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await; + let cookies = get_cookie!(signin_resp); + let app = get_app!(ctx.clone()).await; + + let resp = get_request!(&app, PAGES.dash.gitea_webhook.add, cookies.clone()); + assert_eq!(resp.status(), StatusCode::OK); + let res = String::from_utf8(test::read_body(resp).await.to_vec()).unwrap(); + assert!(res.contains("Add Gitea Webhook")); + + let payload = AddWebhook { + gitea_url: Url::parse("https://git.batsense.net").unwrap(), + }; + + let add_webhook = test::call_service( + &app, + post_request!(&payload, PAGES.dash.gitea_webhook.add, FORM) + .cookie(cookies.clone()) + .to_request(), + ) + .await; + assert_eq!(add_webhook.status(), StatusCode::FOUND); + + let mut hooks = ctx.db.list_all_webhooks_with_owner(NAME).await.unwrap(); + let hook = hooks.pop().unwrap(); + + // let mut event = ctx.db.list(&site.hostname).await.unwrap(); + // let event = event.pop().unwrap(); + + let headers = add_webhook.headers(); + let view_webhook_url = PAGES.dash.gitea_webhook.get_view(&hook.auth_token); + assert_eq!( + headers.get(actix_web::http::header::LOCATION).unwrap(), + &view_webhook_url + ); + + // list webhooks + let resp = get_request!(&app, PAGES.dash.gitea_webhook.list, cookies.clone()); + assert_eq!(resp.status(), StatusCode::OK); + let res = String::from_utf8(test::read_body(resp).await.to_vec()).unwrap(); + assert!(res.contains(&hook.gitea_url.as_str())); + + // view webhook + let resp = get_request!(&app, &view_webhook_url, cookies.clone()); + assert_eq!(resp.status(), StatusCode::OK); + let res = String::from_utf8(test::read_body(resp).await.to_vec()).unwrap(); + assert!(res.contains("****")); + assert!(res.contains( + &crate::V1_API_ROUTES + .gitea + .get_webhook_url(&ctx, &hook.auth_token) + )); + + let show_gitea_webhook_secret = + format!("{view_webhook_url}?show_gitea_webhook_secret=true"); + let resp = get_request!(&app, &show_gitea_webhook_secret, cookies.clone()); + assert_eq!(resp.status(), StatusCode::OK); + let res = String::from_utf8(test::read_body(resp).await.to_vec()).unwrap(); + assert!(res.contains(&hook.gitea_webhook_secret)); + } +} diff --git a/src/pages/dash/gitea/mod.rs b/src/pages/dash/gitea/mod.rs new file mode 100644 index 0000000..3cc51cc --- /dev/null +++ b/src/pages/dash/gitea/mod.rs @@ -0,0 +1,69 @@ +/* + * 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 . + */ +use actix_web::*; +use serde::{Deserialize, Serialize}; + +use super::get_auth_middleware; +pub use super::home::TemplateSite; +pub use super::{context, Footer, TemplateFile, PAGES, PAYLOAD_KEY, TEMPLATES}; + +use crate::ctx::Ctx; +use crate::db::GiteaWebhook; + +pub mod add; +pub mod list; +pub mod view; + +pub fn register_templates(t: &mut tera::Tera) { + add::DASH_GITEA_WEBHOOK_ADD + .register(t) + .expect(add::DASH_GITEA_WEBHOOK_ADD.name); + list::DASH_GITEA_WEBHOOK_LIST + .register(t) + .expect(list::DASH_GITEA_WEBHOOK_LIST.name); + + view::DASH_GITEA_WEBHOOK_VIEW + .register(t) + .expect(view::DASH_GITEA_WEBHOOK_VIEW.name); +} + +pub fn services(cfg: &mut web::ServiceConfig) { + add::services(cfg); + list::services(cfg); + view::services(cfg); +} + +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +pub struct TemplateGiteaWebhook { + pub webhook: GiteaWebhook, + pub view: String, + pub url: String, +} + +impl TemplateGiteaWebhook { + pub fn new(ctx: &Ctx, hook: GiteaWebhook) -> Self { + let view = PAGES.dash.gitea_webhook.get_view(&hook.auth_token); + let url = crate::V1_API_ROUTES + .gitea + .get_webhook_url(ctx, &hook.auth_token); + Self { + webhook: hook, + view, + url, + } + } +} diff --git a/templates/pages/dash/gitea/add.html b/templates/pages/dash/gitea/add.html new file mode 100644 index 0000000..c07d9da --- /dev/null +++ b/templates/pages/dash/gitea/add.html @@ -0,0 +1,23 @@ +{% extends 'base' %}{% block title %} Add Gitea Webhook{% endblock title %} {% block nav +%} {% include "auth_nav" %} {% endblock nav %} {% block main %} + +
+
+
+ +
+ +
+
+
+
+ +{% endblock main %}