Skip to content

Commit

Permalink
Adds basic providers api integration
Browse files Browse the repository at this point in the history
Adds filtering support on inputs

Improves types and adds getCurrentUser support

Updates getCurrentUser Fns

Adds GetReposFn for Azure

Reorganizes types and constants

Adds  providers service

Uses correct filter property for Bitbucket PRs

Switches to logged errors

Adds filter compatibility check

Adds paging and per-repo PR/Issue support

Uses PagedResult for paging

Updates dependencies

Updates dependency

Reorganizes and moves provider service logic to providerIntegration

Updates missing provider mappings, ProviderId usage

Updates provider api dependency

Adds enterprise domain passing and GLSH

Uses the correct base api urls

Updates dependency
  • Loading branch information
axosoft-ramint committed Oct 16, 2023
1 parent 925ffcc commit 5fa7f96
Show file tree
Hide file tree
Showing 20 changed files with 2,196 additions and 254 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14844,6 +14844,7 @@
},
"dependencies": {
"@gitkraken/gitkraken-components": "10.1.30",
"@gitkraken/provider-apis": "^0.8.1",
"@gitkraken/shared-web-components": "0.1.1-rc.15",
"@lit/react": "1.0.0",
"@microsoft/fast-element": "1.12.0",
Expand Down
12 changes: 8 additions & 4 deletions src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ import { Commands, extensionPrefix } from './constants';
import { EventBus } from './eventBus';
import { GitFileSystemProvider } from './git/fsProvider';
import { GitProviderService } from './git/gitProviderService';
import { GitHubAuthenticationProvider } from './git/remotes/github';
import { GitLabAuthenticationProvider } from './git/remotes/gitlab';
import { RichRemoteProviderService } from './git/remotes/remoteProviderService';
import { LineHoverController } from './hovers/lineHoverController';
import type { RepositoryPathMappingProvider } from './pathMapping/repositoryPathMappingProvider';
import { FocusService } from './plus/focus/focusService';
import { AccountAuthenticationProvider } from './plus/gk/authenticationProvider';
import { ServerConnection } from './plus/gk/serverConnection';
import { IntegrationAuthenticationService } from './plus/integrationAuthentication';
import { ProviderIntegrationService } from './plus/providers/providerIntegrationService';
import { AzureDevOpsAuthenticationProvider } from './plus/integrations/authentication/azureDevOps';
import { BitbucketAuthenticationProvider } from './plus/integrations/authentication/bitbucket';
import { GitHubAuthenticationProvider } from './plus/integrations/authentication/github';
import { GitLabAuthenticationProvider } from './plus/integrations/authentication/gitlab';
import { IntegrationAuthenticationService } from './plus/integrations/authentication/integrationAuthentication';
import { ProviderIntegrationService } from './plus/integrations/providers/providerIntegrationService';
import { SubscriptionService } from './plus/subscription/subscriptionService';
import { registerAccountWebviewView } from './plus/webviews/account/registration';
import { registerFocusWebviewPanel } from './plus/webviews/focus/registration';
Expand Down Expand Up @@ -521,6 +523,8 @@ export class Container {
// Register any integration authentication providers
new GitHubAuthenticationProvider(this),
new GitLabAuthenticationProvider(this),
new AzureDevOpsAuthenticationProvider(this),
new BitbucketAuthenticationProvider(this),
);
}

Expand Down
98 changes: 5 additions & 93 deletions src/git/remotes/github.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import type { AuthenticationSession, Disposable, QuickInputButton, Range } from 'vscode';
import { env, ThemeIcon, Uri, window } from 'vscode';
import type { AuthenticationSession, Range } from 'vscode';
import { Uri } from 'vscode';
import type { Autolink, DynamicAutolinkReference } from '../../annotations/autolinks';
import type { AutolinkReference } from '../../config';
import type { Container } from '../../container';
import type {
IntegrationAuthenticationProvider,
IntegrationAuthenticationSessionDescriptor,
} from '../../plus/integrationAuthentication';
import type { ProviderIntegration, RepositoryDescriptor } from '../../plus/providers/providerIntegration';
import { ProviderId } from '../../plus/integrations/providers/models';
import type { ProviderIntegration, RepositoryDescriptor } from '../../plus/integrations/providers/providerIntegration';
import { log } from '../../system/decorators/log';
import { memoize } from '../../system/decorators/memoize';
import { encodeUrl } from '../../system/encoding';
import { supportedInVSCodeVersion } from '../../system/utils';
import type { Account } from '../models/author';
import type { DefaultBranch } from '../models/defaultBranch';
import type { IssueOrPullRequest, SearchedIssue } from '../models/issue';
Expand Down Expand Up @@ -51,7 +47,7 @@ export class GitHubRemote extends RichRemoteProvider {
) {
super(container, domain, path, protocol, name, custom);

this._provider = container.providers.get(custom ? 'github-enterprise' : 'github', domain);
this._provider = container.providers.get(custom ? ProviderId.GitHubEnterprise : ProviderId.GitHub, domain);
}

get apiBaseUrl() {
Expand Down Expand Up @@ -460,87 +456,3 @@ export function getGitHubNoReplyAddressParts(
const [, userId, login, authority] = match;
return { userId: userId, login: login, authority: authority };
}

export class GitHubAuthenticationProvider implements Disposable, IntegrationAuthenticationProvider {
private readonly _disposable: Disposable;

constructor(container: Container) {
this._disposable = container.integrationAuthentication.registerProvider('github-enterprise', this);
}

dispose() {
this._disposable.dispose();
}

getSessionId(descriptor?: IntegrationAuthenticationSessionDescriptor): string {
return descriptor?.domain ?? '';
}

async createSession(
descriptor?: IntegrationAuthenticationSessionDescriptor,
): Promise<AuthenticationSession | undefined> {
const input = window.createInputBox();
input.ignoreFocusOut = true;

const disposables: Disposable[] = [];

let token;
try {
const infoButton: QuickInputButton = {
iconPath: new ThemeIcon(`link-external`),
tooltip: 'Open the GitHub Access Tokens Page',
};

token = await new Promise<string | undefined>(resolve => {
disposables.push(
input.onDidHide(() => resolve(undefined)),
input.onDidChangeValue(() => (input.validationMessage = undefined)),
input.onDidAccept(() => {
const value = input.value.trim();
if (!value) {
input.validationMessage = 'A personal access token is required';
return;
}

resolve(value);
}),
input.onDidTriggerButton(e => {
if (e === infoButton) {
void env.openExternal(
Uri.parse(`https://${descriptor?.domain ?? 'github.com'}/settings/tokens`),
);
}
}),
);

input.password = true;
input.title = `GitHub Authentication${descriptor?.domain ? ` \u2022 ${descriptor.domain}` : ''}`;
input.placeholder = `Requires ${descriptor?.scopes.join(', ') ?? 'all'} scopes`;
input.prompt = supportedInVSCodeVersion('input-prompt-links')
? `Paste your [GitHub Personal Access Token](https://${
descriptor?.domain ?? 'github.com'
}/settings/tokens "Get your GitHub Access Token")`
: 'Paste your GitHub Personal Access Token';

input.buttons = [infoButton];

input.show();
});
} finally {
input.dispose();
disposables.forEach(d => void d.dispose());
}

if (!token) return undefined;

return {
id: this.getSessionId(descriptor),
accessToken: token,
scopes: [],
account: {
id: '',
label: '',
},
};
}
}
93 changes: 1 addition & 92 deletions src/git/remotes/gitlab.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import type { AuthenticationSession, Disposable, QuickInputButton, Range } from 'vscode';
import { env, ThemeIcon, Uri, window } from 'vscode';
import type { AuthenticationSession, Range, Uri } from 'vscode';
import type { Autolink, DynamicAutolinkReference } from '../../annotations/autolinks';
import type { AutolinkReference } from '../../config';
import type { Container } from '../../container';
import type {
IntegrationAuthenticationProvider,
IntegrationAuthenticationSessionDescriptor,
} from '../../plus/integrationAuthentication';
import { log } from '../../system/decorators/log';
import { encodeUrl } from '../../system/encoding';
import { equalsIgnoreCase } from '../../system/string';
import { supportedInVSCodeVersion } from '../../system/utils';
import type { Account } from '../models/author';
import type { DefaultBranch } from '../models/defaultBranch';
import type { IssueOrPullRequest, SearchedIssue } from '../models/issue';
Expand Down Expand Up @@ -388,88 +382,3 @@ export class GitLabRemote extends RichRemoteProvider {
return Promise.resolve(undefined);
}
}

export class GitLabAuthenticationProvider implements Disposable, IntegrationAuthenticationProvider {
private readonly _disposable: Disposable;

constructor(container: Container) {
this._disposable = container.integrationAuthentication.registerProvider('gitlab', this);
}

dispose() {
this._disposable.dispose();
}

getSessionId(descriptor?: IntegrationAuthenticationSessionDescriptor): string {
return descriptor?.domain ?? '';
}

async createSession(
descriptor?: IntegrationAuthenticationSessionDescriptor,
): Promise<AuthenticationSession | undefined> {
const input = window.createInputBox();
input.ignoreFocusOut = true;

const disposables: Disposable[] = [];

let token;
try {
const infoButton: QuickInputButton = {
iconPath: new ThemeIcon(`link-external`),
tooltip: 'Open the GitLab Access Tokens Page',
};

token = await new Promise<string | undefined>(resolve => {
disposables.push(
input.onDidHide(() => resolve(undefined)),
input.onDidChangeValue(() => (input.validationMessage = undefined)),
input.onDidAccept(() => {
const value = input.value.trim();
if (!value) {
input.validationMessage = 'A personal access token is required';
return;
}

resolve(value);
}),
input.onDidTriggerButton(e => {
if (e === infoButton) {
void env.openExternal(
Uri.parse(
`https://${descriptor?.domain ?? 'gitlab.com'}/-/profile/personal_access_tokens`,
),
);
}
}),
);

input.password = true;
input.title = `GitLab Authentication${descriptor?.domain ? ` \u2022 ${descriptor.domain}` : ''}`;
input.placeholder = `Requires ${descriptor?.scopes.join(', ') ?? 'all'} scopes`;
input.prompt = input.prompt = supportedInVSCodeVersion('input-prompt-links')
? `Paste your [GitLab Personal Access Token](https://${
descriptor?.domain ?? 'gitlab.com'
}/-/profile/personal_access_tokens "Get your GitLab Access Token")`
: 'Paste your GitLab Personal Access Token';
input.buttons = [infoButton];

input.show();
});
} finally {
input.dispose();
disposables.forEach(d => void d.dispose());
}

if (!token) return undefined;

return {
id: this.getSessionId(descriptor),
accessToken: token,
scopes: [],
account: {
id: '',
label: '',
},
};
}
}
2 changes: 1 addition & 1 deletion src/git/remotes/richRemoteProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { isWeb } from '@env/platform';
import type { Container } from '../../container';
import { AuthenticationError, ProviderRequestClientError } from '../../errors';
import { showIntegrationDisconnectedTooManyFailedRequestsWarningMessage } from '../../messages';
import type { IntegrationAuthenticationSessionDescriptor } from '../../plus/integrationAuthentication';
import type { IntegrationAuthenticationSessionDescriptor } from '../../plus/integrations/authentication/integrationAuthentication';
import { isSubscriptionPaidPlan, isSubscriptionPreviewTrialExpired } from '../../subscription';
import { configuration } from '../../system/configuration';
import { gate } from '../../system/decorators/gate';
Expand Down
Loading

0 comments on commit 5fa7f96

Please sign in to comment.