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
  • Loading branch information
axosoft-ramint committed Sep 25, 2023
1 parent 5b2e46a commit 8e024de
Show file tree
Hide file tree
Showing 14 changed files with 1,724 additions and 190 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14789,6 +14789,7 @@
},
"dependencies": {
"@gitkraken/gitkraken-components": "10.1.25",
"@gitkraken/provider-apis": "^0.6.3",
"@gitkraken/shared-web-components": "^0.1.1-rc.6",
"@microsoft/fast-element": "1.12.0",
"@microsoft/fast-react-wrapper": "0.3.19",
Expand Down
19 changes: 16 additions & 3 deletions src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ 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 { AccountAuthenticationProvider } from './plus/gk/authenticationProvider';
import { ServerConnection } from './plus/gk/serverConnection';
import { IntegrationAuthenticationService } from './plus/integrationAuthentication';
import { AzureDevOpsAuthenticationProvider } from './plus/integration/azureDevOps';
import { BitbucketAuthenticationProvider } from './plus/integration/bitbucket';
import { GitHubAuthenticationProvider } from './plus/integration/github';
import { GitLabAuthenticationProvider } from './plus/integration/gitlab';
import { IntegrationAuthenticationService } from './plus/integration/integrationAuthentication';
import { ProvidersService } from './plus/providers/providersService';
import { SubscriptionService } from './plus/subscription/subscriptionService';
import { registerAccountWebviewView } from './plus/webviews/account/registration';
import { registerFocusWebviewPanel } from './plus/webviews/focus/registration';
Expand Down Expand Up @@ -510,6 +513,8 @@ export class Container {
// Register any integration authentication providers
new GitHubAuthenticationProvider(this),
new GitLabAuthenticationProvider(this),
new AzureDevOpsAuthenticationProvider(this),
new BitbucketAuthenticationProvider(this),
);
}

Expand Down Expand Up @@ -551,6 +556,14 @@ export class Container {
return this._prerelease || this.debugging;
}

private _providers: ProvidersService | undefined;
get providers(): ProvidersService {
if (this._providers == null) {
this._providers = new ProvidersService(this);
}
return this._providers;
}

private readonly _rebaseEditor: RebaseEditorProvider;
get rebaseEditor() {
return this._rebaseEditor;
Expand Down
93 changes: 2 additions & 91 deletions src/git/remotes/github.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
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 { log } from '../../system/decorators/log';
import { memoize } from '../../system/decorators/memoize';
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 @@ -376,87 +371,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,17 +1,11 @@
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 { AutolinkType } 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 @@ -389,88 +383,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/integration/integrationAuthentication';
import { isSubscriptionPaidPlan, isSubscriptionPreviewTrialExpired } from '../../subscription';
import { configuration } from '../../system/configuration';
import { gate } from '../../system/decorators/gate';
Expand Down
Loading

0 comments on commit 8e024de

Please sign in to comment.