feat: REST API: list all webhooks created by user

This commit is contained in:
Aravinth Manivannan 2022-12-28 03:42:16 +05:30
parent 5d4977f421
commit e423ccc0ee
Signed by: realaravinth
GPG key ID: AD9F0F08E855ED88

200
src/ctx/api/v1/gitea.rs Normal file
View file

@ -0,0 +1,200 @@
/*
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
*
* 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 <https://www.gnu.org/licenses/>.
*/
use actix_web::web;
use actix_web::HttpRequest;
use hmac::{Hmac, Mac};
use serde::{Deserialize, Serialize};
use sha2::Sha256;
use tracing::{info, warn};
use crate::ctx::Ctx;
use crate::errors::ServiceResult;
type HmacSha256 = Hmac<Sha256>;
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct CommitPerson {
name: String,
email: String,
username: String,
}
#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
pub struct Commit {
id: String,
message: String,
url: String,
author: CommitPerson,
committer: CommitPerson,
verification: serde_json::Value,
timestamp: String,
added: serde_json::Value,
removed: serde_json::Value,
modified: serde_json::Value,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct Person {
id: usize,
login: String,
full_name: String,
email: String,
avatar_url: String,
language: String,
is_admin: bool,
last_login: String,
created: String,
restricted: bool,
active: bool,
prohibit_login: bool,
location: String,
website: String,
description: String,
visibility: String,
followers_count: usize,
following_count: usize,
starred_repos_count: usize,
username: String,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct Permissions {
admin: bool,
push: bool,
pull: bool,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct InternalTracker {
enable_time_tracker: bool,
allow_only_contributors_to_track_time: bool,
enable_issue_dependencies: bool,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct Repository {
id: usize,
owner: Person,
name: String,
full_name: String,
description: String,
empty: bool,
private: bool,
fork: bool,
template: bool,
parent: Option<serde_json::Value>,
mirror: bool,
size: usize,
html_url: String,
ssh_url: String,
clone_url: String,
original_url: String,
website: String,
stars_count: usize,
forks_count: usize,
watchers_count: usize,
open_issues_count: usize,
open_pr_counter: usize,
release_counter: usize,
default_branch: String,
archived: bool,
created_at: String,
updated_at: String,
permissions: Permissions,
has_issues: bool,
internal_tracker: InternalTracker,
has_wiki: bool,
has_pull_requests: bool,
has_projects: bool,
ignore_whitespace_conflicts: bool,
allow_merge_commits: bool,
allow_rebase: bool,
allow_rebase_explicit: bool,
allow_squash_merge: bool,
default_merge_style: String,
avatar_url: String,
internal: bool,
mirror_interval: String,
mirror_updated: String,
repo_transfer: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct WebhookPayload {
#[serde(rename(serialize = "ref", deserialize = "ref"))]
reference: String,
before: String,
after: String,
compare_url: String,
repository: Repository,
pusher: Person,
sender: Person,
}
impl Ctx {
pub async fn process_webhook(
&self,
body: &web::Bytes,
req: &HttpRequest,
auth_token: &str,
) -> ServiceResult<()> {
let headers = req.headers();
let _uuid = headers.get("X-Gitea-Delivery").unwrap();
let sig = headers.get("X-Gitea-Signature").unwrap();
let sig = hex::decode(sig).unwrap();
let event_type = headers.get("X-Gitea-Event").unwrap();
let payload: WebhookPayload = serde_json::from_slice(&body).unwrap();
let hook = self.db.get_webhook(auth_token).await?;
for url in [
&payload.repository.html_url,
&payload.repository.ssh_url,
&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())
.expect("HMAC can take key of any size");
mac.update(&body);
mac.verify_slice(&sig[..]).unwrap();
let site = self.db.get_site_from_repo_url(url).await?;
if payload.reference.contains(&site.branch) {
info!(
"[webhook][forgejo/gitea] received update {:?} from {url} repository on deployed branch",
event_type
);
self.update_site(&site.site_secret, Some(site.branch))
.await?;
} else {
info!(
"[webhook][forgejo/gitea] received update {:?} from {url} repository on non-deployed branch {}",
event_type,
payload.reference
);
}
return Ok(());
}
}
warn!(
"[webhook][forgejo/gitea] stray update from {} repository",
payload.repository.html_url
);
Ok(())
}
}