use super::*; use std::collections::BTreeMap; use std::fmt::Write; impl Forgejo { pub async fn admin_get_crons(&self, query: CronQuery) -> Result, 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, ForgejoError> { self.get(&query.path()).await } pub async fn admin_search_emails( &self, query: EmailSearchQuery, ) -> Result, ForgejoError> { self.get(&query.path()).await } pub async fn admin_get_hooks(&self, query: HookQuery) -> Result, ForgejoError> { self.get(&query.path()).await } pub async fn admin_create_hook(&self, opt: CreateHookOption) -> Result { self.post("admin/hooks", &opt).await } pub async fn admin_get_hook(&self, id: u64) -> Result, 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 { self.patch(&format!("admin/hooks/{id}"), &opt).await } pub async fn admin_get_orgs( &self, query: AdminOrganizationQuery, ) -> Result, ForgejoError> { self.get(&query.path()).await } pub async fn admin_unadopted_repos( &self, query: UnadoptedRepoQuery, ) -> Result, 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, ForgejoError> { self.get(&query.path()).await } pub async fn admin_create_user(&self, opt: CreateUserOption) -> Result { 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 { self.patch(&format!("admin/users/{user}"), &opt).await } pub async fn admin_add_key( &self, user: &str, opt: CreateKeyOption, ) -> Result { 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 { 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 { 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, pub limit: Option, } 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, pub limit: Option, } 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, pub limit: Option, } 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, #[serde(with = "time::serde::rfc3339")] pub created_at: time::OffsetDateTime, pub events: Vec, 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, pub limit: Option, } 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, pub authorization_header: Option, pub branch_filter: Option, pub config: CreateHookOptionConfig, pub events: Vec, #[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, } #[derive(serde::Serialize, Debug, PartialEq, Default)] pub struct EditHookOption { pub active: Option, pub authorization_header: Option, pub branch_filter: Option, pub config: Option>, pub events: Option>, } #[derive(Default, Debug)] pub struct AdminOrganizationQuery { pub page: Option, pub limit: Option, } 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, pub limit: Option, 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, pub login_name: String, pub page: Option, pub limit: Option, } 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, pub email: String, pub full_name: Option, pub login_name: Option, pub must_change_password: bool, pub password: String, pub restricted: bool, pub send_notify: bool, pub source_id: Option, pub username: String, pub visibility: String, } #[derive(serde::Serialize, Debug, PartialEq, Default)] pub struct EditUserOption { pub active: Option, pub admin: Option, pub allow_create_organization: Option, pub allow_git_hook: Option, pub allow_import_local: Option, pub description: Option, pub email: Option, pub full_name: Option, pub location: Option, pub login_name: Option, pub max_repo_creation: Option, pub must_change_password: Option, pub password: Option, pub prohibit_login: Option, pub restricted: Option, pub source_id: Option, pub visibility: Option, pub website: Option, } #[derive(serde::Serialize, Debug, PartialEq)] pub struct CreateKeyOption { pub key: String, pub read_only: Option, 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, pub title: String, pub url: Option, pub user: User, } #[derive(serde::Serialize, Debug, PartialEq)] pub struct CreateOrgOption { pub description: Option, pub full_name: Option, pub location: Option, pub repo_admin_change_team_access: Option, pub username: String, pub visibility: OrgVisibility, pub website: Option, } #[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, }