Skip to content

Commit

Permalink
feat(webserver): allow specifying the url base for self-hosted github…
Browse files Browse the repository at this point in the history
…/gitlab instances
  • Loading branch information
boxbeam committed May 20, 2024
1 parent d618fa9 commit 0eccf2c
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 11 deletions.
1 change: 1 addition & 0 deletions ee/tabby-db/migrations/0029_merged-provider-tables.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ CREATE TABLE integrations(
kind TEXT NOT NULL,
display_name TEXT NOT NULL,
access_token TEXT NOT NULL,
url_base TEXT NOT NULL,
error TEXT,
created_at TIMESTAMP NOT NULL DEFAULT (DATETIME('now')),
updated_at TIMESTAMP NOT NULL DEFAULT (DATETIME('now')),
Expand Down
Binary file modified ee/tabby-db/schema.sqlite
Binary file not shown.
9 changes: 7 additions & 2 deletions ee/tabby-db/src/integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub struct IntegrationDAO {
pub error: Option<String>,
pub display_name: String,
pub access_token: String,
pub url_base: String,
pub created_at: DateTimeUtc,
pub updated_at: DateTimeUtc,
pub synced: bool,
Expand All @@ -22,12 +23,14 @@ impl DbConn {
kind: String,
name: String,
access_token: String,
url_base: String,
) -> Result<i64> {
let res = query!(
"INSERT INTO integrations(kind, display_name, access_token) VALUES (?, ?, ?);",
"INSERT INTO integrations(kind, display_name, access_token, url_base) VALUES (?, ?, ?, ?);",
kind,
name,
access_token
access_token,
url_base
)
.execute(&self.pool)
.await?;
Expand All @@ -43,6 +46,7 @@ impl DbConn {
error,
display_name,
access_token,
url_base,
updated_at,
created_at,
synced
Expand Down Expand Up @@ -144,6 +148,7 @@ impl DbConn {
"error",
"display_name",
"access_token",
"url_base",
"created_at",
"updated_at",
"synced"
Expand Down
1 change: 1 addition & 0 deletions ee/tabby-schema/src/dao.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ impl TryFrom<IntegrationDAO> for Integration {
kind: IntegrationKind::from_enum_str(&value.kind)?,
display_name: value.display_name,
access_token: value.access_token,
url_base: value.url_base,
created_at: *value.created_at,
updated_at: *value.updated_at,
status,
Expand Down
11 changes: 11 additions & 0 deletions ee/tabby-schema/src/schema/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ pub enum IntegrationKind {
Gitlab,
}

impl IntegrationKind {
pub fn default_url_base(&self) -> &'static str {
match self {
IntegrationKind::Github => "https://api.github.com",
IntegrationKind::Gitlab => "https://gitlab.com",
}
}
}

#[derive(PartialEq, Eq, Debug)]
pub enum IntegrationStatus {
Ready,
Expand All @@ -23,6 +32,7 @@ pub struct Integration {
pub kind: IntegrationKind,
pub display_name: String,
pub access_token: String,
pub url_base: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub status: IntegrationStatus,
Expand All @@ -35,6 +45,7 @@ pub trait IntegrationService: Send + Sync {
kind: IntegrationKind,
display_name: String,
access_token: String,
url_base: Option<String>,
) -> Result<ID>;

async fn delete_integration(&self, id: ID, kind: IntegrationKind) -> Result<()>;
Expand Down
2 changes: 2 additions & 0 deletions ee/tabby-schema/src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,7 @@ impl Mutation {
IntegrationKind::Github,
input.display_name,
input.access_token,
input.url_base,
)
.await?;
Ok(id)
Expand Down Expand Up @@ -907,6 +908,7 @@ impl Mutation {
IntegrationKind::Gitlab,
input.display_name,
input.access_token,
input.url_base,
)
.await?;
Ok(id)
Expand Down
2 changes: 2 additions & 0 deletions ee/tabby-schema/src/schema/repository/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub struct CreateRepositoryProviderInput {
pub display_name: String,
#[validate(length(code = "accessToken", min = 10, message = "Invalid access token"))]
pub access_token: String,
#[validate(url(code = "url_base"))]

Check failure on line 14 in ee/tabby-schema/src/schema/repository/types.rs

View workflow job for this annotation

GitHub Actions / ast-grep-lint

validate-requires-code

Validations requires code / message being set for frontend error display
pub url_base: Option<String>,
}

#[derive(GraphQLInputObject, Validate)]
Expand Down
10 changes: 8 additions & 2 deletions ee/tabby-webserver/src/service/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ impl IntegrationService for IntegrationServiceImpl {
kind: IntegrationKind,
display_name: String,
access_token: String,
url_base: Option<String>,
) -> Result<ID> {
let id = self
.db
.create_integration(kind.as_enum_str().to_string(), display_name, access_token)
.create_integration(
kind.as_enum_str().to_string(),
display_name,
access_token,
url_base.unwrap_or_else(|| kind.default_url_base().to_string()),
)
.await?;
let id = id.as_id();
let _ = self
Expand Down Expand Up @@ -125,7 +131,7 @@ mod tests {
let integration = Arc::new(create(db, background));

let id = integration
.create_integration(IntegrationKind::Gitlab, "id".into(), "secret".into())
.create_integration(IntegrationKind::Gitlab, "id".into(), "secret".into(), None)
.await
.unwrap();

Expand Down
26 changes: 22 additions & 4 deletions ee/tabby-webserver/src/service/repository/third_party.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,13 @@ impl ThirdPartyRepositoryService for ThirdPartyRepositoryServiceImpl {
provider.display_name
);

let repos = match fetch_all_repos(provider.kind.clone(), &provider.access_token).await {
let repos = match fetch_all_repos(
provider.kind.clone(),
&provider.access_token,
&provider.url_base,
)
.await
{
Ok(repos) => repos,
Err((e, true)) => {
self.integration
Expand Down Expand Up @@ -305,6 +311,7 @@ mod tests {
IntegrationKind::Github,
"test_id1".into(),
"test_secret".into(),
None,
)
.await
.unwrap();
Expand All @@ -314,6 +321,7 @@ mod tests {
IntegrationKind::Github,
"test_id2".into(),
"test_secret".into(),
None,
)
.await
.unwrap();
Expand Down Expand Up @@ -402,7 +410,12 @@ mod tests {
let (repository, integration) = create_fake().await;

let provider_id = integration
.create_integration(IntegrationKind::Github, "provider1".into(), "token".into())
.create_integration(
IntegrationKind::Github,
"provider1".into(),
"token".into(),
None,
)
.await
.unwrap();

Expand Down Expand Up @@ -442,7 +455,12 @@ mod tests {

// Test gitlab urls are formatted properly
let provider_id2 = integration
.create_integration(IntegrationKind::Gitlab, "provider2".into(), "token2".into())
.create_integration(
IntegrationKind::Gitlab,
"provider2".into(),
"token2".into(),
None,
)
.await
.unwrap();

Expand Down Expand Up @@ -488,7 +506,7 @@ mod tests {
let (repository, integration) = create_fake().await;

let provider_id = integration
.create_integration(IntegrationKind::Github, "gh".into(), "token".into())
.create_integration(IntegrationKind::Github, "gh".into(), "token".into(), None)
.await
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ pub struct RepositoryInfo {
pub async fn fetch_all_repos(
kind: IntegrationKind,
access_token: &str,
url_base: &str,
) -> Result<Vec<RepositoryInfo>, (anyhow::Error, bool)> {
match kind {
IntegrationKind::Github => match fetch_all_github_repos(access_token).await {
IntegrationKind::Github => match fetch_all_github_repos(access_token, url_base).await {
Ok(repos) => Ok(repos),
Err(octocrab::Error::GitHub {
source: source @ GitHubError { .. },
..
}) if source.status_code.is_client_error() => Err((source.into(), true)),
Err(e) => Err((e.into(), false)),
},
IntegrationKind::Gitlab => match fetch_all_gitlab_repos(access_token).await {
IntegrationKind::Gitlab => match fetch_all_gitlab_repos(access_token, url_base).await {
Ok(repos) => Ok(repos),
Err(e) => {
let client_error = e.is_client_error();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ use super::RepositoryInfo;

pub async fn fetch_all_github_repos(
access_token: &str,
base_url: &str,
) -> Result<Vec<RepositoryInfo>, octocrab::Error> {
let octocrab = Octocrab::builder()
.base_uri(base_url)?
.user_access_token(access_token.to_string())
.build()?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@ impl GitlabError {

pub async fn fetch_all_gitlab_repos(
access_token: &str,
url_base: &str,
) -> Result<Vec<RepositoryInfo>, GitlabError> {
let gitlab = GitlabBuilder::new("gitlab.com", access_token)
// Gitlab client expects a url base like "gitlab.com" not "https://gitlab.com"
// We still want to take a more consistent format as user input, so this
// will help normalize it to prevent confusion
let base_url = url_base.strip_prefix("https://").unwrap_or(url_base);
let gitlab = GitlabBuilder::new(base_url, access_token)
.build_async()
.await?;
let repos: Vec<GitlabRepository> = gitlab::api::paged(
Expand Down

0 comments on commit 0eccf2c

Please sign in to comment.