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 10 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<i64> {
let res = 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(res.last_insert_rowid())
}

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?;

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

Check warning on line 127 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#L127

Added line #L127 was not covered by tests
}
Ok(())
}

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())

Check warning on line 158 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#L145-L158

Added lines #L145 - L158 were not covered by tests
.then(|| format!("github_repository_provider_id IN ({provider_ids})"))
)

Check warning on line 160 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#L160

Added line #L160 was not covered by tests
.fetch_all(&self.pool)
.await?;
Ok(repos)
}

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?;

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

Check warning on line 182 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#L182

Added line #L182 was not covered by tests
}

Ok(())
}
}
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
48 changes: 48 additions & 0 deletions ee/tabby-webserver/src/schema/github_repository_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
pub id: ID,
pub display_name: String,
pub application_id: String,
pub access_token: Option<String>,
boxbeam marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub access_token: Option<String>,
pub access_token: String,

Copy link
Contributor Author

@boxbeam boxbeam Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The access token can be None (if the user has not gone through the OAuth connect flow yet), and this will only be used internally. I think we should prefer a closer representation of the data, since otherwise I'll be having to check if access_token.is_empty() instead.

}

impl GithubRepositoryProvider {
pub fn strip_access_token(self) -> Self {
Self {
access_token: None,
..self
}

Check warning on line 22 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#L17-L22

Added lines #L17 - L22 were not covered by tests
}
}

impl NodeType for GithubRepositoryProvider {
Expand All @@ -29,6 +39,33 @@
}
}

#[derive(GraphQLObject, Debug)]
#[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 57 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#L55-L57

Added lines #L55 - L57 were not covered by tests
}

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

Check warning on line 61 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#L59-L61

Added lines #L59 - L61 were not covered by tests
}

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

Check warning on line 65 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#L63-L65

Added lines #L63 - L65 were not covered by tests
}
}

#[async_trait]
pub trait GithubRepositoryProviderService: Send + Sync {
async fn get_github_repository_provider(&self, id: ID) -> Result<GithubRepositoryProvider>;
Expand All @@ -46,4 +83,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<()>;
}
50 changes: 49 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 @@ -248,6 +250,40 @@
.locator
.github_repository_provider()
.list_github_repository_providers(after, before, first, last)
.await?
.into_iter()
.map(|provider| provider.strip_access_token())
.collect())
},

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

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/mod.rs#L253-L257

Added lines #L253 - L257 were not covered by tests
)
.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,
)

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

View check run for this annotation

Codecov / codecov/patch

ee/tabby-webserver/src/schema/mod.rs#L276-L286

Added lines #L276 - L286 were not covered by tests
.await?)
},
)
Expand Down Expand Up @@ -669,6 +705,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