Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexTugarev committed Feb 9, 2022
1 parent 1cfbf1a commit ad66981
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 182 deletions.
39 changes: 22 additions & 17 deletions components/server/src/bitbucket-server/bitbucket-api-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
*/

import { User, Token } from "@gitpod/gitpod-protocol";
import { APIClient, Bitbucket } from "bitbucket";
import { inject, injectable } from "inversify";
import { AuthProviderParams } from "../auth/auth-provider";
import { BitbucketTokenHelper } from "../bitbucket/bitbucket-token-handler";
import * as BitbucketServer from "@atlassian/bitbucket-server";

@injectable()
export class BitbucketServerApiFactory {
Expand All @@ -20,35 +20,40 @@ export class BitbucketServerApiFactory {
* Returns a Bitbucket API client for the given user.
* @param user The user the API client should be created for.
*/
public async create(user: User): Promise<APIClient> {
public async create(user: User): Promise<BitbucketServer> {
const token = await this.tokenHelper.getTokenWithScopes(user, []);
return this.createBitbucket(this.baseUrl, token);
}

protected createBitbucket(baseUrl: string, token: Token): APIClient {
return new Bitbucket({
protected createBitbucket(baseUrl: string, token: Token): BitbucketServer {
const options = {
baseUrl,
auth: {
token: token.value
}
});
};
const client = new BitbucketServer(options);
client.authenticate({
type: "token",
token: token.value
})
return client;
}

protected get baseUrl(): string {
return `https://api.${this.config.host}/2.0`;
return `https://${this.config.host}/rest/api/1.0`;
}
}

@injectable()
export class BasicAuthBitbucketServerApiFactory extends BitbucketServerApiFactory {
protected createBitbucket(baseUrl: string, token: Token): APIClient {

return new Bitbucket({
protected createBitbucket(baseUrl: string, token: Token): BitbucketServer {
const options = {
baseUrl,
auth: {
username: token.username!,
password: token.value
}
});
};
const client = new BitbucketServer(options);
client.authenticate({
type: "basic",
username: token.username || "nobody",
password: token.value
})
return client;
}
}
84 changes: 84 additions & 0 deletions components/server/src/bitbucket-server/bitbucket-server-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License-AGPL.txt in the project root for license information.
*/


declare namespace BitbucketServer {

export namespace Schema {
export interface Repository {
id: number;
slug: string;
name: string;
public: boolean;
links: {
clone: {
href: string;
name: string;
}[]
}
project: Project;
}

export interface Project {
key: string;
id: number;
name: string;
public: boolean;
}
}
}


// {
// "slug": "test123",
// "id": 3,
// "name": "test123",
// "hierarchyId": "670d2b6499d312c9deb8",
// "scmId": "git",
// "state": "AVAILABLE",
// "statusMessage": "Available",
// "forkable": true,
// "project": {
// "key": "JLDEC",
// "id": 2,
// "name": "jldec-project",
// "public": false,
// "type": "NORMAL",
// "links": {
// "self": ...
// }
// },
// "public": false,
// "links": {
// "clone": [
// ...,
// {
// "href": "https://bitbucket.gitpod-self-hosted.com/scm/jldec/test123.git",
// "name": "http"
// }
// ],
// "self": ...
// }
// }



// {
// "name": "roboquat",
// "emailAddress": "roboquat@gitpod.io",
// "id": 102,
// "displayName": "Robot Kumquat",
// "active": true,
// "slug": "roboquat",
// "type": "NORMAL",
// "links": {
// "self": [
// {
// "href": "https://bitbucket.gitpod-self-hosted.com/users/roboquat"
// }
// ]
// }
// }
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License-AGPL.txt in the project root for license information.
*/
Expand All @@ -12,7 +12,7 @@ import fetch from "node-fetch";
import { AuthUserSetup } from "../auth/auth-provider";
import { GenericAuthProvider } from "../auth/generic-auth-provider";
import { BitbucketServerOAuthScopes } from "./bitbucket-server-oauth-scopes";
import BitbucketServer = require("@atlassian/bitbucket-server")
import * as BitbucketServer from "@atlassian/bitbucket-server";

@injectable()
export class BitbucketServerAuthProvider extends GenericAuthProvider {
Expand Down Expand Up @@ -94,7 +94,7 @@ export class BitbucketServerAuthProvider extends GenericAuthProvider {
return <AuthUserSetup>{
authUser: {
authId: `${user.id!}`,
authName: user.name!,
authName: user.slug!,
primaryEmail: user.emailAddress!,
name: user.displayName!,
// avatarUrl: user.links!.avatar!.href // TODO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { NavigatorContext, Repository, User, WorkspaceContext } from "@gitpod/gitpod-protocol";
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing";
import { Schema } from "bitbucket";
import { Schema } from "@atlassian/bitbucket-server";
import { inject, injectable } from "inversify";
import { BitbucketTokenHelper } from "../bitbucket/bitbucket-token-handler";
import { NotFoundError } from "../errors";
Expand Down Expand Up @@ -47,34 +47,36 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
return undefined;
}

protected async isValidCommitHash(user: User, owner: string, repoName: string, potentialCommitHash: string) {
if (potentialCommitHash.length !== 40) {
return false;
}
// protected async isValidCommitHash(user: User, owner: string, repoName: string, potentialCommitHash: string) {
// if (potentialCommitHash.length !== 40) {
// return false;
// }
// try {
// const api = await this.api(user);
// const result = (await api.repositories.getCommit({ workspace: owner, repo_slug: repoName, commit: potentialCommitHash }));
// return result.data.hash === potentialCommitHash;
// } catch {
// return false;
// }
// }

// protected async isTag(user: User, owner: string, repoName: string, potentialTag: string) {
// try {
// const api = await this.api(user);
// const result = (await api.repositories.getTag({ workspace: owner, repo_slug: repoName, name: potentialTag }));
// return result.data.name === potentialTag;
// } catch {
// return false;
// }
// }

protected async handleNavigatorContext(ctx: TraceContext, user: User, host: string, owner: string, repoName: string, more: Partial<NavigatorContext> = {}): Promise<NavigatorContext> {
const span = TraceContext.startSpan("BitbucketServerContextParser.handleNavigatorContext", ctx);
try {
const api = await this.api(user);
const result = (await api.repositories.getCommit({ workspace: owner, repo_slug: repoName, commit: potentialCommitHash }));
return result.data.hash === potentialCommitHash;
} catch {
return false;
}
}

protected async isTag(user: User, owner: string, repoName: string, potentialTag: string) {
try {
const api = await this.api(user);
const result = (await api.repositories.getTag({ workspace: owner, repo_slug: repoName, name: potentialTag }));
return result.data.name === potentialTag;
} catch {
return false;
}
}
const repo = (await api.repos.getRepository({projectKey: owner, repositorySlug: repoName})).data;

protected async handleNavigatorContext(ctx: TraceContext, user: User, host: string, owner: string, repoName: string, more: Partial<NavigatorContext> = {}, givenRepo?: Schema.Repository): Promise<NavigatorContext> {
const span = TraceContext.startSpan("BitbucketServerContextParser.handleNavigatorContext", ctx);
try {
const api = await this.api(user);
const repo = givenRepo || (await api.repositories.get({ workspace: owner, repo_slug: repoName })).data;
const repository = await this.toRepository(user, host, repo);
span.log({ "request.finished": "" });

Expand All @@ -87,24 +89,24 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
}
more.refType = more.refType || "branch";

if (!more.revision) {
const commits = (await api.repositories.listCommitsAt({ workspace: owner, repo_slug: repoName, revision: more.ref!, pagelen: 1 })).data;
more.revision = commits.values && commits.values.length > 0 ? commits.values[0].hash : "";
if ((!commits.values || commits.values.length === 0) && more.ref === repository.defaultBranch) {
// empty repo
more.ref = undefined;
more.revision = "";
more.refType = undefined;
}
}

if (!more.path) {
more.isFile = false;
more.path = "";
} else if (more.isFile === undefined) {
const fileMeta = (await api.repositories.readSrc({ workspace: owner, repo_slug: repoName, format: "meta", commit: more.revision!, path: more.path!, pagelen: 1 })).data;
more.isFile = (fileMeta as any).type === "commit_file";
}
// if (!more.revision) {
// const commits = (await api.repositories.listCommitsAt({ workspace: owner, repo_slug: repoName, revision: more.ref!, pagelen: 1 })).data;
// more.revision = commits.values && commits.values.length > 0 ? commits.values[0].hash : "";
// if ((!commits.values || commits.values.length === 0) && more.ref === repository.defaultBranch) {
// // empty repo
// more.ref = undefined;
// more.revision = "";
// more.refType = undefined;
// }
// }

// if (!more.path) {
// more.isFile = false;
// more.path = "";
// } else if (more.isFile === undefined) {
// const fileMeta = (await api.repositories.readSrc({ workspace: owner, repo_slug: repoName, format: "meta", commit: more.revision!, path: more.path!, pagelen: 1 })).data;
// more.isFile = (fileMeta as any).type === "commit_file";
// }

return {
...more,
Expand All @@ -125,27 +127,26 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
if (!repo) {
throw new Error('Unknown repository.');
}
// full_name: string
// The concatenation of the repository owner's username and the slugified name, e.g. "evzijst/interruptingcow". This is the same string used in Bitbucket URLs.
const fullName = repo.full_name!.split("/");
const owner = fullName[0];
const name = fullName[1];

const owner = repo.project.key;
const name = repo.name;
const cloneUrl = repo.links.clone.find(u => u.name === "http")?.href!;

const result: Repository = {
cloneUrl: `https://${host}/${repo.full_name}.git`,
cloneUrl,
host,
name,
owner,
private: !!repo.isPrivate,
defaultBranch: repo.mainbranch ? repo.mainbranch.name : DEFAULT_BRANCH,
}
if (!!repo.parent && !!repo.parent.full_name) {
const api = await this.api(user);
const parentRepo = (await api.repositories.get({ workspace: repo.parent!.full_name!.split("/")[0], repo_slug: repo.parent!.full_name!.split("/")[1] })).data;
result.fork = {
parent: await this.toRepository(user, host, parentRepo)
};
private: !repo.public,
defaultBranch: DEFAULT_BRANCH,
}
// if (!!repo.parent && !!repo.parent.full_name) {
// const api = await this.api(user);
// const parentRepo = (await api.repositories.get({ workspace: repo.parent!.full_name!.split("/")[0], repo_slug: repo.parent!.full_name!.split("/")[1] })).data;
// result.fork = {
// parent: await this.toRepository(user, host, parentRepo)
// };
// }

return result;
}
Expand Down
Loading

0 comments on commit ad66981

Please sign in to comment.