Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webserver, db): Implement github provided repositories #1800

Merged
merged 15 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ee/tabby-db/migrations/0024_github-provided-repos.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE github_provided_repositories;
10 changes: 10 additions & 0 deletions ee/tabby-db/migrations/0024_github-provided-repos.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE github_provided_repositories(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
boxbeam marked this conversation as resolved.
Show resolved Hide resolved
github_repository_provider_id INTEGER NOT NULL,
-- vendor_id from https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repositories-for-a-user
vendor_id TEXT NOT NULL,
boxbeam marked this conversation as resolved.
Show resolved Hide resolved
name TEXT NOT NULL,
git_url TEXT NOT NULL,
active BOOLEAN NOT NULL DEFAULT FALSE,
FOREIGN KEY (github_repository_provider_id) REFERENCES github_repository_provider(id) ON DELETE CASCADE
);
Binary file modified ee/tabby-db/schema.sqlite
Binary file not shown.
89 changes: 89 additions & 0 deletions ee/tabby-db/src/github_repository_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
pub access_token: Option<String>,
}

#[derive(FromRow)]
pub struct GithubProvidedRepositoryDAO {
pub id: i64,
pub vendor_id: String,
pub github_repository_provider_id: i64,
pub name: String,
pub git_url: String,
pub active: bool,
}

impl DbConn {
pub async fn create_github_provider(
&self,
Expand Down Expand Up @@ -95,4 +105,83 @@
.await?;
Ok(providers)
}

pub async fn create_github_provided_repository(
&self,
github_provider_id: i64,
vendor_id: String,
name: String,
git_url: String,
) -> Result<()> {
query!("INSERT INTO github_provided_repositories (github_repository_provider_id, vendor_id, name, git_url) VALUES (?, ?, ?, ?)",
github_provider_id, vendor_id, name, git_url).execute(&self.pool).await?;
Ok(())
}

Check warning on line 119 in ee/tabby-db/src/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/github_repository_provider.rs#L109-L119

Added lines #L109 - L119 were not covered by tests

pub async fn delete_github_provided_repository(&self, id: i64) -> Result<()> {
let res = query!("DELETE FROM github_provided_repositories WHERE id = ?", id)
.execute(&self.pool)
.await?;

Check warning on line 124 in ee/tabby-db/src/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/github_repository_provider.rs#L121-L124

Added lines #L121 - L124 were not covered by tests

if res.rows_affected() != 1 {
return Err(anyhow!("Repository not found"));
}
Ok(())
}

Check warning on line 130 in ee/tabby-db/src/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/github_repository_provider.rs#L126-L130

Added lines #L126 - L130 were not covered by tests

pub async fn list_github_provided_repositories(
&self,
provider_ids: Vec<i64>,
limit: Option<usize>,
skip_id: Option<i32>,
backwards: bool,
) -> Result<Vec<GithubProvidedRepositoryDAO>> {
let provider_ids = provider_ids
.into_iter()
.map(|id| id.to_string())
.collect::<Vec<_>>()
.join(", ");
let repos = query_paged_as!(
GithubProvidedRepositoryDAO,
"github_provided_repositories",
[
"id",
"vendor_id",
"name",
"git_url",
"active",
"github_repository_provider_id"
],
limit,
skip_id,
backwards,
(!provider_ids.is_empty())
.then(|| format!("github_repository_provider_id IN ({provider_ids})"))
)
.fetch_all(&self.pool)
.await?;
Ok(repos)
}

Check warning on line 164 in ee/tabby-db/src/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/github_repository_provider.rs#L132-L164

Added lines #L132 - L164 were not covered by tests

pub async fn update_github_provided_repository_active(
&self,
id: i64,
active: bool,
) -> Result<()> {
let not_active = !active;
let res = query!(
"UPDATE github_provided_repositories SET active = ? WHERE id = ? AND active = ?",
active,
id,
not_active
)
.execute(&self.pool)
.await?;

Check warning on line 179 in ee/tabby-db/src/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/github_repository_provider.rs#L166-L179

Added lines #L166 - L179 were not covered by tests

if res.rows_affected() != 1 {
return Err(anyhow!("Repository active status was not changed"));
}

Ok(())
}

Check warning on line 186 in ee/tabby-db/src/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-db/src/github_repository_provider.rs#L181-L186

Added lines #L181 - L186 were not covered by tests
}
2 changes: 1 addition & 1 deletion ee/tabby-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cache::Cache;
use cached::TimedSizedCache;
use chrono::{DateTime, NaiveDateTime, Utc};
pub use email_setting::EmailSettingDAO;
pub use github_repository_provider::GithubRepositoryProviderDAO;
pub use github_repository_provider::{GithubProvidedRepositoryDAO, GithubRepositoryProviderDAO};
pub use invitations::InvitationDAO;
pub use job_runs::JobRunDAO;
pub use oauth_credential::OAuthCredentialDAO;
Expand Down
25 changes: 23 additions & 2 deletions ee/tabby-webserver/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ enum AuthMethod {
LOGIN
}

