Merge pull request 'add admin
methods' (#27) from admin into main
Reviewed-on: https://codeberg.org/Cyborus/forgejo-api/pulls/27
This commit is contained in:
commit
78d44348da
502
src/admin.rs
Normal file
502
src/admin.rs
Normal file
|
@ -0,0 +1,502 @@
|
|||
use super::*;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Write;
|
||||
|
||||
impl Forgejo {
|
||||
pub async fn admin_get_crons(&self, query: CronQuery) -> Result<Vec<Cron>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_run_cron(&self, name: &str) -> Result<(), ForgejoError> {
|
||||
self.post_unit(&format!("admin/cron/{name}"), &()).await
|
||||
}
|
||||
|
||||
pub async fn admin_get_emails(
|
||||
&self,
|
||||
query: EmailListQuery,
|
||||
) -> Result<Vec<Email>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_search_emails(
|
||||
&self,
|
||||
query: EmailSearchQuery,
|
||||
) -> Result<Vec<Email>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_get_hooks(&self, query: HookQuery) -> Result<Vec<Hook>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_create_hook(&self, opt: CreateHookOption) -> Result<Hook, ForgejoError> {
|
||||
self.post("admin/hooks", &opt).await
|
||||
}
|
||||
|
||||
pub async fn admin_get_hook(&self, id: u64) -> Result<Option<Hook>, ForgejoError> {
|
||||
self.get_opt(&format!("admin/hooks/{id}")).await
|
||||
}
|
||||
|
||||
pub async fn admin_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
|
||||
self.delete(&format!("admin/hooks/{id}")).await
|
||||
}
|
||||
|
||||
pub async fn admin_edit_hook(
|
||||
&self,
|
||||
id: u64,
|
||||
opt: EditHookOption,
|
||||
) -> Result<Hook, ForgejoError> {
|
||||
self.patch(&format!("admin/hooks/{id}"), &opt).await
|
||||
}
|
||||
|
||||
pub async fn admin_get_orgs(
|
||||
&self,
|
||||
query: AdminOrganizationQuery,
|
||||
) -> Result<Vec<Organization>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_unadopted_repos(
|
||||
&self,
|
||||
query: UnadoptedRepoQuery,
|
||||
) -> Result<Vec<String>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_adopt(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
|
||||
self.post(&format!("admin/unadopted/{owner}/{repo}"), &())
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn admin_delete_unadopted(
|
||||
&self,
|
||||
owner: &str,
|
||||
repo: &str,
|
||||
) -> Result<(), ForgejoError> {
|
||||
self.delete(&format!("admin/unadopted/{owner}/{repo}"))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn admin_users(&self, query: AdminUserQuery) -> Result<Vec<User>, ForgejoError> {
|
||||
self.get(&query.path()).await
|
||||
}
|
||||
|
||||
pub async fn admin_create_user(&self, opt: CreateUserOption) -> Result<User, ForgejoError> {
|
||||
self.post("admin/users", &opt).await
|
||||
}
|
||||
|
||||
pub async fn admin_delete_user(&self, user: &str, purge: bool) -> Result<(), ForgejoError> {
|
||||
self.delete(&format!("admin/users/{user}?purge={purge}"))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn admin_edit_user(
|
||||
&self,
|
||||
user: &str,
|
||||
opt: CreateUserOption,
|
||||
) -> Result<User, ForgejoError> {
|
||||
self.patch(&format!("admin/users/{user}"), &opt).await
|
||||
}
|
||||
|
||||
pub async fn admin_add_key(
|
||||
&self,
|
||||
user: &str,
|
||||
opt: CreateKeyOption,
|
||||
) -> Result<PublicKey, ForgejoError> {
|
||||
self.post(&format!("admin/users/{user}/keys"), &opt).await
|
||||
}
|
||||
|
||||
pub async fn admin_delete_key(&self, user: &str, id: u64) -> Result<(), ForgejoError> {
|
||||
self.delete(&format!("admin/users/{user}/keys/{id}")).await
|
||||
}
|
||||
|
||||
pub async fn admin_create_org(
|
||||
&self,
|
||||
owner: &str,
|
||||
opt: CreateOrgOption,
|
||||
) -> Result<Organization, ForgejoError> {
|
||||
self.post(&format!("admin/users/{owner}/orgs"), &opt).await
|
||||
}
|
||||
|
||||
pub async fn admin_rename_user(
|
||||
&self,
|
||||
user: &str,
|
||||
opt: RenameUserOption,
|
||||
) -> Result<(), ForgejoError> {
|
||||
self.post_unit(&format!("admin/users/{user}/rename"), &opt)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn admin_create_repo(
|
||||
&self,
|
||||
owner: &str,
|
||||
opt: CreateRepoOption,
|
||||
) -> Result<Repository, ForgejoError> {
|
||||
self.post(&format!("admin/users/{owner}/repos"), &opt).await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, PartialEq)]
|
||||
pub struct Cron {
|
||||
pub exec_times: u64,
|
||||
pub name: String,
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub next: time::OffsetDateTime,
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub prev: time::OffsetDateTime,
|
||||
pub schedule: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct CronQuery {
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
impl CronQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/cron?");
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, PartialEq)]
|
||||
pub struct Email {
|
||||
pub email: String,
|
||||
pub primary: bool,
|
||||
pub user_id: u64,
|
||||
pub username: String,
|
||||
pub verified: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct EmailListQuery {
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
impl EmailListQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/emails?");
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct EmailSearchQuery {
|
||||
pub query: String,
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
impl EmailSearchQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/emails/search?");
|
||||
if !self.query.is_empty() {
|
||||
s.push_str("q=");
|
||||
s.push_str(&self.query);
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, PartialEq)]
|
||||
pub struct Hook {
|
||||
pub active: bool,
|
||||
pub authorization_header: String,
|
||||
pub branch_filter: String,
|
||||
pub config: std::collections::BTreeMap<String, String>,
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub created_at: time::OffsetDateTime,
|
||||
pub events: Vec<String>,
|
||||
pub id: u64,
|
||||
#[serde(rename = "type")]
|
||||
pub _type: HookType,
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub updated_at: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum HookType {
|
||||
Forgejo,
|
||||
Dingtalk,
|
||||
Discord,
|
||||
Gitea,
|
||||
Gogs,
|
||||
Msteams,
|
||||
Slack,
|
||||
Telegram,
|
||||
Feishu,
|
||||
Wechatwork,
|
||||
Packagist,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct HookQuery {
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
impl HookQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/hooks?");
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
pub struct CreateHookOption {
|
||||
pub active: Option<bool>,
|
||||
pub authorization_header: Option<String>,
|
||||
pub branch_filter: Option<String>,
|
||||
pub config: CreateHookOptionConfig,
|
||||
pub events: Vec<String>,
|
||||
#[serde(rename = "type")]
|
||||
pub _type: HookType,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
pub struct CreateHookOptionConfig {
|
||||
pub content_type: String,
|
||||
pub url: Url,
|
||||
#[serde(flatten)]
|
||||
pub other: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
|
||||
pub struct EditHookOption {
|
||||
pub active: Option<bool>,
|
||||
pub authorization_header: Option<String>,
|
||||
pub branch_filter: Option<String>,
|
||||
pub config: Option<BTreeMap<String, String>>,
|
||||
pub events: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct AdminOrganizationQuery {
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
impl AdminOrganizationQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/orgs?");
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct UnadoptedRepoQuery {
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
pub pattern: String,
|
||||
}
|
||||
|
||||
impl UnadoptedRepoQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/unadopted?");
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if !self.pattern.is_empty() {
|
||||
s.push_str("pattern=");
|
||||
s.push_str(&self.pattern);
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct AdminUserQuery {
|
||||
pub source_id: Option<u64>,
|
||||
pub login_name: String,
|
||||
pub page: Option<u32>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
impl AdminUserQuery {
|
||||
fn path(&self) -> String {
|
||||
let mut s = String::from("admin/users?");
|
||||
if let Some(source_id) = self.source_id {
|
||||
s.push_str("source_id=");
|
||||
s.write_fmt(format_args!("{source_id}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if !self.login_name.is_empty() {
|
||||
s.push_str("login_name=");
|
||||
s.push_str(&self.login_name);
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(page) = self.page {
|
||||
s.push_str("page=");
|
||||
s.write_fmt(format_args!("{page}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
if let Some(limit) = self.limit {
|
||||
s.push_str("limit=");
|
||||
s.write_fmt(format_args!("{limit}"))
|
||||
.expect("writing to string can't fail");
|
||||
s.push('&');
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
pub struct CreateUserOption {
|
||||
#[serde(with = "time::serde::rfc3339::option")]
|
||||
pub created_at: Option<time::OffsetDateTime>,
|
||||
pub email: String,
|
||||
pub full_name: Option<String>,
|
||||
pub login_name: Option<String>,
|
||||
pub must_change_password: bool,
|
||||
pub password: String,
|
||||
pub restricted: bool,
|
||||
pub send_notify: bool,
|
||||
pub source_id: Option<u64>,
|
||||
pub username: String,
|
||||
pub visibility: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq, Default)]
|
||||
pub struct EditUserOption {
|
||||
pub active: Option<bool>,
|
||||
pub admin: Option<bool>,
|
||||
pub allow_create_organization: Option<bool>,
|
||||
pub allow_git_hook: Option<bool>,
|
||||
pub allow_import_local: Option<bool>,
|
||||
pub description: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub full_name: Option<String>,
|
||||
pub location: Option<String>,
|
||||
pub login_name: Option<String>,
|
||||
pub max_repo_creation: Option<u64>,
|
||||
pub must_change_password: Option<bool>,
|
||||
pub password: Option<String>,
|
||||
pub prohibit_login: Option<bool>,
|
||||
pub restricted: Option<bool>,
|
||||
pub source_id: Option<u64>,
|
||||
pub visibility: Option<String>,
|
||||
pub website: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
pub struct CreateKeyOption {
|
||||
pub key: String,
|
||||
pub read_only: Option<bool>,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, PartialEq)]
|
||||
pub struct PublicKey {
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub created_at: time::OffsetDateTime,
|
||||
pub fingerprint: String,
|
||||
pub id: u64,
|
||||
pub key: String,
|
||||
pub key_type: String,
|
||||
pub read_only: Option<bool>,
|
||||
pub title: String,
|
||||
pub url: Option<Url>,
|
||||
pub user: User,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
pub struct CreateOrgOption {
|
||||
pub description: Option<String>,
|
||||
pub full_name: Option<String>,
|
||||
pub location: Option<String>,
|
||||
pub repo_admin_change_team_access: Option<bool>,
|
||||
pub username: String,
|
||||
pub visibility: OrgVisibility,
|
||||
pub website: Option<Url>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum OrgVisibility {
|
||||
Public,
|
||||
Limited,
|
||||
Private,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug, PartialEq)]
|
||||
pub struct RenameUserOption {
|
||||
pub new_username: String,
|
||||
}
|
|
@ -8,6 +8,7 @@ pub struct Forgejo {
|
|||
client: Client,
|
||||
}
|
||||
|
||||
mod admin;
|
||||
mod issue;
|
||||
mod misc;
|
||||
mod notification;
|
||||
|
@ -16,6 +17,7 @@ mod package;
|
|||
mod repository;
|
||||
mod user;
|
||||
|
||||
pub use admin::*;
|
||||
pub use issue::*;
|
||||
pub use misc::*;
|
||||
pub use notification::*;
|
||||
|
|
126
tests/ci_test.rs
126
tests/ci_test.rs
|
@ -11,6 +11,7 @@ async fn ci() -> eyre::Result<()> {
|
|||
|
||||
results.push(user(&api).await.wrap_err("user error"));
|
||||
results.push(repo(&api).await.wrap_err("repo error"));
|
||||
results.push(admin(&api).await.wrap_err("admin error"));
|
||||
|
||||
let mut errors = 0;
|
||||
for report in results.into_iter().filter_map(Result::err) {
|
||||
|
@ -233,3 +234,128 @@ async fn repo(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn admin(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
|
||||
let user_opt = forgejo_api::CreateUserOption {
|
||||
created_at: None,
|
||||
email: "user@noreply.example.org".into(),
|
||||
full_name: None,
|
||||
login_name: None,
|
||||
must_change_password: false,
|
||||
password: "userpass".into(),
|
||||
restricted: false,
|
||||
send_notify: true,
|
||||
source_id: None,
|
||||
username: "Pipis".into(),
|
||||
visibility: "public".into(),
|
||||
};
|
||||
let _ = api
|
||||
.admin_create_user(user_opt)
|
||||
.await
|
||||
.wrap_err("failed to create user")?;
|
||||
|
||||
let users = api
|
||||
.admin_users(forgejo_api::AdminUserQuery::default())
|
||||
.await
|
||||
.wrap_err("failed to search users")?;
|
||||
ensure!(
|
||||
users.iter().find(|u| u.login == "Pipis").is_some(),
|
||||
"could not find new user"
|
||||
);
|
||||
let users = api
|
||||
.admin_get_emails(forgejo_api::EmailListQuery::default())
|
||||
.await
|
||||
.wrap_err("failed to search emails")?;
|
||||
ensure!(
|
||||
users
|
||||
.iter()
|
||||
.find(|u| u.email == "user@noreply.example.org")
|
||||
.is_some(),
|
||||
"could not find new user"
|
||||
);
|
||||
|
||||
let org_opt = forgejo_api::CreateOrgOption {
|
||||
description: None,
|
||||
full_name: None,
|
||||
location: None,
|
||||
repo_admin_change_team_access: None,
|
||||
username: "test-org".into(),
|
||||
visibility: forgejo_api::OrgVisibility::Public,
|
||||
website: None,
|
||||
};
|
||||
let _ = api
|
||||
.admin_create_org("Pipis", org_opt)
|
||||
.await
|
||||
.wrap_err("failed to create org")?;
|
||||
ensure!(
|
||||
!api.admin_get_orgs(forgejo_api::AdminOrganizationQuery::default())
|
||||
.await?
|
||||
.is_empty(),
|
||||
"org list empty"
|
||||
);
|
||||
|
||||
let key_opt = forgejo_api::CreateKeyOption {
|
||||
key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN68ehQAsbGEwlXPa2AxbAh1QxFQrtRel2jeC0hRlPc1 user@noreply.example.org".into(),
|
||||
read_only: None,
|
||||
title: "Example Key".into(),
|
||||
};
|
||||
let key = api
|
||||
.admin_add_key("Pipis", key_opt)
|
||||
.await
|
||||
.wrap_err("failed to create key")?;
|
||||
api.admin_delete_key("Pipis", key.id)
|
||||
.await
|
||||
.wrap_err("failed to delete key")?;
|
||||
|
||||
let rename_opt = forgejo_api::RenameUserOption {
|
||||
new_username: "Bepis".into(),
|
||||
};
|
||||
api.admin_rename_user("Pipis", rename_opt)
|
||||
.await
|
||||
.wrap_err("failed to rename user")?;
|
||||
api.admin_delete_user("Bepis", true)
|
||||
.await
|
||||
.wrap_err("failed to delete user")?;
|
||||
ensure!(
|
||||
api.admin_delete_user("Ghost", true).await.is_err(),
|
||||
"deleting fake user should fail"
|
||||
);
|
||||
|
||||
let crons = api
|
||||
.admin_get_crons(forgejo_api::CronQuery::default())
|
||||
.await
|
||||
.wrap_err("failed to get crons list")?;
|
||||
api.admin_run_cron(&crons.get(0).ok_or_else(|| eyre!("no crons"))?.name)
|
||||
.await
|
||||
.wrap_err("failed to run cron")?;
|
||||
|
||||
let hook_opt = forgejo_api::CreateHookOption {
|
||||
active: None,
|
||||
authorization_header: None,
|
||||
branch_filter: None,
|
||||
config: forgejo_api::CreateHookOptionConfig {
|
||||
content_type: "json".into(),
|
||||
url: url::Url::parse("http://test.local/").unwrap(),
|
||||
other: Default::default(),
|
||||
},
|
||||
events: Vec::new(),
|
||||
_type: forgejo_api::HookType::Forgejo,
|
||||
};
|
||||
// yarr har har me matey this is me hook
|
||||
let hook = api
|
||||
.admin_create_hook(hook_opt)
|
||||
.await
|
||||
.wrap_err("failed to create hook")?;
|
||||
let edit_hook = forgejo_api::EditHookOption {
|
||||
active: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
api.admin_edit_hook(hook.id, edit_hook)
|
||||
.await
|
||||
.wrap_err("failed to edit hook")?;
|
||||
api.admin_delete_hook(hook.id)
|
||||
.await
|
||||
.wrap_err("failed to delete hook")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue