Skip to content

Commit

Permalink
[server] remove unused RepositoryService.canInstallAutomatedPrebuilds
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexTugarev committed Nov 22, 2023
1 parent aa5f1dc commit ac7fe43
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 140 deletions.
32 changes: 0 additions & 32 deletions components/server/src/prebuilds/bitbucket-server-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,38 +89,6 @@ class TestBitbucketServerService {
};
}

@test async test_canInstallAutomatedPrebuilds_unauthorized() {
const result = await this.service.canInstallAutomatedPrebuilds(
this.user,
"https://bitbucket.gitpod-self-hosted.com/users/jldec/repos/test-repo",
);
expect(result).to.be.false;
}

@test async test_canInstallAutomatedPrebuilds_in_project_ok() {
const result = await this.service.canInstallAutomatedPrebuilds(
this.user,
"https://bitbucket.gitpod-self-hosted.com/projects/jldec/repos/jldec-repo-march-30",
);
expect(result).to.be.true;
}

@test async test_canInstallAutomatedPrebuilds_ok() {
const result = await this.service.canInstallAutomatedPrebuilds(
this.user,
"https://bitbucket.gitpod-self-hosted.com/projects/FOO/repos/repo123",
);
expect(result).to.be.true;
}

@test async test_canInstallAutomatedPrebuilds_users_project_ok() {
const result = await this.service.canInstallAutomatedPrebuilds(
this.user,
"https://bitbucket.gitpod-self-hosted.com/scm/~alextugarev/yolo.git",
);
expect(result).to.be.true;
}

@test async test_installAutomatedPrebuilds_ok() {
try {
await this.service.installAutomatedPrebuilds(
Expand Down
37 changes: 8 additions & 29 deletions components/server/src/prebuilds/bitbucket-server-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service";
import { ProviderRepository, User } from "@gitpod/gitpod-protocol";
import { inject, injectable } from "inversify";
import { BitbucketServerApi } from "../bitbucket-server/bitbucket-server-api";
import { AuthProviderParams } from "../auth/auth-provider";
import { BitbucketServerContextParser } from "../bitbucket-server/bitbucket-server-context-parser";
import { Config } from "../config";
import { TokenService } from "../user/token-service";
Expand All @@ -19,11 +18,14 @@ import { CancellationToken } from "vscode-jsonrpc";
export class BitbucketServerService extends RepositoryService {
static PREBUILD_TOKEN_SCOPE = "prebuilds";

@inject(BitbucketServerApi) protected api: BitbucketServerApi;
@inject(Config) protected readonly config: Config;
@inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams;
@inject(TokenService) protected tokenService: TokenService;
@inject(BitbucketServerContextParser) protected contextParser: BitbucketServerContextParser;
constructor(
@inject(BitbucketServerApi) private readonly api: BitbucketServerApi,
@inject(Config) private readonly config: Config,
@inject(TokenService) private readonly tokenService: TokenService,
@inject(BitbucketServerContextParser) private readonly contextParser: BitbucketServerContextParser,
) {
super();
}

async getRepositoriesForAutomatedPrebuilds(
user: User,
Expand All @@ -44,29 +46,6 @@ export class BitbucketServerService extends RepositoryService {
});
}

async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise<boolean> {
const { host, repoKind, owner, repoName } = await this.contextParser.parseURL(user, cloneUrl);
if (host !== this.authProviderConfig.host) {
return false;
}

const identity = user.identities.find((i) => i.authProviderId === this.authProviderConfig.id);
if (!identity) {
console.error(`BBS: no identity found.`, { host: this.authProviderConfig.host, userId: user.id, cloneUrl });
return false;
}

try {
await this.api.getWebhooks(user, { repoKind, repositorySlug: repoName, owner });
// reading webhooks to check if admin scope is provided
} catch (error) {
console.log(`BBS: could not read webhooks.`, error, { error, cloneUrl });
return false;
}
// return true once it can get webhooks, fallback to let SCM itself to check permission
return true;
}

async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise<void> {
const { owner, repoName, repoKind } = await this.contextParser.parseURL(user, cloneUrl);

Expand Down
26 changes: 7 additions & 19 deletions components/server/src/prebuilds/bitbucket-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service";
import { User } from "@gitpod/gitpod-protocol";
import { inject, injectable } from "inversify";
import { BitbucketApiFactory } from "../bitbucket/bitbucket-api-factory";
import { AuthProviderParams } from "../auth/auth-provider";
import { BitbucketApp } from "./bitbucket-app";
import { Config } from "../config";
import { TokenService } from "../user/token-service";
Expand All @@ -18,24 +17,13 @@ import { BitbucketContextParser } from "../bitbucket/bitbucket-context-parser";
export class BitbucketService extends RepositoryService {
static PREBUILD_TOKEN_SCOPE = "prebuilds";

@inject(BitbucketApiFactory) protected api: BitbucketApiFactory;
@inject(Config) protected readonly config: Config;
@inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams;
@inject(TokenService) protected tokenService: TokenService;
@inject(BitbucketContextParser) protected bitbucketContextParser: BitbucketContextParser;

async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise<boolean> {
const { host, owner, repoName } = await this.bitbucketContextParser.parseURL(user, cloneUrl);
if (host !== this.authProviderConfig.host) {
return false;
}

// only admins may install webhooks on repositories
const api = await this.api.create(user);
const response = await api.user.listPermissionsForRepos({
q: `repository.full_name="${owner}/${repoName}"`,
});
return !!response.data?.values && response.data.values[0]?.permission === "admin";
constructor(
@inject(BitbucketApiFactory) private readonly api: BitbucketApiFactory,
@inject(Config) private readonly config: Config,
@inject(TokenService) private readonly tokenService: TokenService,
@inject(BitbucketContextParser) private readonly bitbucketContextParser: BitbucketContextParser,
) {
super();
}

async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise<void> {
Expand Down
41 changes: 9 additions & 32 deletions components/server/src/prebuilds/github-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service";
import { inject, injectable } from "inversify";
import { GitHubGraphQlEndpoint, GitHubRestApi } from "../github/api";
import { GitHubEnterpriseApp } from "./github-enterprise-app";
import { AuthProviderParams } from "../auth/auth-provider";
import { GithubContextParser } from "../github/github-context-parser";
import { ProviderRepository, User } from "@gitpod/gitpod-protocol";
import { Config } from "../config";
Expand All @@ -18,12 +17,15 @@ import { TokenService } from "../user/token-service";
export class GitHubService extends RepositoryService {
static PREBUILD_TOKEN_SCOPE = "prebuilds";

@inject(GitHubGraphQlEndpoint) protected readonly githubQueryApi: GitHubGraphQlEndpoint;
@inject(GitHubRestApi) protected readonly githubApi: GitHubRestApi;
@inject(Config) protected readonly config: Config;
@inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams;
@inject(TokenService) protected tokenService: TokenService;
@inject(GithubContextParser) protected githubContextParser: GithubContextParser;
constructor(
@inject(GitHubGraphQlEndpoint) protected readonly githubQueryApi: GitHubGraphQlEndpoint,
@inject(GitHubRestApi) protected readonly githubApi: GitHubRestApi,
@inject(Config) private readonly config: Config,
@inject(TokenService) private readonly tokenService: TokenService,
@inject(GithubContextParser) private readonly githubContextParser: GithubContextParser,
) {
super();
}

// TODO: consider refactoring this to either use GH Search API w/ typeahead search only OR
// return results in a stream, appending pages as being fetched (via callback below) OR
Expand Down Expand Up @@ -53,31 +55,6 @@ export class GitHubService extends RepositoryService {
return repositories;
}

async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise<boolean> {
const { host, owner, repoName: repo } = await this.githubContextParser.parseURL(user, cloneUrl);
if (host !== this.authProviderConfig.host) {
return false;
}
try {
// You need "ADMIN" permission on a repository to be able to install a webhook.
// Ref: https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role
// Ref: https://docs.github.com/en/graphql/reference/enums#repositorypermission
const result: any = await this.githubQueryApi.runQuery(
user,
`
query {
repository(name: "${repo}", owner: "${owner}") {
viewerPermission
}
}
`,
);
return result.data.repository && result.data.repository.viewerPermission === "ADMIN";
} catch (err) {
return false;
}
}

async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise<void> {
const { owner, repoName: repo } = await this.githubContextParser.parseURL(user, cloneUrl);
const webhooks = (await this.githubApi.run(user, (gh) => gh.repos.listWebhooks({ owner, repo }))).data;
Expand Down
29 changes: 8 additions & 21 deletions components/server/src/prebuilds/gitlab-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service";
import { User } from "@gitpod/gitpod-protocol";
import { inject, injectable } from "inversify";
import { GitLabApi, GitLab } from "../gitlab/api";
import { AuthProviderParams } from "../auth/auth-provider";
import { GitLabApp } from "./gitlab-app";
import { Config } from "../config";
import { TokenService } from "../user/token-service";
Expand All @@ -19,25 +18,13 @@ import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
export class GitlabService extends RepositoryService {
static PREBUILD_TOKEN_SCOPE = "prebuilds";

@inject(GitLabApi) protected api: GitLabApi;
@inject(Config) protected readonly config: Config;
@inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams;
@inject(TokenService) protected tokenService: TokenService;
@inject(GitlabContextParser) protected gitlabContextParser: GitlabContextParser;

async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise<boolean> {
const { host, owner, repoName } = await this.gitlabContextParser.parseURL(user, cloneUrl);
if (host !== this.authProviderConfig.host) {
return false;
}
const api = await this.api.create(user);
const response = (await api.Projects.show(`${owner}/${repoName}`)) as unknown as GitLab.Project;
if (GitLab.ApiError.is(response)) {
throw response;
}
// one need to have at least the access level of a maintainer (40) in order to install webhooks on a project
// cf. https://docs.gitlab.com/ee/api/members.html#valid-access-levels
return GitLab.Permissions.hasMaintainerAccess(response);
constructor(
@inject(GitLabApi) protected api: GitLabApi,
@inject(Config) private readonly config: Config,
@inject(TokenService) private readonly tokenService: TokenService,
@inject(GitlabContextParser) private readonly gitlabContextParser: GitlabContextParser,
) {
super();
}

async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise<void> {
Expand Down Expand Up @@ -69,7 +56,7 @@ export class GitlabService extends RepositoryService {
log.info("Installed Webhook for " + cloneUrl, { cloneUrl, userId: user.id });
}

protected getHookUrl() {
private getHookUrl() {
return this.config.hostUrl
.asPublicServices()
.with({
Expand Down
4 changes: 0 additions & 4 deletions components/server/src/repohost/repo-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ export class RepositoryService {
return [];
}

async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise<boolean> {
return false;
}

async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise<void> {
throw new Error("unsupported");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,6 @@ const mockApplyingContainerModule = new ContainerModule((bind, unbound, isbound,
installAutomatedPrebuilds: async (user: any, cloneUrl: string) => {
webhooks.add(cloneUrl);
},
canInstallAutomatedPrebuilds: async () => {
throw "not expected to be called";
},
},
repositoryProvider: {
hasReadAccess: async (user: any, owner: string, repo: string) => {
Expand Down

0 comments on commit ac7fe43

Please sign in to comment.