type GithubProvidedRepositoryConnection {
edges: [GithubProvidedRepositoryEdge!]!
pageInfo: PageInfo!
}

type RegisterResponse {
accessToken: String!
refreshToken: String!
Expand Down Expand Up @@ -175,6 +180,7 @@ type Mutation {
deleteEmailSetting: Boolean!
uploadLicense(license: String!): Boolean!
resetLicense: Boolean!
updateGithubProvidedRepositoryActive(id: ID!, active: Boolean!): Boolean!
}

type RepositoryEdge {
Expand All @@ -192,8 +198,13 @@ type FileEntrySearchResult {
indices: [Int!]!
}

input NetworkSettingInput {
externalUrl: String!
type GithubProvidedRepository {
id: ID!
vendorId: String!
githubRepositoryProviderId: ID!
name: String!
gitUrl: String!
active: Boolean!
}

type Query {
Expand All @@ -204,6 +215,7 @@ type Query {
users(after: String, before: String, first: Int, last: Int): UserConnection!
invitations(after: String, before: String, first: Int, last: Int): InvitationConnection!
githubRepositoryProviders(after: String, before: String, first: Int, last: Int): GithubRepositoryProviderConnection!
githubRepositories(providerIds: [ID!]!, after: String, before: String, first: Int, last: Int): GithubProvidedRepositoryConnection!
jobRuns(ids: [ID!], jobs: [String!], after: String, before: String, first: Int, last: Int): JobRunConnection!
jobRunStats(jobs: [String!]): JobStats!
emailSetting: EmailSetting
Expand All @@ -221,6 +233,10 @@ type Query {
dailyStats(start: DateTimeUtc!, end: DateTimeUtc!, users: [ID!], languages: [Language!]): [CompletionStats!]!
}

input NetworkSettingInput {
externalUrl: String!
}

enum Encryption {
START_TLS
SSL_TLS
Expand Down Expand Up @@ -328,6 +344,11 @@ type PageInfo {
endCursor: String
}

type GithubProvidedRepositoryEdge {
node: GithubProvidedRepository!
cursor: String!
}

type Repository {
id: ID!
name: String!
Expand Down
6 changes: 5 additions & 1 deletion ee/tabby-webserver/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,11 @@
)
.nest(
"/integrations/github",
integrations::github::routes(ctx.setting(), ctx.github_repository_provider()),
integrations::github::routes(
ctx.auth(),
ctx.setting(),
ctx.github_repository_provider(),
),

Check warning on line 151 in ee/tabby-webserver/src/handler.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/handler.rs#L147-L151

Added lines #L147 - L151 were not covered by tests
)
.route(
"/avatar/:id",
Expand Down
11 changes: 9 additions & 2 deletions ee/tabby-webserver/src/integrations/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use anyhow::Result;
use axum::{
extract::{Path, Query, State},
middleware::from_fn_with_state,
response::Redirect,
routing, Router,
};
Expand All @@ -12,8 +13,12 @@
use tracing::error;
use url::Url;

use crate::schema::{
github_repository_provider::GithubRepositoryProviderService, setting::SettingService,
use crate::{
handler::require_login_middleware,
schema::{
auth::AuthenticationService, github_repository_provider::GithubRepositoryProviderService,
setting::SettingService,
},
};

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -47,6 +52,7 @@
}

pub fn routes(
auth: Arc<dyn AuthenticationService>,

Check warning on line 55 in ee/tabby-webserver/src/integrations/github.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/integrations/github.rs#L55

Added line #L55 was not covered by tests
settings: Arc<dyn SettingService>,
github_repository_provider: Arc<dyn GithubRepositoryProviderService>,
) -> Router {
Expand All @@ -57,6 +63,7 @@
Router::new()
.route("/connect/:id", routing::get(connect))
.route("/callback", routing::get(callback))
.layer(from_fn_with_state(auth, require_login_middleware))

Check warning on line 66 in ee/tabby-webserver/src/integrations/github.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/integrations/github.rs#L66

Added line #L66 was not covered by tests
.with_state(state)
}

Expand Down
39 changes: 39 additions & 0 deletions ee/tabby-webserver/src/schema/github_repository_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,38 @@
}
}

#[derive(GraphQLObject, Debug)]

Check warning on line 32 in ee/tabby-webserver/src/schema/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/github_repository_provider.rs#L32

Added line #L32 was not covered by tests
#[graphql(context = Context)]
pub struct GithubProvidedRepository {
pub id: ID,
pub vendor_id: String,
pub github_repository_provider_id: ID,
pub name: String,
pub git_url: String,
pub active: bool,
}

impl NodeType for GithubProvidedRepository {
type Cursor = String;

fn cursor(&self) -> Self::Cursor {
self.id.to_string()
}

Check warning on line 48 in ee/tabby-webserver/src/schema/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/github_repository_provider.rs#L46-L48

Added lines #L46 - L48 were not covered by tests

fn connection_type_name() -> &'static str {
"GithubProvidedRepositoryConnection"
}

Check warning on line 52 in ee/tabby-webserver/src/schema/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/github_repository_provider.rs#L50-L52

Added lines #L50 - L52 were not covered by tests

fn edge_type_name() -> &'static str {
"GithubProvidedRepositoryEdge"
}

Check warning on line 56 in ee/tabby-webserver/src/schema/github_repository_provider.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/github_repository_provider.rs#L54-L56

Added lines #L54 - L56 were not covered by tests
}

#[async_trait]
pub trait GithubRepositoryProviderService: Send + Sync {
async fn get_github_repository_provider(&self, id: ID) -> Result<GithubRepositoryProvider>;
async fn read_github_repository_provider_secret(&self, id: ID) -> Result<String>;
async fn read_github_repository_provider_access_token(&self, id: ID) -> Result<String>;
boxbeam marked this conversation as resolved.
Show resolved Hide resolved
async fn update_github_repository_provider_access_token(
&self,
id: ID,
Expand All @@ -46,4 +74,15 @@
first: Option<usize>,
last: Option<usize>,
) -> Result<Vec<GithubRepositoryProvider>>;

async fn list_github_provided_repositories_by_provider(
&self,
provider: Vec<ID>,
after: Option<String>,
before: Option<String>,
first: Option<usize>,
last: Option<usize>,
) -> Result<Vec<GithubProvidedRepository>>;

async fn update_github_provided_repository_active(&self, id: ID, active: bool) -> Result<()>;
}
47 changes: 46 additions & 1 deletion ee/tabby-webserver/src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
RequestInvitationInput, RequestPasswordResetEmailInput, UpdateOAuthCredentialInput,
},
email::{EmailService, EmailSetting, EmailSettingInput},
github_repository_provider::{GithubRepositoryProvider, GithubRepositoryProviderService},
github_repository_provider::{
GithubProvidedRepository, GithubRepositoryProvider, GithubRepositoryProviderService,
},
job::JobStats,
license::{IsLicenseValid, LicenseInfo, LicenseService, LicenseType},
repository::{Repository, RepositoryService},
Expand Down Expand Up @@ -254,6 +256,37 @@
.await
}

async fn github_repositories(
ctx: &Context,
provider_ids: Vec<ID>,
after: Option<String>,
before: Option<String>,
first: Option<i32>,
last: Option<i32>,
) -> FieldResult<Connection<GithubProvidedRepository>> {
check_admin(ctx).await?;
relay::query_async(
after,
before,
first,
last,
|after, before, first, last| async move {
Ok(ctx
.locator
.github_repository_provider()
.list_github_provided_repositories_by_provider(
provider_ids,
after,
before,
first,
last,
)
.await?)
},

Check warning on line 285 in ee/tabby-webserver/src/schema/mod.rs

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/mod.rs#L273-L285

Added lines #L273 - L285 were not covered by tests
)
.await
}

async fn job_runs(
ctx: &Context,
ids: Option<Vec<ID>>,
Expand Down Expand Up @@ -669,6 +702,18 @@
ctx.locator.license().reset_license().await?;
Ok(true)
}

async fn update_github_provided_repository_active(
ctx: &Context,
id: ID,
active: bool,
) -> Result<bool> {
ctx.locator
.github_repository_provider()
.update_github_provided_repository_active(id, active)
.await?;
Ok(true)
}
}

async fn check_analytic_access(ctx: &Context, users: &[ID]) -> Result<(), CoreError> {
Expand Down
Loading
Loading