1
0
Fork 0

Compare commits

...

9 commits

Author SHA1 Message Date
56fc4a167c
Releasing debian version 0.5.0-3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 08:55:14 +01:00
52f23a73d7
Updating year in debian copyright for 2025.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 06:54:24 +01:00
14da201645
Adding vcs fields.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:27:50 +01:00
3b4303b10f
Releasing debian version 0.5.0-2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:24:37 +01:00
9336ce5f71
Using codenames in changelog.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:24:34 +01:00
eddf2600bf
Releasing debian version 0.5.0-1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:24:23 +01:00
857f815429
Updating rust packaging for version 0.5.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:24:20 +01:00
45ad53e42f
Merging upstream version 0.5.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:24:07 +01:00
6b69abf4e7
Adding debian version 0.4.1-1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 05:23:39 +01:00
19 changed files with 2728 additions and 110 deletions

View file

@ -1,6 +1,6 @@
{
"git": {
"sha1": "ecbc505270cabdbd34402c0c118cb35df53ff257"
"sha1": "c49e0c3fc6ec4b8821e2c28dad38e1ac04571b0b"
},
"path_in_vcs": ""
}

View file

@ -5,11 +5,11 @@ steps:
image: rust
environment:
- "FORGEJO_API_CI_INSTANCE_URL=http://forgejo-testing:3000/"
- FORGEJO_API_CI_TOKEN=e4f301dffd4993a3389f601761c0103291e58d85
- FORGEJO_API_CI_TOKEN=6eaba97c49d9f1bbe54f8975ea884af54826c9fe
commands:
- cargo test
services:
forgejo-testing:
pull: true
image: code.cartoon-aa.xyz/cyborus/ci-forgejo:8.0.0
image: code.cartoon-aa.xyz/cyborus/ci-forgejo:9.0.0

View file

@ -12,8 +12,9 @@
[package]
edition = "2021"
name = "forgejo-api"
version = "0.4.1"
version = "0.5.0"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false

2
Cargo.toml.orig generated
View file

@ -1,7 +1,7 @@
workspace = { members = ["generator"] }
[package]
name = "forgejo-api"
version = "0.4.1"
version = "0.5.0"
edition = "2021"
license = "Apache-2.0 OR MIT"
repository = "https://codeberg.org/Cyborus/forgejo-api"

1
debian/cargo-checksum.json vendored Normal file
View file

@ -0,0 +1 @@
{"package":"4f8d2679a21200688ea04a8c79ecb70b91dcded60c9eded2549d8cee94859484","files":{}}

25
debian/changelog vendored Normal file
View file

@ -0,0 +1,25 @@
forgejo-api (0.5.0-3) sid; urgency=medium
* Adding vcs fields.
* Updating year in debian copyright for 2025.
-- Daniel Baumann <daniel@debian.org> Wed, 05 Feb 2025 08:55:08 +0100
forgejo-api (0.5.0-2) sid; urgency=medium
* Using codenames in changelog.
-- Daniel Baumann <daniel@debian.org> Thu, 23 Jan 2025 20:47:05 +0100
forgejo-api (0.5.0-1) sid; urgency=medium
* Merging upstream version 0.5.0.
* Updating rust packaging for version 0.5.0.
-- Daniel Baumann <daniel@debian.org> Tue, 24 Dec 2024 09:09:48 +0100
forgejo-api (0.4.1-1) sid; urgency=low
* Initial upload to sid (Closes: #1087909).
-- Daniel Baumann <daniel@debian.org> Wed, 20 Nov 2024 06:18:21 +0100

76
debian/control vendored Normal file
View file

@ -0,0 +1,76 @@
Source: forgejo-api
Section: utils
Priority: optional
Maintainer: Daniel Baumann <daniel@debian.org>
Build-Depends:
cargo:native <!nocheck>,
debhelper-compat (= 13),
dh-sequence-cargo,
librust-base64ct-1+default-dev (>= 1.6.0-~~) <!nocheck>,
librust-bytes-1+default-dev (>= 1.5.0-~~) <!nocheck>,
librust-reqwest-0.11+default-dev (>= 0.11.18-~~) <!nocheck>,
librust-reqwest-0.11+json-dev (>= 0.11.18-~~) <!nocheck>,
librust-reqwest-0.11+multipart-dev (>= 0.11.18-~~) <!nocheck>,
librust-serde-1+default-dev (>= 1.0.168-~~) <!nocheck>,
librust-serde-1+derive-dev (>= 1.0.168-~~) <!nocheck>,
librust-serde-json-1+default-dev (>= 1.0.108-~~) <!nocheck>,
librust-soft-assert-0.1+default-dev (>= 0.1.1-~~) <!nocheck>,
librust-thiserror-1+default-dev (>= 1.0.43-~~) <!nocheck>,
librust-time-0.3+default-dev (>= 0.3.26-~~) <!nocheck>,
librust-time-0.3+formatting-dev (>= 0.3.26-~~) <!nocheck>,
librust-time-0.3+parsing-dev (>= 0.3.26-~~) <!nocheck>,
librust-time-0.3+serde-dev (>= 0.3.26-~~) <!nocheck>,
librust-tokio-1+default-dev (>= 1.29.1-~~) <!nocheck>,
librust-tokio-1+net-dev (>= 1.29.1-~~) <!nocheck>,
librust-url-2+default-dev (>= 2.4.0-~~) <!nocheck>,
librust-url-2+serde-dev (>= 2.4.0-~~) <!nocheck>,
librust-zeroize-1+default-dev (>= 1.7.0-~~) <!nocheck>,
libstd-rust-dev <!nocheck>,
rustc:native <!nocheck>,
Rules-Requires-Root: no
Standards-Version: 4.7.0
Homepage: https://codeberg.org/Cyborus/forgejo-api
Vcs-Browser: https://forgejo.debian.net/forgejo/forgejo-api
Vcs-Git: https://forgejo.debian.net/forgejo/forgejo-api
X-Cargo-Crate: forgejo-api
Package: librust-forgejo-api-dev
Section: rust
Architecture: any
Multi-Arch: same
Depends:
librust-base64ct-1+default-dev (>= 1.6.0-~~),
librust-bytes-1+default-dev (>= 1.5.0-~~),
librust-reqwest-0.11+default-dev (>= 0.11.18-~~),
librust-reqwest-0.11+json-dev (>= 0.11.18-~~),
librust-reqwest-0.11+multipart-dev (>= 0.11.18-~~),
librust-serde-1+default-dev (>= 1.0.168-~~),
librust-serde-1+derive-dev (>= 1.0.168-~~),
librust-serde-json-1+default-dev (>= 1.0.108-~~),
librust-soft-assert-0.1+default-dev (>= 0.1.1-~~),
librust-thiserror-1+default-dev (>= 1.0.43-~~),
librust-time-0.3+default-dev (>= 0.3.26-~~),
librust-time-0.3+formatting-dev (>= 0.3.26-~~),
librust-time-0.3+parsing-dev (>= 0.3.26-~~),
librust-time-0.3+serde-dev (>= 0.3.26-~~),
librust-tokio-1+default-dev (>= 1.29.1-~~),
librust-tokio-1+net-dev (>= 1.29.1-~~),
librust-url-2+default-dev (>= 2.4.0-~~),
librust-url-2+serde-dev (>= 2.4.0-~~),
librust-zeroize-1+default-dev (>= 1.7.0-~~),
${misc:Depends},
Provides:
librust-forgejo-api+default-dev (= ${binary:Version}),
librust-forgejo-api-0+default-dev (= ${binary:Version}),
librust-forgejo-api-0-dev (= ${binary:Version}),
librust-forgejo-api-0.5+default-dev (= ${binary:Version}),
librust-forgejo-api-0.5-dev (= ${binary:Version}),
librust-forgejo-api-0.5.0+default-dev (= ${binary:Version}),
librust-forgejo-api-0.5.0-dev (= ${binary:Version}),
Description: self-hosted lightweight software forge (Rust interface to Forgejo's Web API)
Forgejo is a forge software package for hosting software development version
control using Git as well as other collaborative features like bug tracking,
code review, continuous integration, kanban boards, tickets, and wikis.
.
This package contains the Rust interface to Forgejo's Web API for use with
cargo and dh-cargo.

47
debian/copyright vendored Normal file
View file

@ -0,0 +1,47 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: forgejo-api
Upstream-Contact: https://codeberg.org/Cyborus/forgejo-api/issues
Source: https://codeberg.org/Cyborus/forgejo-api/tags
Files: *
Copyright: 2023-2024 Cyborus <cyborus@cyborus.xyz>
License: Apache-2.0 or MIT
Files: debian/*
Copyright: 2024-2025 Daniel Baumann <daniel@debian.org>
License: Apache-2.0 or MIT
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
.
https://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
.
The complete text of the Apache-2.0 License
can be found in /usr/share/common-licenses/Apache-2.0 file.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

14
debian/rules vendored Executable file
View file

@ -0,0 +1,14 @@
#!/usr/bin/make -f
%:
dh ${@} --buildsystem cargo
execute_after_dh_auto_install:
# removing unneeded files
rm -rf debian/librust-*/usr/share/cargo/registry/*/.git*
rm -rf debian/librust-*/usr/share/cargo/registry/*/.woodpecker
rm -rf debian/librust-*/usr/share/cargo/registry/*/tests
rm -f debian/librust-*/usr/share/cargo/registry/*/*.orig
rm -f debian/librust-*/usr/share/cargo/registry/*/*.md
rm -f debian/librust-*/usr/share/cargo/registry/*/LICENSE*
rm -f debian/librust-*/usr/share/cargo/registry/*/swagger*.json

1
debian/source/format vendored Normal file
View file

@ -0,0 +1 @@
3.0 (quilt)

47
debian/tests/control vendored Normal file
View file

@ -0,0 +1,47 @@
Test-Command: /usr/share/cargo/bin/cargo-auto-test forgejo-api 0.5.0 --all-targets --all-features
Features: test-name=rust-forgejo-api:@
Depends:
dh-cargo (>= 31),
librust-eyre-0.6+default-dev (>= 0.6.9-~~),
librust-reqwest-0.11+cookies-dev (>= 0.11.18-~~),
librust-reqwest-0.11+default-dev (>= 0.11.18-~~),
librust-tokio-1+default-dev (>= 1.29.1-~~),
librust-tokio-1+fs-dev (>= 1.29.1-~~),
librust-tokio-1+macros-dev (>= 1.29.1-~~),
librust-tokio-1+net-dev (>= 1.29.1-~~),
librust-tokio-1+rt-dev (>= 1.29.1-~~),
rustc,
@,
Restrictions: allow-stderr, skip-not-installable
Test-Command: /usr/share/cargo/bin/cargo-auto-test forgejo-api 0.5.0 --all-targets
Features: test-name=librust-forgejo-api-dev:default
Depends:
dh-cargo (>= 31),
librust-eyre-0.6+default-dev (>= 0.6.9-~~),
librust-reqwest-0.11+cookies-dev (>= 0.11.18-~~),
librust-reqwest-0.11+default-dev (>= 0.11.18-~~),
librust-tokio-1+default-dev (>= 1.29.1-~~),
librust-tokio-1+fs-dev (>= 1.29.1-~~),
librust-tokio-1+macros-dev (>= 1.29.1-~~),
librust-tokio-1+net-dev (>= 1.29.1-~~),
librust-tokio-1+rt-dev (>= 1.29.1-~~),
rustc,
@,
Restrictions: allow-stderr, skip-not-installable
Test-Command: /usr/share/cargo/bin/cargo-auto-test forgejo-api 0.5.0 --all-targets --no-default-features
Features: test-name=librust-forgejo-api-dev:
Depends:
dh-cargo (>= 31),
librust-eyre-0.6+default-dev (>= 0.6.9-~~),
librust-reqwest-0.11+cookies-dev (>= 0.11.18-~~),
librust-reqwest-0.11+default-dev (>= 0.11.18-~~),
librust-tokio-1+default-dev (>= 1.29.1-~~),
librust-tokio-1+fs-dev (>= 1.29.1-~~),
librust-tokio-1+macros-dev (>= 1.29.1-~~),
librust-tokio-1+net-dev (>= 1.29.1-~~),
librust-tokio-1+rt-dev (>= 1.29.1-~~),
rustc,
@,
Restrictions: allow-stderr, skip-not-installable

4
debian/watch vendored Normal file
View file

@ -0,0 +1,4 @@
version=4
opts=filenamemangle=s/.*\/(.*)\/download/forgejo-api-$1\.tar\.gz/g,\
uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\.?\d*)$/$1~$2/ \
https://qa.debian.org/cgi-bin/fakeupstream.cgi?upstream=crates.io/forgejo-api .*/crates/forgejo-api/@ANY_VERSION@/download

View file

@ -3,6 +3,26 @@ use crate::ForgejoError;
use std::collections::BTreeMap;
impl crate::Forgejo {
/// Returns the instance's Actor
pub async fn activitypub_instance_actor(&self) -> Result<ActivityPub, ForgejoError> {
let request = self.get("activitypub/actor").build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Send to the inbox
pub async fn activitypub_instance_actor_inbox(&self) -> Result<(), ForgejoError> {
let request = self.post("activitypub/actor/inbox").build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Returns the Repository actor for a repo
///
/// - `repository-id`: repository ID of the repo
@ -206,6 +226,239 @@ impl crate::Forgejo {
}
}
/// List the available quota groups
pub async fn admin_list_quota_groups(&self) -> Result<Vec<QuotaGroup>, ForgejoError> {
let request = self.get("admin/quota/groups").build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Create a new quota group
///
/// - `group`: Definition of the quota group
/// See [`CreateQuotaGroupOptions`]
pub async fn admin_create_quota_group(
&self,
group: CreateQuotaGroupOptions,
) -> Result<QuotaGroup, ForgejoError> {
let request = self.post("admin/quota/groups").json(&group).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
201 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Get information about the quota group
///
/// - `quotagroup`: quota group to query
pub async fn admin_get_quota_group(
&self,
quotagroup: &str,
) -> Result<QuotaGroup, ForgejoError> {
let request = self
.get(&format!("admin/quota/groups/{quotagroup}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Delete a quota group
///
/// - `quotagroup`: quota group to delete
pub async fn admin_delete_quota_group(&self, quotagroup: &str) -> Result<(), ForgejoError> {
let request = self
.delete(&format!("admin/quota/groups/{quotagroup}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Adds a rule to a quota group
///
/// - `quotagroup`: quota group to add a rule to
/// - `quotarule`: the name of the quota rule to add to the group
pub async fn admin_add_rule_to_quota_group(
&self,
quotagroup: &str,
quotarule: &str,
) -> Result<(), ForgejoError> {
let request = self
.put(&format!(
"admin/quota/groups/{quotagroup}/rules/{quotarule}"
))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Removes a rule from a quota group
///
/// - `quotagroup`: quota group to remove a rule from
/// - `quotarule`: the name of the quota rule to remove from the group
pub async fn admin_remove_rule_from_quota_group(
&self,
quotagroup: &str,
quotarule: &str,
) -> Result<(), ForgejoError> {
let request = self
.delete(&format!(
"admin/quota/groups/{quotagroup}/rules/{quotarule}"
))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List users in a quota group
///
/// - `quotagroup`: quota group to list members of
pub async fn admin_list_users_in_quota_group(
&self,
quotagroup: &str,
) -> Result<Vec<User>, ForgejoError> {
let request = self
.get(&format!("admin/quota/groups/{quotagroup}/users"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Add a user to a quota group
///
/// - `quotagroup`: quota group to add the user to
/// - `username`: username of the user to add to the quota group
pub async fn admin_add_user_to_quota_group(
&self,
quotagroup: &str,
username: &str,
) -> Result<(), ForgejoError> {
let request = self
.put(&format!("admin/quota/groups/{quotagroup}/users/{username}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Remove a user from a quota group
///
/// - `quotagroup`: quota group to remove a user from
/// - `username`: username of the user to remove from the quota group
pub async fn admin_remove_user_from_quota_group(
&self,
quotagroup: &str,
username: &str,
) -> Result<(), ForgejoError> {
let request = self
.delete(&format!("admin/quota/groups/{quotagroup}/users/{username}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the available quota rules
pub async fn admin_list_quota_rules(&self) -> Result<Vec<QuotaRuleInfo>, ForgejoError> {
let request = self.get("admin/quota/rules").build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Create a new quota rule
///
/// - `rule`: Definition of the quota rule
/// See [`CreateQuotaRuleOptions`]
pub async fn admin_create_quota_rule(
&self,
rule: CreateQuotaRuleOptions,
) -> Result<QuotaRuleInfo, ForgejoError> {
let request = self.post("admin/quota/rules").json(&rule).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
201 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Get information about a quota rule
///
/// - `quotarule`: quota rule to query
pub async fn admin_get_quota_rule(
&self,
quotarule: &str,
) -> Result<QuotaRuleInfo, ForgejoError> {
let request = self
.get(&format!("admin/quota/rules/{quotarule}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Deletes a quota rule
///
/// - `quotarule`: quota rule to delete
pub async fn admin_delete_quota_rule(&self, quotarule: &str) -> Result<(), ForgejoError> {
let request = self
.delete(&format!("admin/quota/rules/{quotarule}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Change an existing quota rule
///
/// - `quotarule`: Quota rule to change
/// - `rule`: See [`EditQuotaRuleOptions`]
pub async fn admin_edit_quota_rule(
&self,
quotarule: &str,
rule: EditQuotaRuleOptions,
) -> Result<QuotaRuleInfo, ForgejoError> {
let request = self
.patch(&format!("admin/quota/rules/{quotarule}"))
.json(&rule)
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Get an global actions runner registration token
pub async fn admin_get_runner_registration_token(
&self,
@ -393,6 +646,40 @@ impl crate::Forgejo {
}
}
/// Get the user's quota info
///
/// - `username`: username of user to query
pub async fn admin_get_user_quota(&self, username: &str) -> Result<QuotaInfo, ForgejoError> {
let request = self.get(&format!("admin/users/{username}/quota")).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Set the user's quota groups to a given list.
///
/// - `username`: username of the user to modify the quota groups from
/// - `groups`: list of groups that the user should be a member of
/// See [`SetUserQuotaGroupsOptions`]
pub async fn admin_set_user_quota_groups(
&self,
username: &str,
groups: SetUserQuotaGroupsOptions,
) -> Result<(), ForgejoError> {
let request = self
.post(&format!("admin/users/{username}/quota/groups"))
.json(&groups)
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
204 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Rename a user
///
/// - `username`: existing username of user
@ -1256,6 +1543,84 @@ impl crate::Forgejo {
}
}
/// Get quota information for an organization
///
/// - `org`: name of the organization
pub async fn org_get_quota(&self, org: &str) -> Result<QuotaInfo, ForgejoError> {
let request = self.get(&format!("orgs/{org}/quota")).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the artifacts affecting the organization's quota
///
/// - `org`: name of the organization
pub async fn org_list_quota_artifacts(
&self,
org: &str,
query: OrgListQuotaArtifactsQuery,
) -> Result<Vec<QuotaUsedArtifact>, ForgejoError> {
let request = self
.get(&format!("orgs/{org}/quota/artifacts?{query}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the attachments affecting the organization's quota
///
/// - `org`: name of the organization
pub async fn org_list_quota_attachments(
&self,
org: &str,
query: OrgListQuotaAttachmentsQuery,
) -> Result<Vec<QuotaUsedAttachment>, ForgejoError> {
let request = self
.get(&format!("orgs/{org}/quota/attachments?{query}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Check if the organization is over quota for a given subject
///
/// - `org`: name of the organization
pub async fn org_check_quota(&self, org: &str) -> Result<(), ForgejoError> {
let request = self.get(&format!("orgs/{org}/quota/check")).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the packages affecting the organization's quota
///
/// - `org`: name of the organization
pub async fn org_list_quota_packages(
&self,
org: &str,
query: OrgListQuotaPackagesQuery,
) -> Result<Vec<QuotaUsedPackage>, ForgejoError> {
let request = self
.get(&format!("orgs/{org}/quota/packages?{query}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List an organization's repos
///
/// - `org`: name of the organization
@ -1533,6 +1898,27 @@ impl crate::Forgejo {
}
}
/// Get a repository's actions runner registration token
///
/// - `owner`: owner of the repo
/// - `repo`: name of the repo
pub async fn repo_get_runner_registration_token(
&self,
owner: &str,
repo: &str,
) -> Result<RegistrationTokenHeaders, ForgejoError> {
let request = self
.get(&format!(
"repos/{owner}/{repo}/actions/runners/registration-token"
))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.headers().try_into()?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List an repo's actions secrets
///
/// - `owner`: owner of the repository
@ -3235,20 +3621,19 @@ impl crate::Forgejo {
attachment: Vec<u8>,
query: IssueCreateIssueCommentAttachmentQuery,
) -> Result<Attachment, ForgejoError> {
let request = self
.post(&format!(
"repos/{owner}/{repo}/issues/comments/{id}/assets?{query}"
))
.multipart(
reqwest::multipart::Form::new().part(
"attachment",
reqwest::multipart::Part::bytes(attachment)
.file_name("file")
.mime_str("*/*")
.unwrap(),
),
)
.build()?;
let builder = self.post(&format!(
"repos/{owner}/{repo}/issues/comments/{id}/assets?{query}"
));
let builder = builder.multipart(
reqwest::multipart::Form::new().part(
"attachment",
reqwest::multipart::Part::bytes(attachment)
.file_name("file")
.mime_str("*/*")
.unwrap(),
),
);
let request = builder.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
201 => Ok(response.json().await?),
@ -3530,20 +3915,19 @@ impl crate::Forgejo {
attachment: Vec<u8>,
query: IssueCreateIssueAttachmentQuery,
) -> Result<Attachment, ForgejoError> {
let request = self
.post(&format!(
"repos/{owner}/{repo}/issues/{index}/assets?{query}"
))
.multipart(
reqwest::multipart::Form::new().part(
"attachment",
reqwest::multipart::Part::bytes(attachment)
.file_name("file")
.mime_str("*/*")
.unwrap(),
),
)
.build()?;
let builder = self.post(&format!(
"repos/{owner}/{repo}/issues/{index}/assets?{query}"
));
let builder = builder.multipart(
reqwest::multipart::Form::new().part(
"attachment",
reqwest::multipart::Part::bytes(attachment)
.file_name("file")
.mime_str("*/*")
.unwrap(),
),
);
let request = builder.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
201 => Ok(response.json().await?),
@ -5791,20 +6175,22 @@ impl crate::Forgejo {
/// - `owner`: owner of the repo
/// - `repo`: name of the repo
/// - `id`: id of the release
/// - `attachment`: attachment to upload
/// - `attachment`: attachment to upload (this parameter is incompatible with `external_url`)
/// - `external_url`: url to external asset (this parameter is incompatible with `attachment`)
pub async fn repo_create_release_attachment(
&self,
owner: &str,
repo: &str,
id: u64,
attachment: Vec<u8>,
attachment: Option<Vec<u8>>,
external_url: Option<Vec<u8>>,
query: RepoCreateReleaseAttachmentQuery,
) -> Result<Attachment, ForgejoError> {
let request = self
.post(&format!(
"repos/{owner}/{repo}/releases/{id}/assets?{query}"
))
.multipart(
let builder = self.post(&format!(
"repos/{owner}/{repo}/releases/{id}/assets?{query}"
));
let builder = match attachment {
Some(attachment) => builder.multipart(
reqwest::multipart::Form::new().part(
"attachment",
reqwest::multipart::Part::bytes(attachment)
@ -5812,8 +6198,22 @@ impl crate::Forgejo {
.mime_str("*/*")
.unwrap(),
),
)
.build()?;
),
None => builder,
};
let builder = match external_url {
Some(external_url) => builder.multipart(
reqwest::multipart::Form::new().part(
"attachment",
reqwest::multipart::Part::bytes(external_url)
.file_name("file")
.mime_str("*/*")
.unwrap(),
),
),
None => builder,
};
let request = builder.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
201 => Ok(response.json().await?),
@ -5918,25 +6318,6 @@ impl crate::Forgejo {
}
}
/// Get a repository's actions runner registration token
///
/// - `owner`: owner of the repo
/// - `repo`: name of the repo
pub async fn repo_get_runner_registration_token(
&self,
owner: &str,
repo: &str,
) -> Result<RegistrationTokenHeaders, ForgejoError> {
let request = self
.get(&format!("repos/{owner}/{repo}/runners/registration-token"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.headers().try_into()?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Get signing-key.gpg for given repository
///
/// - `owner`: owner of the repo
@ -7583,6 +7964,70 @@ impl crate::Forgejo {
}
}
/// Get quota information for the authenticated user
pub async fn user_get_quota(&self) -> Result<QuotaInfo, ForgejoError> {
let request = self.get("user/quota").build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the artifacts affecting the authenticated user's quota
///
pub async fn user_list_quota_artifacts(
&self,
query: UserListQuotaArtifactsQuery,
) -> Result<Vec<QuotaUsedArtifact>, ForgejoError> {
let request = self.get(&format!("user/quota/artifacts?{query}")).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the attachments affecting the authenticated user's quota
///
pub async fn user_list_quota_attachments(
&self,
query: UserListQuotaAttachmentsQuery,
) -> Result<Vec<QuotaUsedAttachment>, ForgejoError> {
let request = self
.get(&format!("user/quota/attachments?{query}"))
.build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// Check if the authenticated user is over quota for a given subject
pub async fn user_check_quota(&self) -> Result<(), ForgejoError> {
let request = self.get("user/quota/check").build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(()),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the packages affecting the authenticated user's quota
///
pub async fn user_list_quota_packages(
&self,
query: UserListQuotaPackagesQuery,
) -> Result<Vec<QuotaUsedPackage>, ForgejoError> {
let request = self.get(&format!("user/quota/packages?{query}")).build()?;
let response = self.execute(request).await?;
match response.status().as_u16() {
200 => Ok(response.json().await?),
_ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
}
}
/// List the repos that the authenticated user owns
///
pub async fn user_current_list_repos(

View file

@ -147,9 +147,18 @@ pub struct ActivityPub {
/// AddCollaboratorOption options when adding a user as a collaborator of a repository
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct AddCollaboratorOption {
pub permission: Option<String>,
pub permission: Option<AddCollaboratorOptionPermission>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum AddCollaboratorOptionPermission {
#[serde(rename = "read")]
Read,
#[serde(rename = "write")]
Write,
#[serde(rename = "admin")]
Admin,
}
/// AddTimeOption options for adding time to an issue
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct AddTimeOption {
@ -196,9 +205,18 @@ pub struct Attachment {
pub id: Option<i64>,
pub name: Option<String>,
pub size: Option<i64>,
#[serde(rename = "type")]
pub r#type: Option<AttachmentType>,
pub uuid: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum AttachmentType {
#[serde(rename = "attachment")]
Attachment,
#[serde(rename = "external")]
External,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct BlockedUser {
pub block_id: Option<i64>,
@ -767,8 +785,62 @@ pub struct CreatePushMirrorOption {
pub remote_password: Option<String>,
pub remote_username: Option<String>,
pub sync_on_commit: Option<bool>,
pub use_ssh: Option<bool>,
}
/// CreateQutaGroupOptions represents the options for creating a quota group
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CreateQuotaGroupOptions {
/// Name of the quota group to create
pub name: Option<String>,
/// Rules to add to the newly created group.
///
/// If a rule does not exist, it will be created.
pub rules: Option<Vec<CreateQuotaRuleOptions>>,
}
/// CreateQuotaRuleOptions represents the options for creating a quota rule
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CreateQuotaRuleOptions {
/// The limit set by the rule
pub limit: Option<i64>,
/// Name of the rule to create
pub name: Option<String>,
/// The subjects affected by the rule
pub subjects: Option<Vec<CreateQuotaRuleOptionsSubjects>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum CreateQuotaRuleOptionsSubjects {
#[serde(rename = "none")]
None,
#[serde(rename = "size:all")]
SizeAll,
#[serde(rename = "size:repos:all")]
SizeReposAll,
#[serde(rename = "size:repos:public")]
SizeReposPublic,
#[serde(rename = "size:repos:private")]
SizeReposPrivate,
#[serde(rename = "size:git:all")]
SizeGitAll,
#[serde(rename = "size:git:lfs")]
SizeGitLfs,
#[serde(rename = "size:assets:all")]
SizeAssetsAll,
#[serde(rename = "size:assets:attachments:all")]
SizeAssetsAttachmentsAll,
#[serde(rename = "size:assets:attachments:issues")]
SizeAssetsAttachmentsIssues,
#[serde(rename = "size:assets:attachments:releases")]
SizeAssetsAttachmentsReleases,
#[serde(rename = "size:assets:artifacts")]
SizeAssetsArtifacts,
#[serde(rename = "size:assets:packages:all")]
SizeAssetsPackagesAll,
#[serde(rename = "size:assets:wiki")]
SizeAssetsWiki,
}
/// CreateReleaseOption options when creating a release
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CreateReleaseOption {
@ -1004,6 +1076,9 @@ pub struct DispatchWorkflowOption {
/// EditAttachmentOptions options for editing attachments
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct EditAttachmentOptions {
#[serde(deserialize_with = "crate::none_if_blank_url")]
/// (Can only be set if existing attachment is of external type)
pub browser_download_url: Option<url::Url>,
pub name: Option<String>,
}
@ -1146,6 +1221,15 @@ pub struct EditPullRequestOption {
pub unset_due_date: Option<bool>,
}
/// EditQuotaRuleOptions represents the options for editing a quota rule
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct EditQuotaRuleOptions {
/// The limit set by the rule
pub limit: Option<i64>,
/// The subjects affected by the rule
pub subjects: Option<Vec<String>>,
}
/// EditReactionOption contain the reaction type
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct EditReactionOption {
@ -2192,6 +2276,7 @@ pub struct PullRequest {
pub pin_order: Option<i64>,
#[serde(deserialize_with = "crate::requested_reviewers_ignore_null")]
pub requested_reviewers: Option<Vec<User>>,
pub requested_reviewers_teams: Option<Vec<Team>>,
/// number of review comments made on the diff of a PR review (not including comments on commits or issues in a PR)
pub review_comments: Option<i64>,
pub state: Option<StateType>,
@ -2277,12 +2362,150 @@ pub struct PushMirror {
pub last_error: Option<String>,
#[serde(with = "time::serde::rfc3339::option")]
pub last_update: Option<time::OffsetDateTime>,
pub public_key: Option<String>,
pub remote_address: Option<String>,
pub remote_name: Option<String>,
pub repo_name: Option<String>,
pub sync_on_commit: Option<bool>,
}
/// QuotaGroup represents a quota group
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaGroup {
/// Name of the group
pub name: Option<String>,
/// Rules associated with the group
pub rules: Option<Vec<QuotaRuleInfo>>,
}
/// QuotaInfo represents information about a user's quota
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaInfo {
pub groups: Option<Vec<QuotaGroup>>,
pub used: Option<QuotaUsed>,
}
/// QuotaRuleInfo contains information about a quota rule
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaRuleInfo {
/// The limit set by the rule
pub limit: Option<i64>,
/// Name of the rule (only shown to admins)
pub name: Option<String>,
/// Subjects the rule affects
pub subjects: Option<Vec<String>>,
}
/// QuotaUsed represents the quota usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsed {
pub size: Option<QuotaUsedSize>,
}
/// QuotaUsedArtifact represents an artifact counting towards a user's quota
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedArtifact {
#[serde(deserialize_with = "crate::none_if_blank_url")]
/// HTML URL to the action run containing the artifact
pub html_url: Option<url::Url>,
/// Name of the artifact
pub name: Option<String>,
/// Size of the artifact (compressed)
pub size: Option<i64>,
}
/// QuotaUsedAttachment represents an attachment counting towards a user's quota
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedAttachment {
#[serde(deserialize_with = "crate::none_if_blank_url")]
/// API URL for the attachment
pub api_url: Option<url::Url>,
/// Context for the attachment: URLs to the containing object
pub contained_in: Option<QuotaUsedAttachmentContainedIn>,
/// Filename of the attachment
pub name: Option<String>,
/// Size of the attachment (in bytes)
pub size: Option<i64>,
}
/// Context for the attachment: URLs to the containing object
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedAttachmentContainedIn {
#[serde(deserialize_with = "crate::none_if_blank_url")]
/// API URL for the object that contains this attachment
pub api_url: Option<url::Url>,
#[serde(deserialize_with = "crate::none_if_blank_url")]
/// HTML URL for the object that contains this attachment
pub html_url: Option<url::Url>,
}
/// QuotaUsedPackage represents a package counting towards a user's quota
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedPackage {
#[serde(deserialize_with = "crate::none_if_blank_url")]
/// HTML URL to the package version
pub html_url: Option<url::Url>,
/// Name of the package
pub name: Option<String>,
/// Size of the package version
pub size: Option<i64>,
/// Type of the package
#[serde(rename = "type")]
pub r#type: Option<String>,
/// Version of the package
pub version: Option<String>,
}
/// QuotaUsedSize represents the size-based quota usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedSize {
pub assets: Option<QuotaUsedSizeAssets>,
pub git: Option<QuotaUsedSizeGit>,
pub repos: Option<QuotaUsedSizeRepos>,
}
/// QuotaUsedSizeAssets represents the size-based asset usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedSizeAssets {
/// Storage size used for the user's artifacts
pub artifacts: Option<i64>,
pub attachments: Option<QuotaUsedSizeAssetsAttachments>,
pub packages: Option<QuotaUsedSizeAssetsPackages>,
}
/// QuotaUsedSizeAssetsAttachments represents the size-based attachment quota usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedSizeAssetsAttachments {
/// Storage size used for the user's issue & comment attachments
pub issues: Option<i64>,
/// Storage size used for the user's release attachments
pub releases: Option<i64>,
}
/// QuotaUsedSizeAssetsPackages represents the size-based package quota usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedSizeAssetsPackages {
/// Storage suze used for the user's packages
pub all: Option<i64>,
}
/// QuotaUsedSizeGit represents the size-based git (lfs) quota usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedSizeGit {
/// Storage size of the user's Git LFS objects
#[serde(rename = "LFS")]
pub lfs: Option<i64>,
}
/// QuotaUsedSizeRepos represents the size-based repository quota usage of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct QuotaUsedSizeRepos {
/// Storage size of the user's private repositories
pub private: Option<i64>,
/// Storage size of the user's public repositories
pub public: Option<i64>,
}
/// Reaction contain one reaction
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Reaction {
@ -2491,6 +2714,13 @@ pub struct ServerVersion {
pub version: Option<String>,
}
/// SetUserQuotaGroupsOptions represents the quota groups of a user
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct SetUserQuotaGroupsOptions {
/// Quota groups the user shall have
pub groups: Vec<String>,
}
/// StateType issue state type
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
@ -3091,6 +3321,46 @@ impl TryFrom<&reqwest::header::HeaderMap> for InvalidTopicsErrorHeaders {
}
}
pub struct QuotaExceededHeaders {
pub message: Option<String>,
pub user_id: Option<i64>,
pub username: Option<String>,
}
impl TryFrom<&reqwest::header::HeaderMap> for QuotaExceededHeaders {
type Error = StructureError;
fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
let message = map
.get("message")
.map(|s| -> Result<_, _> {
let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
Ok(s.to_string())
})
.transpose()?;
let user_id = map
.get("user_id")
.map(|s| -> Result<_, _> {
let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
s.parse::<i64>()
.map_err(|_| StructureError::HeaderParseFailed)
})
.transpose()?;
let username = map
.get("username")
.map(|s| -> Result<_, _> {
let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
Ok(s.to_string())
})
.transpose()?;
Ok(Self {
message,
user_id,
username,
})
}
}
pub struct RepoArchivedErrorHeaders {
pub message: Option<String>,
pub url: Option<url::Url>,
@ -3681,6 +3951,69 @@ impl std::fmt::Display for OrgListPublicMembersQuery {
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct OrgListQuotaArtifactsQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
}
impl std::fmt::Display for OrgListQuotaArtifactsQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(page) = &self.page {
write!(f, "page={page}&")?;
}
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct OrgListQuotaAttachmentsQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
}
impl std::fmt::Display for OrgListQuotaAttachmentsQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(page) = &self.page {
write!(f, "page={page}&")?;
}
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct OrgListQuotaPackagesQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
}
impl std::fmt::Display for OrgListQuotaPackagesQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(page) = &self.page {
write!(f, "page={page}&")?;
}
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct OrgListReposQuery {
/// page number of results to return (1-based)
@ -6071,12 +6404,77 @@ impl std::fmt::Display for OrgListCurrentUserOrgsQuery {
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct UserListQuotaArtifactsQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
}
impl std::fmt::Display for UserListQuotaArtifactsQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(page) = &self.page {
write!(f, "page={page}&")?;
}
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct UserListQuotaAttachmentsQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
}
impl std::fmt::Display for UserListQuotaAttachmentsQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(page) = &self.page {
write!(f, "page={page}&")?;
}
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct UserListQuotaPackagesQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
}
impl std::fmt::Display for UserListQuotaPackagesQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(page) = &self.page {
write!(f, "page={page}&")?;
}
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct UserCurrentListReposQuery {
/// page number of results to return (1-based)
pub page: Option<u32>,
/// page size of results
pub limit: Option<u32>,
/// order the repositories by name (default), id, or size
pub order_by: Option<String>,
}
impl std::fmt::Display for UserCurrentListReposQuery {
@ -6087,6 +6485,9 @@ impl std::fmt::Display for UserCurrentListReposQuery {
if let Some(limit) = &self.limit {
write!(f, "limit={limit}&")?;
}
if let Some(order_by) = &self.order_by {
write!(f, "order_by={order_by}&")?;
}
Ok(())
}

View file

@ -367,7 +367,7 @@ where
{
let list: Option<Vec<Option<structs::User>>> =
Option::deserialize(deserializer).map_err(DE::custom)?;
Ok(list.map(|list| list.into_iter().filter_map(|x| x).collect::<Vec<_>>()))
Ok(list.map(|list| list.into_iter().flatten().collect::<Vec<_>>()))
}
fn parse_ssh_url(raw_url: &String) -> Result<Url, url::ParseError> {

File diff suppressed because it is too large Load diff

View file

@ -30,10 +30,7 @@ async fn user() {
.await
.expect("failed to search users");
assert!(
users
.iter()
.find(|u| u.login.as_ref().unwrap() == "Pipis")
.is_some(),
users.iter().any(|u| u.login.as_ref().unwrap() == "Pipis"),
"could not find new user"
);
let query = AdminGetAllEmailsQuery::default();
@ -44,8 +41,7 @@ async fn user() {
assert!(
users
.iter()
.find(|u| u.email.as_ref().unwrap() == "pipis@noreply.example.org")
.is_some(),
.any(|u| u.email.as_ref().unwrap() == "pipis@noreply.example.org"),
"could not find new user"
);
}
@ -153,7 +149,7 @@ async fn cron() {
.admin_cron_list(query)
.await
.expect("failed to get crons list");
api.admin_cron_run(&crons.get(0).expect("no crons").name.as_ref().unwrap())
api.admin_cron_run(crons.first().expect("no crons").name.as_ref().unwrap())
.await
.expect("failed to run cron");
}
@ -192,3 +188,91 @@ async fn hook() {
.await
.expect("failed to delete hook");
}
#[tokio::test]
async fn quota_group() {
let api = common::login();
let user_opts = CreateUserOption {
created_at: None,
email: "1997@example.com".into(),
full_name: None,
login_name: None,
must_change_password: None,
password: Some("dialtone".into()),
restricted: None,
send_notify: None,
source_id: None,
username: "salesman".into(),
visibility: None,
};
api.admin_create_user(user_opts)
.await
.expect("failed to create user");
let group = CreateQuotaGroupOptions {
name: Some("no doing anything".into()),
rules: Some(vec![CreateQuotaRuleOptions {
limit: Some(0),
name: Some("blah".into()),
subjects: Some(vec![CreateQuotaRuleOptionsSubjects::SizeAll]),
}]),
};
let quota_group = api
.admin_create_quota_group(group)
.await
.expect("failed to create quota group");
api.admin_add_user_to_quota_group("no doing anything", "salesman")
.await
.expect("failed to add user to quota group");
assert!(quota_group
.name
.as_ref()
.is_some_and(|name| name == "no doing anything"));
assert!(quota_group
.rules
.as_ref()
.is_some_and(|rules| rules.len() == 1));
let quota_groups = api
.admin_list_quota_groups()
.await
.expect("failed to list quota groups");
assert_eq!(quota_groups.len(), 1);
assert_eq!(&quota_groups[0], &quota_group);
let quota_info = api
.admin_get_user_quota("salesman")
.await
.expect("failed to get user quota");
let usage = quota_info
.used
.expect("quota info missing usage info")
.size
.expect("quota info missing size info");
assert!(usage
.git
.is_some_and(|git| git.lfs.is_some_and(|lfs| lfs == 0)));
assert!(usage
.repos
.as_ref()
.is_some_and(|repos| repos.public.is_some_and(|lfs| lfs == 0)));
assert!(usage
.repos
.is_some_and(|repos| repos.private.is_some_and(|lfs| lfs == 0)));
assert!(usage
.assets
.is_some_and(|assets| assets.artifacts.is_some_and(|lfs| lfs == 0)));
api.admin_remove_rule_from_quota_group("no doing anything", "blah")
.await
.expect("failed to delete rule from quota group");
api.admin_remove_user_from_quota_group("no doing anything", "salesman")
.await
.expect("failed to remove user from quota group");
api.admin_delete_quota_group("no doing anything")
.await
.expect("failed to delete quota group");
}

View file

@ -271,7 +271,8 @@ async fn release() {
"TestingAdmin",
"release-test",
release.id.unwrap() as u64,
b"This is a file!".to_vec(),
Some(b"This is a file!".to_vec()),
None,
RepoCreateReleaseAttachmentQuery {
name: Some("test.txt".into()),
},
@ -390,7 +391,7 @@ async fn team_pr_review_request() {
.repo_get_pull_request("team-review-org", "team-pr-review", 1)
.await
.expect("couldn't get pr");
assert_eq!(pr.requested_reviewers, Some(Vec::new()));
assert_eq!(pr.requested_reviewers, None);
}
#[tokio::test]

View file

@ -164,7 +164,7 @@ async fn oauth2_login() {
let code = code.unwrap();
// Redeem the code and check it works
let url = url::Url::parse(&base_url).unwrap();
let url = url::Url::parse(base_url).unwrap();
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::None, url.clone()).unwrap();
let request = forgejo_api::structs::OAuthTokenRequest::Confidential {