diff --git a/migrations/20221220010013_librepages_forgejo_webhooks.sql b/migrations/20221220010013_librepages_forgejo_webhooks.sql new file mode 100644 index 0000000..1b58a15 --- /dev/null +++ b/migrations/20221220010013_librepages_forgejo_webhooks.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS librepages_forgejo_webhooks ( + forgejo_webhook_secret VARCHAR(40) NOT NULL UNIQUE, + forgejo_url VARCHAR(3000) NOT NULL, + auth_token VARCHAR(40) NOT NULL UNIQUE, + ID SERIAL PRIMARY KEY NOT NULL, + owned_by INTEGER NOT NULL references librepages_users(ID) ON DELETE CASCADE +); + +CREATE UNIQUE INDEX librepages_forgejo_webhook_auth_token_index ON librepages_forgejo_webhooks(auth_token); + +CREATE TABLE IF NOT EXISTS librepages_forgejo_webhook_site_mapping ( + site_id INTEGER NOT NULL references librepages_sites(ID) ON DELETE CASCADE, + forgejo_webhook_id INTEGER NOT NULL references librepages_forgejo_webhooks(ID) ON DELETE CASCADE, + UNIQUE(site_id, forgejo_webhook_id) +); diff --git a/migrations/20221220010013_librepages_gitea_webhooks.sql b/migrations/20221220010013_librepages_gitea_webhooks.sql deleted file mode 100644 index 655f505..0000000 --- a/migrations/20221220010013_librepages_gitea_webhooks.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE TABLE IF NOT EXISTS librepages_gitea_webhooks ( - gitea_webhook_secret VARCHAR(40) NOT NULL UNIQUE, - gitea_url VARCHAR(3000) NOT NULL, - auth_token VARCHAR(40) NOT NULL UNIQUE, - ID SERIAL PRIMARY KEY NOT NULL, - owned_by INTEGER NOT NULL references librepages_users(ID) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX librepages_gitea_webhook_auth_token_index ON librepages_gitea_webhooks(auth_token); - -CREATE TABLE IF NOT EXISTS librepages_gitea_webhook_site_mapping ( - site_id INTEGER NOT NULL references librepages_sites(ID) ON DELETE CASCADE, - gitea_webhook_id INTEGER NOT NULL references librepages_gitea_webhooks(ID) ON DELETE CASCADE, - UNIQUE(site_id, gitea_webhook_id) -); diff --git a/sqlx-data.json b/sqlx-data.json index 34103cb..cf0071d 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -98,38 +98,6 @@ }, "query": "SELECT name, password FROM librepages_users WHERE name = ($1)" }, - "278dafae8343ee7b15b7014707a769e6d8f5042478c001d3dbe6cdad919f4546": { - "describe": { - "columns": [ - { - "name": "gitea_url", - "ordinal": 0, - "type_info": "Varchar" - }, - { - "name": "auth_token", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "gitea_webhook_secret", - "ordinal": 2, - "type_info": "Varchar" - } - ], - "nullable": [ - false, - false, - false - ], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "SELECT\n gitea_url, auth_token, gitea_webhook_secret\n FROM\n librepages_gitea_webhooks\n WHERE\n owned_by = (SELECT ID FROM librepages_users WHERE name = $1);\n " - }, "279b5ae27935279b06d2799eef2da6a316324a05d23ba7a729c608c70168c496": { "describe": { "columns": [], @@ -176,6 +144,39 @@ }, "query": "SELECT\n librepages_deploy_event_type.name,\n librepages_site_deploy_events.time,\n librepages_site_deploy_events.pub_id\n FROM\n librepages_site_deploy_events\n INNER JOIN librepages_deploy_event_type ON\n librepages_deploy_event_type.ID = librepages_site_deploy_events.event_type\n WHERE\n librepages_site_deploy_events.site = (\n SELECT ID FROM librepages_sites WHERE hostname = $1\n )\n AND\n librepages_site_deploy_events.pub_id = $2\n " }, + "3ecc3a4c89b1289368ef9d9c97204330f74138a0da614ef2174c59a687119595": { + "describe": { + "columns": [ + { + "name": "forgejo_url", + "ordinal": 0, + "type_info": "Varchar" + }, + { + "name": "auth_token", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "forgejo_webhook_secret", + "ordinal": 2, + "type_info": "Varchar" + } + ], + "nullable": [ + false, + false, + false + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + } + }, + "query": "SELECT\n forgejo_url, auth_token, forgejo_webhook_secret\n FROM\n librepages_forgejo_webhooks\n WHERE\n auth_token = $1\n AND\n owned_by = (SELECT ID FROM librepages_users WHERE name = $2);\n " + }, "432fe829719ce8110f768b4a611724bb34191ac224d2143ff4c81548da75c103": { "describe": { "columns": [ @@ -271,6 +272,26 @@ }, "query": "SELECT repo_url, site_secret, branch, hostname, owned_by, pub_id\n FROM librepages_sites\n WHERE repo_url = $1\n AND deleted = false;\n " }, + "4cddf1049783251bfc79090055724e894a2be9451302f7691ce2f4240f1ee3ad": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int4" + } + ], + "nullable": [ + false + ], + "parameters": { + "Left": [ + "Text" + ] + } + }, + "query": "SELECT ID FROM librepages_sites WHERE repo_url = $1" + }, "53f3c21c06c8d1c218537dfa9183fd0604aaf28200d8aa12e97db4ac317df39e": { "describe": { "columns": [ @@ -452,71 +473,6 @@ }, "query": "SELECT\n time,\n pub_id\n FROM\n librepages_site_deploy_events\n WHERE\n site = (SELECT ID FROM librepages_sites WHERE hostname = $1)\n AND\n event_type = (SELECT ID FROM librepages_deploy_event_type WHERE name = $2)\n AND\n time = (\n SELECT MAX(time) \n FROM\n librepages_site_deploy_events\n WHERE\n site = (SELECT ID FROM librepages_sites WHERE hostname = $1)\n )\n " }, - "78d6aacc46441d72e42bc8d74f36f98056b442dd0e624757b1f25db29610cb08": { - "describe": { - "columns": [ - { - "name": "gitea_url", - "ordinal": 0, - "type_info": "Varchar" - }, - { - "name": "auth_token", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "gitea_webhook_secret", - "ordinal": 2, - "type_info": "Varchar" - } - ], - "nullable": [ - false, - false, - false - ], - "parameters": { - "Left": [ - "Text", - "Text" - ] - } - }, - "query": "SELECT\n gitea_url, auth_token, gitea_webhook_secret\n FROM\n librepages_gitea_webhooks\n WHERE\n auth_token = $1\n AND\n owned_by = (SELECT ID FROM librepages_users WHERE name = $2);\n " - }, - "7d2b7a4a57b9b031d15db57116807355e9e03b7bf9b0cff0958bfebe4bc1d1be": { - "describe": { - "columns": [ - { - "name": "gitea_url", - "ordinal": 0, - "type_info": "Varchar" - }, - { - "name": "auth_token", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "gitea_webhook_secret", - "ordinal": 2, - "type_info": "Varchar" - } - ], - "nullable": [ - false, - false, - false - ], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "SELECT gitea_url, auth_token, gitea_webhook_secret\n FROM librepages_gitea_webhooks\n WHERE auth_token = $1\n " - }, "8735b654bc261571e6a5908d55a8217474c76bdff7f3cbcc71500a0fe13249db": { "describe": { "columns": [ @@ -537,6 +493,21 @@ }, "query": "SELECT EXISTS (SELECT 1 from librepages_users WHERE email = $1)" }, + "8bf4e01b8c38d035fe6bdbfbe8ad9cb35e3fc2fd11107bae92880d157ed11379": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Varchar", + "Text" + ] + } + }, + "query": "INSERT INTO librepages_forgejo_webhooks\n (forgejo_url , auth_token, forgejo_webhook_secret, owned_by) VALUES ($1, $2, $3, \n (SELECT ID FROM librepages_users WHERE name = $4)\n )" + }, "90907d6cb4ca3b485f7b583584fb5821a950362679d061e490545c76634c211e": { "describe": { "columns": [ @@ -570,6 +541,70 @@ }, "query": "UPDATE librepages_users set password = $1\n WHERE name = $2" }, + "9710a01bc4c5c5cda2db27d14baca3d7a6ceffa66c7d539da6fda7947c222e71": { + "describe": { + "columns": [ + { + "name": "forgejo_url", + "ordinal": 0, + "type_info": "Varchar" + }, + { + "name": "auth_token", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "forgejo_webhook_secret", + "ordinal": 2, + "type_info": "Varchar" + } + ], + "nullable": [ + false, + false, + false + ], + "parameters": { + "Left": [ + "Text" + ] + } + }, + "query": "SELECT\n forgejo_url, auth_token, forgejo_webhook_secret\n FROM\n librepages_forgejo_webhooks\n WHERE\n owned_by = (SELECT ID FROM librepages_users WHERE name = $1);\n " + }, + "a6284ede1dbf340942dd97afb75865ba0a41009a145254117b03002bd9afa588": { + "describe": { + "columns": [ + { + "name": "forgejo_url", + "ordinal": 0, + "type_info": "Varchar" + }, + { + "name": "auth_token", + "ordinal": 1, + "type_info": "Varchar" + }, + { + "name": "forgejo_webhook_secret", + "ordinal": 2, + "type_info": "Varchar" + } + ], + "nullable": [ + false, + false, + false + ], + "parameters": { + "Left": [ + "Text" + ] + } + }, + "query": "SELECT forgejo_url, auth_token, forgejo_webhook_secret\n FROM librepages_forgejo_webhooks\n WHERE auth_token = $1\n " + }, "b48c77db6e663d97df44bf9ec2ee92fd3e02f2dcbcdbd1d491e09fab2da68494": { "describe": { "columns": [ @@ -596,6 +631,20 @@ }, "query": "SELECT name, password FROM librepages_users WHERE email = ($1)" }, + "b7e51e976a4a80a78df8dbfed1f195af212023d00faee88ab2d09326896bd653": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Left": [ + "Text", + "Int4", + "Text" + ] + } + }, + "query": "INSERT INTO librepages_forgejo_webhook_site_mapping\n (site_id, forgejo_webhook_id) VALUES (\n (SELECT ID FROM librepages_sites WHERE repo_url = $1 AND ID = $2),\n (SELECT ID FROM librepages_forgejo_webhooks WHERE auth_token = $3)\n ) ON CONFLICT (site_id, forgejo_webhook_id) DO NOTHING;" + }, "b8b1b3c5fa205b071f577b2ce9993ddfc7c99ada26aea48aa1c201c8c3c7fcf6": { "describe": { "columns": [], @@ -633,21 +682,6 @@ }, "query": "SELECT EXISTS (SELECT 1 from librepages_users WHERE name = $1)" }, - "cd2347774ea740deae59e031a398adfc0b5c2942e556faa676fbd161297a81a6": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Varchar", - "Varchar", - "Varchar", - "Text" - ] - } - }, - "query": "INSERT INTO librepages_gitea_webhooks\n (gitea_url , auth_token, gitea_webhook_secret, owned_by) VALUES ($1, $2, $3, \n (SELECT ID FROM librepages_users WHERE name = $4)\n )" - }, "ced69a08729ffb906e8971dbdce6a8d4197bc9bb8ccd7c58b3a88eb7be73fc2e": { "describe": { "columns": [ @@ -745,18 +779,5 @@ } }, "query": "INSERT INTO librepages_users\n (name , password, email) VALUES ($1, $2, $3)" - }, - "fdcad0cd77ae37ed74cc7c92f20f9d95d851af5f9c9e6e4c34c39abf4a1d0f14": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text" - ] - } - }, - "query": "INSERT INTO librepages_gitea_webhook_site_mapping\n (site_id, gitea_webhook_id) VALUES (\n (SELECT ID FROM librepages_sites WHERE repo_url = $1),\n (SELECT ID FROM librepages_gitea_webhooks WHERE auth_token = $2)\n ) ON CONFLICT (site_id, gitea_webhook_id) DO NOTHING;" } } \ No newline at end of file diff --git a/src/api/v1/gitea.rs b/src/api/v1/forgejo.rs similarity index 81% rename from src/api/v1/gitea.rs rename to src/api/v1/forgejo.rs index bb2789f..8fa9b9c 100644 --- a/src/api/v1/gitea.rs +++ b/src/api/v1/forgejo.rs @@ -26,20 +26,20 @@ use crate::{errors::*, AppCtx}; pub mod routes { use crate::ctx::Ctx; - pub struct Gitea { + pub struct Forgejo { pub add_webhook: &'static str, pub view_webhook: &'static str, pub list_webhooks: &'static str, pub webhook: &'static str, } - impl Gitea { + impl Forgejo { pub const fn new() -> Self { Self { - add_webhook: "/api/v1/gitea/webhook/add", - list_webhooks: "/api/v1/gitea/webhook/add", - view_webhook: "/api/v1/gitea/webhook/view/{auth_token}", - webhook: "/api/v1/gitea/webhook/event/new", + add_webhook: "/api/v1/forgejo/webhook/add", + list_webhooks: "/api/v1/forgejo/webhook/add", + view_webhook: "/api/v1/forgejo/webhook/view/{auth_token}", + webhook: "/api/v1/forgejo/webhook/event/new", } } @@ -58,11 +58,11 @@ pub mod routes { #[derive(Serialize, Deserialize)] pub struct AddWebhook { - pub gitea_url: Url, + pub forgejo_url: Url, } #[actix_web_codegen_const_routes::post( - path = "crate::V1_API_ROUTES.gitea.add_webhook", + path = "crate::V1_API_ROUTES.forgejo.add_webhook", wrap = "get_auth_middleware()" )] #[tracing::instrument(name = "Add webhook" skip(id, ctx, payload))] @@ -72,17 +72,17 @@ async fn add_webhook( payload: web::Json, ) -> ServiceResult { info!( - "Adding webhook for Gitea instance: {}", - payload.gitea_url.as_str() + "Adding webhook for Forgejo instance: {}", + payload.forgejo_url.as_str() ); let owner = id.identity().unwrap(); let payload = payload.into_inner(); - let hook = ctx.db.new_webhook(payload.gitea_url, &owner).await?; + let hook = ctx.db.new_webhook(payload.forgejo_url, &owner).await?; Ok(HttpResponse::Ok().json(hook)) } #[actix_web_codegen_const_routes::get( - path = "crate::V1_API_ROUTES.gitea.list_webhooks", + path = "crate::V1_API_ROUTES.forgejo.list_webhooks", wrap = "get_auth_middleware()" )] #[tracing::instrument(name = "Delete webhook" skip(id, ctx))] @@ -94,7 +94,7 @@ async fn list_webhooks(ctx: AppCtx, id: Identity) -> ServiceResult ServiceResult { let path = path.into_inner(); let owner = id.identity().unwrap(); - info!("Gitting webhook webhook for Gitea instance: {}", path,); + info!("Gitting webhook webhook for Forgejo instance: {}", path,); let hook = ctx.db.get_webhook_with_owner(&path, &owner).await?; Ok(HttpResponse::Ok().json(hook)) } @@ -115,7 +115,7 @@ struct Auth { auth: String, } -#[actix_web_codegen_const_routes::post(path = "crate::V1_API_ROUTES.gitea.webhook")] +#[actix_web_codegen_const_routes::post(path = "crate::V1_API_ROUTES.forgejo.webhook")] #[tracing::instrument(name = "Update ", skip(body, ctx, req, q))] async fn webhook( ctx: AppCtx, @@ -139,18 +139,18 @@ mod tests { use actix_web::{error::ResponseError, http::StatusCode, test}; use hmac::Mac; - use crate::ctx::api::v1::gitea::{HmacSha256, WebhookPayload}; - use crate::db::GiteaWebhook; + use crate::ctx::api::v1::forgejo::{HmacSha256, WebhookPayload}; + use crate::db::ForgejoWebhook; use crate::tests; use crate::*; use super::*; #[actix_rt::test] - async fn test_api_gitea_webhook() { - const NAME: &str = "apigiteawebhookuser"; + async fn test_api_forgejo_webhook() { + const NAME: &str = "apiforgejowebhookuser"; const PASSWORD: &str = "longpasswordasdfa2"; - const EMAIL: &str = "apigiteawebhookuser@a.com"; + const EMAIL: &str = "apiforgejowebhookuser@a.com"; let (_dir, ctx) = tests::get_ctx().await; let _ = ctx.delete_user(NAME, PASSWORD).await; @@ -160,37 +160,37 @@ mod tests { let app = get_app!(ctx).await; let payload = AddWebhook { - gitea_url: Url::parse("https://git.batnsense.net").unwrap(), + forgejo_url: Url::parse("https://git.batnsense.net").unwrap(), }; let add_webhook_resp = test::call_service( &app, - post_request!(&payload, V1_API_ROUTES.gitea.add_webhook) + post_request!(&payload, V1_API_ROUTES.forgejo.add_webhook) .cookie(cookies.clone()) .to_request(), ) .await; check_status!(add_webhook_resp, StatusCode::OK); - let response: GiteaWebhook = actix_web::test::read_body_json(add_webhook_resp).await; - assert_eq!(response.gitea_url, payload.gitea_url); + let response: ForgejoWebhook = actix_web::test::read_body_json(add_webhook_resp).await; + assert_eq!(response.forgejo_url, payload.forgejo_url); let view_webhook_resp = get_request!( &app, - &V1_API_ROUTES.gitea.get_view(&response.auth_token), + &V1_API_ROUTES.forgejo.get_view(&response.auth_token), cookies.clone() ); check_status!(view_webhook_resp, StatusCode::OK); - let hook: GiteaWebhook = actix_web::test::read_body_json(view_webhook_resp).await; + let hook: ForgejoWebhook = actix_web::test::read_body_json(view_webhook_resp).await; assert_eq!(hook, response); let list_all_webhooks_resp = - get_request!(&app, &V1_API_ROUTES.gitea.list_webhooks, cookies.clone()); + get_request!(&app, &V1_API_ROUTES.forgejo.list_webhooks, cookies.clone()); check_status!(list_all_webhooks_resp, StatusCode::OK); - let hooks: Vec = + let hooks: Vec = actix_web::test::read_body_json(list_all_webhooks_resp).await; assert_eq!(vec![hook.clone()], hooks); - let webhook_url = format!("{}?auth={}", V1_API_ROUTES.gitea.webhook, hook.auth_token); + let webhook_url = format!("{}?auth={}", V1_API_ROUTES.forgejo.webhook, hook.auth_token); // test webhook let mut webhook_payload = WebhookPayload::default(); @@ -199,7 +199,7 @@ mod tests { let body = serde_json::to_string(&webhook_payload).unwrap(); let body = body.as_bytes(); - let mut mac = HmacSha256::new_from_slice(hook.gitea_webhook_secret.as_bytes()) + let mut mac = HmacSha256::new_from_slice(hook.forgejo_webhook_secret.as_bytes()) .expect("HMAC can take key of any size"); mac.update(&body); let res = mac.finalize(); @@ -221,7 +221,7 @@ mod tests { // no webhook let fake_webhook_url = format!( "{}?auth={}", - V1_API_ROUTES.gitea.webhook, hook.gitea_webhook_secret + V1_API_ROUTES.forgejo.webhook, hook.forgejo_webhook_secret ); let body = serde_json::to_string(&webhook_payload).unwrap(); let body = body.as_bytes(); @@ -255,7 +255,7 @@ mod tests { let body = serde_json::to_string(&webhook_payload).unwrap(); let body = body.as_bytes(); - let mut mac = HmacSha256::new_from_slice(hook.gitea_webhook_secret.as_bytes()) + let mut mac = HmacSha256::new_from_slice(hook.forgejo_webhook_secret.as_bytes()) .expect("HMAC can take key of any size"); mac.update(&body); let res = mac.finalize(); diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index a9c270b..19b5047 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -20,7 +20,7 @@ use serde::Deserialize; pub mod account; pub mod auth; -pub mod gitea; +pub mod forgejo; pub mod meta; pub mod pages; pub mod routes; @@ -31,7 +31,7 @@ pub fn services(cfg: &mut ServiceConfig) { auth::services(cfg); account::services(cfg); meta::services(cfg); - gitea::services(cfg); + forgejo::services(cfg); pages::services(cfg); } diff --git a/src/api/v1/routes.rs b/src/api/v1/routes.rs index 9192707..d7acc75 100644 --- a/src/api/v1/routes.rs +++ b/src/api/v1/routes.rs @@ -19,7 +19,7 @@ use actix_auth_middleware::GetLoginRoute; use crate::serve::routes::Serve; -use super::gitea::routes::Gitea; +use super::forgejo::routes::Forgejo; use super::meta::routes::Meta; use super::pages::routes::Deploy; @@ -93,7 +93,7 @@ pub struct Routes { pub account: Account, /// Meta routes pub meta: Meta, - pub gitea: Gitea, + pub forgejo: Forgejo, pub deploy: Deploy, pub serve: Serve, } @@ -105,7 +105,7 @@ impl Routes { auth: Auth::new(), account: Account::new(), meta: Meta::new(), - gitea: Gitea::new(), + forgejo: Forgejo::new(), deploy: Deploy::new(), serve: Serve::new(), } diff --git a/src/ctx/api/v1/gitea.rs b/src/ctx/api/v1/forgejo.rs similarity index 98% rename from src/ctx/api/v1/gitea.rs rename to src/ctx/api/v1/forgejo.rs index df1a59d..e74704a 100644 --- a/src/ctx/api/v1/gitea.rs +++ b/src/ctx/api/v1/forgejo.rs @@ -170,7 +170,7 @@ impl Ctx { &payload.repository.clone_url, ] { if self.db.site_with_repository_exists(url).await? { - let mut mac = HmacSha256::new_from_slice(hook.gitea_webhook_secret.as_bytes())?; + let mut mac = HmacSha256::new_from_slice(hook.forgejo_webhook_secret.as_bytes())?; mac.update(&body); mac.verify_slice(&sig[..])?; diff --git a/src/ctx/api/v1/mod.rs b/src/ctx/api/v1/mod.rs index db1fc2a..abc7bf1 100644 --- a/src/ctx/api/v1/mod.rs +++ b/src/ctx/api/v1/mod.rs @@ -16,7 +16,7 @@ */ pub mod account; pub mod auth; -pub mod gitea; +pub mod forgejo; pub mod pages; #[cfg(test)] diff --git a/src/db.rs b/src/db.rs index 80b1577..5139dbf 100644 --- a/src/db.rs +++ b/src/db.rs @@ -691,16 +691,20 @@ impl Database { } /// register a new webhook - pub async fn new_webhook(&self, gitea_url: Url, owner: &str) -> ServiceResult { - let hook = GiteaWebhook::new(gitea_url); + pub async fn new_webhook( + &self, + forgejo_url: Url, + owner: &str, + ) -> ServiceResult { + let hook = ForgejoWebhook::new(forgejo_url); sqlx::query!( - "INSERT INTO librepages_gitea_webhooks - (gitea_url , auth_token, gitea_webhook_secret, owned_by) VALUES ($1, $2, $3, + "INSERT INTO librepages_forgejo_webhooks + (forgejo_url , auth_token, forgejo_webhook_secret, owned_by) VALUES ($1, $2, $3, (SELECT ID FROM librepages_users WHERE name = $4) )", - hook.gitea_url.as_str(), + hook.forgejo_url.as_str(), &hook.auth_token, - &hook.gitea_webhook_secret, + &hook.forgejo_webhook_secret, owner, ) .execute(&self.pool) @@ -712,13 +716,13 @@ impl Database { pub async fn list_all_webhooks_with_owner( &self, owner: &str, - ) -> ServiceResult> { + ) -> ServiceResult> { let mut db_hooks = sqlx::query_as!( - InnerGiteaWebhook, + InnerForgejoWebhook, "SELECT - gitea_url, auth_token, gitea_webhook_secret + forgejo_url, auth_token, forgejo_webhook_secret FROM - librepages_gitea_webhooks + librepages_forgejo_webhooks WHERE owned_by = (SELECT ID FROM librepages_users WHERE name = $1); ", @@ -741,13 +745,13 @@ impl Database { &self, auth_token: &str, owner: &str, - ) -> ServiceResult { + ) -> ServiceResult { let h = sqlx::query_as!( - InnerGiteaWebhook, + InnerForgejoWebhook, "SELECT - gitea_url, auth_token, gitea_webhook_secret + forgejo_url, auth_token, forgejo_webhook_secret FROM - librepages_gitea_webhooks + librepages_forgejo_webhooks WHERE auth_token = $1 AND @@ -763,11 +767,11 @@ impl Database { h.to_webhook() } - pub async fn get_webhook(&self, auth_token: &str) -> ServiceResult { + pub async fn get_webhook(&self, auth_token: &str) -> ServiceResult { let h = sqlx::query_as!( - InnerGiteaWebhook, - "SELECT gitea_url, auth_token, gitea_webhook_secret - FROM librepages_gitea_webhooks + InnerForgejoWebhook, + "SELECT forgejo_url, auth_token, forgejo_webhook_secret + FROM librepages_forgejo_webhooks WHERE auth_token = $1 ", auth_token, @@ -795,11 +799,11 @@ impl Database { for site in sites { sqlx::query!( - "INSERT INTO librepages_gitea_webhook_site_mapping - (site_id, gitea_webhook_id) VALUES ( + "INSERT INTO librepages_forgejo_webhook_site_mapping + (site_id, forgejo_webhook_id) VALUES ( (SELECT ID FROM librepages_sites WHERE repo_url = $1 AND ID = $2), - (SELECT ID FROM librepages_gitea_webhooks WHERE auth_token = $3) - ) ON CONFLICT (site_id, gitea_webhook_id) DO NOTHING;", + (SELECT ID FROM librepages_forgejo_webhooks WHERE auth_token = $3) + ) ON CONFLICT (site_id, forgejo_webhook_id) DO NOTHING;", repo_url.as_str(), site.id, auth_token @@ -923,34 +927,34 @@ pub struct LibrePagesEvent { } #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub struct GiteaWebhook { - pub gitea_url: Url, - pub gitea_webhook_secret: String, +pub struct ForgejoWebhook { + pub forgejo_url: Url, + pub forgejo_webhook_secret: String, pub auth_token: String, } -impl GiteaWebhook { - fn new(gitea_url: Url) -> Self { +impl ForgejoWebhook { + fn new(forgejo_url: Url) -> Self { Self { - gitea_url, - gitea_webhook_secret: utils::get_random(40), + forgejo_url, + forgejo_webhook_secret: utils::get_random(40), auth_token: utils::get_random(40), } } } -struct InnerGiteaWebhook { - gitea_url: String, +struct InnerForgejoWebhook { + forgejo_url: String, auth_token: String, - gitea_webhook_secret: String, + forgejo_webhook_secret: String, } -impl InnerGiteaWebhook { - fn to_webhook(self) -> ServiceResult { - Ok(GiteaWebhook { - gitea_url: Url::parse(&self.gitea_url)?, +impl InnerForgejoWebhook { + fn to_webhook(self) -> ServiceResult { + Ok(ForgejoWebhook { + forgejo_url: Url::parse(&self.forgejo_url)?, auth_token: self.auth_token, - gitea_webhook_secret: self.gitea_webhook_secret, + forgejo_webhook_secret: self.forgejo_webhook_secret, }) } } @@ -1261,8 +1265,8 @@ mod tests { assert_eq!(latest_update_event_id_from_db.id, latest_update_event_id); // add webhook - let gitea_url = Url::parse("https://example.org").unwrap(); - let hook = db.new_webhook(gitea_url, NAME).await.unwrap(); + let forgejo_url = Url::parse("https://example.org").unwrap(); + let hook = db.new_webhook(forgejo_url, NAME).await.unwrap(); assert_eq!(hook, db.get_webhook(&hook.auth_token).await.unwrap()); assert_eq!( vec![hook.clone()], @@ -1275,7 +1279,7 @@ mod tests { .unwrap() ); assert_eq!( - db.get_webhook(&hook.gitea_webhook_secret).await.err(), + db.get_webhook(&hook.forgejo_webhook_secret).await.err(), Some(ServiceError::WebhookNotFound) ); diff --git a/src/pages/dash/gitea/add.rs b/src/pages/dash/forgejo/add.rs similarity index 68% rename from src/pages/dash/gitea/add.rs rename to src/pages/dash/forgejo/add.rs index 779a426..967e016 100644 --- a/src/pages/dash/gitea/add.rs +++ b/src/pages/dash/forgejo/add.rs @@ -22,15 +22,15 @@ use tera::Context; use tracing::info; use super::get_auth_middleware; -use crate::api::v1::gitea::AddWebhook; +use crate::api::v1::forgejo::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 const DASH_FORGEJO_WEBHOOK_ADD: TemplateFile = + TemplateFile::new("dash_forgejo_webhook_add", "pages/dash/forgejo/add.html"); pub struct Add { ctx: RefCell, @@ -51,31 +51,31 @@ impl Add { pub fn render(&self) -> String { TEMPLATES - .render(DASH_GITEA_WEBHOOK_ADD.name, &self.ctx.borrow()) + .render(DASH_FORGEJO_WEBHOOK_ADD.name, &self.ctx.borrow()) .unwrap() } } #[actix_web_codegen_const_routes::get( - path = "PAGES.dash.gitea_webhook.add", + path = "PAGES.dash.forgejo_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 { +#[tracing::instrument(name = "Dashboard add forgejo webhook webpage", skip(ctx))] +pub async fn get_add_forgejo_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", + path = "PAGES.dash.forgejo_webhook.add", wrap = "get_auth_middleware()" )] #[tracing::instrument( - name = "Post Dashboard add Gitea webhook webpage", + name = "Post Dashboard add Forgejo webhook webpage", skip(ctx, id, payload) )] -pub async fn post_add_gitea_webhook( +pub async fn post_add_forgejo_webhook( ctx: AppCtx, id: Identity, payload: web::Form, @@ -84,26 +84,26 @@ pub async fn post_add_gitea_webhook( let payload = payload.into_inner(); info!( - "Adding webhook for Gitea instance: {}", - payload.gitea_url.as_str() + "Adding webhook for Forgejo instance: {}", + payload.forgejo_url.as_str() ); let hook = ctx .db - .new_webhook(payload.gitea_url, &owner) + .new_webhook(payload.forgejo_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), + PAGES.dash.forgejo_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.service(get_add_forgejo_webhook); + cfg.service(post_add_forgejo_webhook); } #[cfg(test)] @@ -112,7 +112,7 @@ mod tests { use actix_web::test; use url::Url; - use crate::api::v1::gitea::AddWebhook; + use crate::api::v1::forgejo::AddWebhook; use crate::ctx::ArcCtx; use crate::tests; use crate::*; @@ -120,14 +120,14 @@ mod tests { use super::PAGES; #[actix_rt::test] - async fn postgres_dashboadr_add_gitea_webhook_works() { + async fn postgres_dashboadr_add_forgejo_webhook_works() { let (_, ctx) = tests::get_ctx().await; - dashboadr_add_gitea_webhook_works(ctx.clone()).await; + dashboadr_add_forgejo_webhook_works(ctx.clone()).await; } - async fn dashboadr_add_gitea_webhook_works(ctx: ArcCtx) { - const NAME: &str = "testdashwebhookgiteaadduser"; - const EMAIL: &str = "testdashwebhookgiteaadduser@foo.com"; + async fn dashboadr_add_forgejo_webhook_works(ctx: ArcCtx) { + const NAME: &str = "testdashwebhookforgejoadduser"; + const EMAIL: &str = "testdashwebhookforgejoadduser@foo.com"; const PASSWORD: &str = "longpassword"; let _ = ctx.delete_user(NAME, PASSWORD).await; @@ -135,18 +135,18 @@ mod tests { 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()); + let resp = get_request!(&app, PAGES.dash.forgejo_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")); + assert!(res.contains("Add Forgejo Webhook")); let payload = AddWebhook { - gitea_url: Url::parse("https://git.batsense.net").unwrap(), + forgejo_url: Url::parse("https://git.batsense.net").unwrap(), }; let add_webhook = test::call_service( &app, - post_request!(&payload, PAGES.dash.gitea_webhook.add, FORM) + post_request!(&payload, PAGES.dash.forgejo_webhook.add, FORM) .cookie(cookies.clone()) .to_request(), ) @@ -160,17 +160,17 @@ mod tests { // let event = event.pop().unwrap(); let headers = add_webhook.headers(); - let view_webhook_url = PAGES.dash.gitea_webhook.get_view(&hook.auth_token); + let view_webhook_url = PAGES.dash.forgejo_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()); + let resp = get_request!(&app, PAGES.dash.forgejo_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())); + assert!(res.contains(&hook.forgejo_url.as_str())); // view webhook let resp = get_request!(&app, &view_webhook_url, cookies.clone()); @@ -179,15 +179,15 @@ mod tests { assert!(res.contains("****")); assert!(res.contains( &crate::V1_API_ROUTES - .gitea + .forgejo .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()); + let show_forgejo_webhook_secret = + format!("{view_webhook_url}?show_forgejo_webhook_secret=true"); + let resp = get_request!(&app, &show_forgejo_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)); + assert!(res.contains(&hook.forgejo_webhook_secret)); } } diff --git a/src/pages/dash/gitea/list.rs b/src/pages/dash/forgejo/list.rs similarity index 79% rename from src/pages/dash/gitea/list.rs rename to src/pages/dash/forgejo/list.rs index c438957..f5aed37 100644 --- a/src/pages/dash/gitea/list.rs +++ b/src/pages/dash/forgejo/list.rs @@ -29,8 +29,8 @@ use crate::AppCtx; pub use super::*; -pub const DASH_GITEA_WEBHOOK_LIST: TemplateFile = - TemplateFile::new("dash_gitea_webhook_list", "pages/dash/gitea/list.html"); +pub const DASH_FORGEJO_WEBHOOK_LIST: TemplateFile = + TemplateFile::new("dash_forgejo_webhook_list", "pages/dash/forgejo/list.html"); pub struct List { ctx: RefCell, @@ -44,7 +44,7 @@ impl CtxError for List { } impl List { - pub fn new(settings: &Settings, hooks: Option<&[TemplateGiteaWebhook]>) -> Self { + pub fn new(settings: &Settings, hooks: Option<&[TemplateForgejoWebhook]>) -> Self { let ctx = RefCell::new(context(settings)); if let Some(hooks) = hooks { ctx.borrow_mut().insert(PAYLOAD_KEY, hooks); @@ -54,28 +54,31 @@ impl List { pub fn render(&self) -> String { TEMPLATES - .render(DASH_GITEA_WEBHOOK_LIST.name, &self.ctx.borrow()) + .render(DASH_FORGEJO_WEBHOOK_LIST.name, &self.ctx.borrow()) .unwrap() } } -async fn get_webhook_data(ctx: &AppCtx, id: &Identity) -> ServiceResult> { +async fn get_webhook_data( + ctx: &AppCtx, + id: &Identity, +) -> ServiceResult> { let db_hooks = ctx .db .list_all_webhooks_with_owner(&id.identity().unwrap()) .await?; let mut hooks = Vec::with_capacity(db_hooks.len()); for hook in db_hooks { - hooks.push(TemplateGiteaWebhook::new(ctx, hook)); + hooks.push(TemplateForgejoWebhook::new(ctx, hook)); } Ok(hooks) } #[actix_web_codegen_const_routes::get( - path = "PAGES.dash.gitea_webhook.list", + path = "PAGES.dash.forgejo_webhook.list", wrap = "get_auth_middleware()" )] -#[tracing::instrument(name = "List all Gitea webhooks", skip(ctx, id))] +#[tracing::instrument(name = "List all Forgejo webhooks", skip(ctx, id))] pub async fn list_hooks(ctx: AppCtx, id: Identity) -> PageResult { let sites = get_webhook_data(&ctx, &id) .await diff --git a/src/pages/dash/gitea/mod.rs b/src/pages/dash/forgejo/mod.rs similarity index 73% rename from src/pages/dash/gitea/mod.rs rename to src/pages/dash/forgejo/mod.rs index 3cc51cc..4fb702e 100644 --- a/src/pages/dash/gitea/mod.rs +++ b/src/pages/dash/forgejo/mod.rs @@ -22,23 +22,23 @@ pub use super::home::TemplateSite; pub use super::{context, Footer, TemplateFile, PAGES, PAYLOAD_KEY, TEMPLATES}; use crate::ctx::Ctx; -use crate::db::GiteaWebhook; +use crate::db::ForgejoWebhook; pub mod add; pub mod list; pub mod view; pub fn register_templates(t: &mut tera::Tera) { - add::DASH_GITEA_WEBHOOK_ADD + add::DASH_FORGEJO_WEBHOOK_ADD .register(t) - .expect(add::DASH_GITEA_WEBHOOK_ADD.name); - list::DASH_GITEA_WEBHOOK_LIST + .expect(add::DASH_FORGEJO_WEBHOOK_ADD.name); + list::DASH_FORGEJO_WEBHOOK_LIST .register(t) - .expect(list::DASH_GITEA_WEBHOOK_LIST.name); + .expect(list::DASH_FORGEJO_WEBHOOK_LIST.name); - view::DASH_GITEA_WEBHOOK_VIEW + view::DASH_FORGEJO_WEBHOOK_VIEW .register(t) - .expect(view::DASH_GITEA_WEBHOOK_VIEW.name); + .expect(view::DASH_FORGEJO_WEBHOOK_VIEW.name); } pub fn services(cfg: &mut web::ServiceConfig) { @@ -48,17 +48,17 @@ pub fn services(cfg: &mut web::ServiceConfig) { } #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] -pub struct TemplateGiteaWebhook { - pub webhook: GiteaWebhook, +pub struct TemplateForgejoWebhook { + pub webhook: ForgejoWebhook, 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); +impl TemplateForgejoWebhook { + pub fn new(ctx: &Ctx, hook: ForgejoWebhook) -> Self { + let view = PAGES.dash.forgejo_webhook.get_view(&hook.auth_token); let url = crate::V1_API_ROUTES - .gitea + .forgejo .get_webhook_url(ctx, &hook.auth_token); Self { webhook: hook, diff --git a/src/pages/dash/gitea/view.rs b/src/pages/dash/forgejo/view.rs similarity index 75% rename from src/pages/dash/gitea/view.rs rename to src/pages/dash/forgejo/view.rs index e0c7878..a9f8e43 100644 --- a/src/pages/dash/gitea/view.rs +++ b/src/pages/dash/forgejo/view.rs @@ -32,10 +32,10 @@ use crate::AppCtx; pub use super::*; -pub const DASH_GITEA_WEBHOOK_VIEW: TemplateFile = - TemplateFile::new("dash_gitea_webhook_view", "pages/dash/gitea/view.html"); +pub const DASH_FORGEJO_WEBHOOK_VIEW: TemplateFile = + TemplateFile::new("dash_forgejo_webhook_view", "pages/dash/forgejo/view.html"); -const SHOW_GITEA_WEBHOOK_SECRET_KEY: &str = "show_gitea_webhook_secret"; +const SHOW_FORGEJO_WEBHOOK_SECRET_KEY: &str = "show_forgejo_webhook_secret"; pub struct View { ctx: RefCell, @@ -49,7 +49,7 @@ impl CtxError for View { } impl View { - pub fn new(settings: &Settings, payload: Option) -> Self { + pub fn new(settings: &Settings, payload: Option) -> Self { let ctx = RefCell::new(context(settings)); if let Some(payload) = payload { ctx.borrow_mut().insert(PAYLOAD_KEY, &payload); @@ -58,29 +58,29 @@ impl View { Self { ctx } } - pub fn show_gitea_webhook_secret(&mut self) { + pub fn show_forgejo_webhook_secret(&mut self) { self.ctx .borrow_mut() - .insert(SHOW_GITEA_WEBHOOK_SECRET_KEY, &true); + .insert(SHOW_FORGEJO_WEBHOOK_SECRET_KEY, &true); } pub fn render(&self) -> String { TEMPLATES - .render(DASH_GITEA_WEBHOOK_VIEW.name, &self.ctx.borrow()) + .render(DASH_FORGEJO_WEBHOOK_VIEW.name, &self.ctx.borrow()) .unwrap() } } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct ViewOptions { - show_gitea_webhook_secret: Option, + show_forgejo_webhook_secret: Option, } #[actix_web_codegen_const_routes::get( - path = "PAGES.dash.gitea_webhook.view", + path = "PAGES.dash.forgejo_webhook.view", wrap = "get_auth_middleware()" )] -#[tracing::instrument(name = "Dashboard Gitea webhook webpage", skip(ctx, id))] +#[tracing::instrument(name = "Dashboard Forgejo webhook webpage", skip(ctx, id))] pub async fn get_view_site( ctx: AppCtx, id: Identity, @@ -96,10 +96,10 @@ pub async fn get_view_site( .await .map_err(|e| PageError::new(View::new(&ctx.settings, None), e))?; - let payload = TemplateGiteaWebhook::new(&ctx, hook); + let payload = TemplateForgejoWebhook::new(&ctx, hook); let mut page = View::new(&ctx.settings, Some(payload)); - if let Some(true) = query.show_gitea_webhook_secret { - page.show_gitea_webhook_secret(); + if let Some(true) = query.show_forgejo_webhook_secret { + page.show_forgejo_webhook_secret(); } let add = page.render(); let html = ContentType::html(); diff --git a/src/pages/dash/mod.rs b/src/pages/dash/mod.rs index bb3985e..ea01379 100644 --- a/src/pages/dash/mod.rs +++ b/src/pages/dash/mod.rs @@ -24,7 +24,7 @@ pub use super::{context, Footer, TemplateFile, PAGES, PAYLOAD_KEY, TEMPLATES}; use crate::db::Event; use crate::db::LibrePagesEvent; -pub mod gitea; +pub mod forgejo; pub mod home; pub mod sites; @@ -50,11 +50,11 @@ impl From for TemplateSiteEvent { pub fn register_templates(t: &mut tera::Tera) { home::DASH_HOME.register(t).expect(home::DASH_HOME.name); sites::register_templates(t); - gitea::register_templates(t); + forgejo::register_templates(t); } pub fn services(cfg: &mut web::ServiceConfig) { home::services(cfg); sites::services(cfg); - gitea::services(cfg); + forgejo::services(cfg); } diff --git a/src/pages/routes.rs b/src/pages/routes.rs index cf1a8ce..67875e4 100644 --- a/src/pages/routes.rs +++ b/src/pages/routes.rs @@ -72,7 +72,7 @@ pub struct Dash { /// home route pub home: &'static str, pub site: DashSite, - pub gitea_webhook: GiteaWebhook, + pub forgejo_webhook: ForgejoWebhook, } impl Dash { @@ -80,33 +80,33 @@ impl Dash { pub const fn new() -> Dash { let home = "/dash"; let site = DashSite::new(); - let gitea_webhook = GiteaWebhook::new(); + let forgejo_webhook = ForgejoWebhook::new(); Dash { home, site, - gitea_webhook, + forgejo_webhook, } } } #[derive(Serialize)] -/// Dashboard GiteaWebhook routes -pub struct GiteaWebhook { - /// add gitea webhook route +/// Dashboard ForgejoWebhook routes +pub struct ForgejoWebhook { + /// add forgejo webhook route pub add: &'static str, - /// view gitea webhook route + /// view forgejo webhook route pub view: &'static str, - /// list gitea webhooks route + /// list forgejo webhooks route pub list: &'static str, } -impl GiteaWebhook { - /// create new instance of GiteaWebhook route - pub const fn new() -> GiteaWebhook { - let add = "/dash/gitea/webhook/add"; - let list = "/dash/gitea/webhook/list"; - let view = "/dash/gitea/webhook/view/{auth_token}"; - GiteaWebhook { add, view, list } +impl ForgejoWebhook { + /// create new instance of ForgejoWebhook route + pub const fn new() -> ForgejoWebhook { + let add = "/dash/forgejo/webhook/add"; + let list = "/dash/forgejo/webhook/list"; + let view = "/dash/forgejo/webhook/view/{auth_token}"; + ForgejoWebhook { add, view, list } } pub fn get_view(&self, auth_token: &str) -> String { diff --git a/templates/components/nav/auth.html b/templates/components/nav/auth.html index dc3fe91..87966d4 100644 --- a/templates/components/nav/auth.html +++ b/templates/components/nav/auth.html @@ -18,7 +18,7 @@