feat: REST API: list all webhooks created by user
This commit is contained in:
parent
5d4977f421
commit
e423ccc0ee
1 changed files with 200 additions and 0 deletions
200
src/ctx/api/v1/gitea.rs
Normal file
200
src/ctx/api/v1/gitea.rs
Normal 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(())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue