pub mod net;
pub mod robotstxt;
pub mod error;
pub mod responses;
pub mod forgejo;
pub mod gitlab;
use crate::{
config::SecretHeader,
handlers::templates::PercentEncoded,
network::{forgejo::ForgejoApi, gitlab::GitLabApi},
};
use async_trait::async_trait;
use net::Net;
use reqwest::header::{AUTHORIZATION, HeaderName};
use std::fmt::Debug;
use strum_macros::{Display, EnumIter, EnumString};
use url::Url;
#[derive(Clone, Copy, Debug, Display, EnumIter, EnumString, PartialEq)]
#[strum(ascii_case_insensitive)] pub enum ForgeApiKind {
Forgejo,
Gitea,
GitLab,
}
#[async_trait]
pub trait ForgeApi
where
Self: Sync + Send + Sized,
{
fn kind(&self) -> ForgeApiKind;
fn base_url(&self) -> &Url;
async fn get_branches(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
) -> Result<Vec<responses::Branch>, error::Error>;
async fn get_contents(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
branch_name: &PercentEncoded,
item_path: &PercentEncoded,
) -> Result<responses::Contents<responses::Item>, error::Error>;
async fn get_file_tree(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
) -> Result<Vec<responses::Item>, error::Error>;
async fn get_recent_repos(&self, net: &Net) -> Result<Vec<responses::Repo>, error::Error>;
async fn get_repo(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
) -> Result<responses::Repo, error::Error>;
async fn get_user_repos(
&self,
net: &Net,
username: &PercentEncoded,
) -> Result<Vec<responses::Repo>, error::Error>;
async fn get_users(&self, net: &Net) -> Result<Vec<responses::User>, error::Error>;
async fn get_version(&self, net: &Net) -> Result<responses::ServerVersion, error::Error>;
async fn check_access_token(&self, net: &Net) -> Result<(), error::Error>;
fn access_token_header_name(&self) -> HeaderName {
AUTHORIZATION
}
fn access_token_value(&self) -> Option<SecretHeader> {
None
}
}
pub enum Api {
Forgejo(ForgejoApi),
Gitea(ForgejoApi), GitLab(GitLabApi),
}
#[async_trait]
impl ForgeApi for Api {
fn kind(&self) -> ForgeApiKind {
match self {
Self::Forgejo(_) => ForgeApiKind::Forgejo,
Self::GitLab(_) => ForgeApiKind::GitLab,
Self::Gitea(_) => ForgeApiKind::Gitea,
}
}
fn base_url(&self) -> &Url {
match self {
Self::Forgejo(api) => api.base_url(),
Self::GitLab(api) => api.base_url(),
Self::Gitea(api) => api.base_url(),
}
}
async fn get_branches(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
) -> Result<Vec<responses::Branch>, error::Error> {
match self {
Self::Forgejo(api) => api.get_branches(net, username, repo_name).await,
Self::GitLab(api) => api.get_branches(net, username, repo_name).await,
Self::Gitea(api) => api.get_branches(net, username, repo_name).await,
}
}
async fn get_contents(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
branch_name: &PercentEncoded,
item_path: &PercentEncoded,
) -> Result<responses::Contents<responses::Item>, error::Error> {
match self {
Self::Forgejo(api) => {
api.get_contents(net, username, repo_name, branch_name, item_path)
.await
}
Self::GitLab(api) => {
api.get_contents(net, username, repo_name, branch_name, item_path)
.await
}
Self::Gitea(api) => {
api.get_contents(net, username, repo_name, branch_name, item_path)
.await
}
}
}
async fn get_file_tree(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
) -> Result<Vec<responses::Item>, error::Error> {
match self {
Self::Forgejo(api) => api.get_file_tree(net, username, repo_name).await,
Self::GitLab(api) => api.get_file_tree(net, username, repo_name).await,
Self::Gitea(api) => api.get_file_tree(net, username, repo_name).await,
}
}
async fn get_recent_repos(&self, net: &Net) -> Result<Vec<responses::Repo>, error::Error> {
match self {
Self::Forgejo(api) => api.get_recent_repos(net).await,
Self::GitLab(api) => api.get_recent_repos(net).await,
Self::Gitea(api) => api.get_recent_repos(net).await,
}
}
async fn get_repo(
&self,
net: &Net,
username: &PercentEncoded,
repo_name: &PercentEncoded,
) -> Result<responses::Repo, error::Error> {
match self {
Self::Forgejo(api) => api.get_repo(net, username, repo_name).await,
Self::GitLab(api) => api.get_repo(net, username, repo_name).await,
Self::Gitea(api) => api.get_repo(net, username, repo_name).await,
}
}
async fn get_user_repos(
&self,
net: &Net,
username: &PercentEncoded,
) -> Result<Vec<responses::Repo>, error::Error> {
match self {
Self::Forgejo(api) => api.get_user_repos(net, username).await,
Self::GitLab(api) => api.get_user_repos(net, username).await,
Self::Gitea(api) => api.get_user_repos(net, username).await,
}
}
async fn get_users(&self, net: &Net) -> Result<Vec<responses::User>, error::Error> {
match self {
Self::Forgejo(api) => api.get_users(net).await,
Self::GitLab(api) => api.get_users(net).await,
Self::Gitea(api) => api.get_users(net).await,
}
}
async fn get_version(&self, net: &Net) -> Result<responses::ServerVersion, error::Error> {
match self {
Self::Forgejo(api) => api.get_version(net).await,
Self::GitLab(api) => api.get_version(net).await,
Self::Gitea(api) => api.get_version(net).await,
}
}
async fn check_access_token(&self, net: &Net) -> Result<(), error::Error> {
match self {
Self::Forgejo(api) => api.check_access_token(net).await,
Self::GitLab(api) => api.check_access_token(net).await,
Self::Gitea(api) => api.check_access_token(net).await,
}
}
fn access_token_header_name(&self) -> HeaderName {
match self {
Self::Forgejo(api) => api.access_token_header_name(),
Self::GitLab(api) => api.access_token_header_name(),
Self::Gitea(api) => api.access_token_header_name(),
}
}
fn access_token_value(&self) -> Option<SecretHeader> {
match self {
Self::Forgejo(api) => api.access_token_value(),
Self::GitLab(api) => api.access_token_value(),
Self::Gitea(api) => api.access_token_value(),
}
}
}