Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 7533ada

Browse files
abeatrixtjkandalaStephen Gutekanst
authored
feat: token creation callback page (#35826)
Co-authored-by: TJ Kandala <[email protected]> Co-authored-by: Stephen Gutekanst <[email protected]>
1 parent 62e7f73 commit 7533ada

17 files changed

+534
-133
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ All notable changes to Sourcegraph are documented in this file.
5050
- Batch Changes are now supported on [Bitbucket Cloud](https://bitbucket.org/). [#24199](https://github.com/sourcegraph/sourcegraph/issues/24199)
5151
- Pings for server-side batch changes [#34308](https://github.com/sourcegraph/sourcegraph/pull/34308)
5252
- Indexed search will detect when it is misconfigured and has multiple replicas writing to the same directory. [#35513](https://github.com/sourcegraph/sourcegraph/pull/35513)
53+
- A new token creation callback feature that sends a token back to a trusted program automatically after the user has signed in [#35339](https://github.com/sourcegraph/sourcegraph/pull/35339)
5354

5455
### Changed
5556

client/vscode/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ The Sourcegraph extension uses major.EVEN_NUMBER.patch (eg. 2.0.1) for release v
77
### Changes
88

99
- Update Access Token headers setting method --thanks @ptxmac for the contribution! [issues/34338](https://github.com/sourcegraph/sourcegraph/issues/34338)
10+
- Add ability to import Sourcegraph Access token automatically after logging in on Sourcegraph Cloud [issues/28311](https://github.com/sourcegraph/sourcegraph/issues/28311)
1011

1112
### Fixes
1213

1314
- Windows file path issue [issues/34788](https://github.com/sourcegraph/sourcegraph/issues/34788)
15+
- Sourcegraph icon in help sidebar now shows on light theme [issues/35672](https://github.com/sourcegraph/sourcegraph/issues/35672)
1416

1517
## 2.2.2
1618

client/vscode/src/backend/instanceVersion.ts

+31-23
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,38 @@ import { requestGraphQLFromVSCode } from './requestGraphQl'
1212
* This function will return the EventSource Type based
1313
* on the instance version
1414
*/
15-
export function initializeInstantVersionNumber(localStorageService: LocalStorageService): EventSource {
16-
requestGraphQLFromVSCode<SiteVersionResult>(siteVersionQuery, {})
17-
.then(async siteVersionResult => {
18-
if (siteVersionResult.data) {
19-
// assume instance version longer than 8 is using insider version
20-
const flattenVersion =
21-
siteVersionResult.data.site.productVersion.length > 8
22-
? '999999'
23-
: siteVersionResult.data.site.productVersion.split('.').join('')
24-
if (flattenVersion < '3320') {
25-
displayWarning(
26-
'Your Sourcegraph instance version is not fully compatible with the Sourcegraph extension. Please ask your site admin to upgrade to version 3.32.0 or above. Read more about version support in our [troubleshooting docs](https://docs.sourcegraph.com/admin/how-to/troubleshoot-sg-extension#unsupported-features-by-sourcegraph-version).'
27-
).catch(() => {})
15+
export function initializeInstanceVersionNumber(
16+
localStorageService: LocalStorageService,
17+
instanceURL: string,
18+
accessToken: string | undefined
19+
): EventSource {
20+
// Check only if a user is trying to connect to a private instance with a valid access token provided
21+
if (instanceURL !== 'https://sourcegraph.com' && accessToken) {
22+
requestGraphQLFromVSCode<SiteVersionResult>(siteVersionQuery, {})
23+
.then(async siteVersionResult => {
24+
if (siteVersionResult.data) {
25+
// assume instance version longer than 8 is using insider version
26+
const flattenVersion =
27+
siteVersionResult.data.site.productVersion.length > 8
28+
? '999999'
29+
: siteVersionResult.data.site.productVersion.split('.').join('')
30+
if (flattenVersion < '3320') {
31+
displayWarning(
32+
'Your Sourcegraph instance version is not fully compatible with the Sourcegraph extension. Please ask your site admin to upgrade to version 3.32.0 or above. Read more about version support in our [troubleshooting docs](https://docs.sourcegraph.com/admin/how-to/troubleshoot-sg-extension#unsupported-features-by-sourcegraph-version).'
33+
).catch(() => {})
34+
}
35+
await localStorageService.setValue(INSTANCE_VERSION_NUMBER_KEY, flattenVersion)
2836
}
29-
await localStorageService.setValue(INSTANCE_VERSION_NUMBER_KEY, flattenVersion)
30-
}
31-
})
32-
.catch(error => {
33-
console.error('Failed to get instance version from host:', error)
34-
displayWarning('Cannot determine instance version number').catch(() => {})
35-
})
36-
const versionNumber = localStorageService.getValue(INSTANCE_VERSION_NUMBER_KEY)
37-
// instances below 3.38.0 does not support EventSource.IDEEXTENSION and should fallback to BACKEND source
38-
return versionNumber >= '3380' ? EventSource.IDEEXTENSION : EventSource.BACKEND
37+
})
38+
.catch(error => {
39+
console.error('Failed to get instance version from host:', error)
40+
displayWarning('Cannot determine instance version number').catch(() => {})
41+
})
42+
const versionNumber = localStorageService.getValue(INSTANCE_VERSION_NUMBER_KEY)
43+
// instances below 3.38.0 does not support EventSource.IDEEXTENSION and should fallback to BACKEND source
44+
return versionNumber >= '3380' ? EventSource.IDEEXTENSION : EventSource.BACKEND
45+
}
46+
return EventSource.IDEEXTENSION
3947
}
4048

4149
const siteVersionQuery = gql`

client/vscode/src/backend/requestGraphQl.ts

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const requestGraphQLFromVSCode = async <R, V = object>(
4747
query: request,
4848
variables,
4949
}),
50+
credentials: 'include',
5051
method: 'POST',
5152
headers,
5253
})

client/vscode/src/common/links.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* All Sourcegraph Cloud related links
3+
*/
4+
// MAIN
5+
const VSCE_CALLBACK_CODE = 'VSCEAUTH'
6+
export const VSCE_LINK_DOTCOM = 'https://sourcegraph.com'
7+
export const VSCE_LINK_TOKEN_CALLBACK =
8+
'https://sourcegraph.com/sign-in?returnTo=user/settings/tokens/new/callback?requestFrom=VSCEAUTH'
9+
export const VSCE_LINK_TOKEN_CALLBACK_TEST =
10+
'https://sourcegraph.test:3443/sign-in?returnTo=user/settings/tokens/new/callback?requestFrom=VSCEAUTH'
11+
12+
// PARAMS
13+
export const VSCE_SIDEBAR_PARAMS = '?utm_medium=VSCODE&utm_source=sidebar&utm_campaign=vsce-sign-up&utm_content=sign-up'
14+
const VSCE_LINK_PARAMS_TOKEN_REDIRECT = {
15+
returnTo: `user/settings/tokens/new/callback?requestFrom=${VSCE_CALLBACK_CODE}`,
16+
}
17+
const VSCE_LINK_PARAMS_EDITOR = { editor: 'vscode' }
18+
// UTM for Commands
19+
const VSCE_LINK_PARAMS_UTM_COMMANDS = {
20+
utm_campaign: 'vscode-extension',
21+
utm_medium: 'direct_traffic',
22+
utm_source: 'vscode-extension',
23+
utm_content: 'vsce-commands',
24+
}
25+
// UTM for Sidebar actions
26+
const VSCE_LINK_PARAMS_UTM_SIDEBAR = {
27+
utm_campaign: 'vsce-sign-up',
28+
utm_medium: 'VSCODE',
29+
utm_source: 'sidebar',
30+
utm_content: 'sign-up',
31+
}
32+
export const VSCE_COMMANDS_PARAMS = new URLSearchParams({ ...VSCE_LINK_PARAMS_UTM_COMMANDS }).toString()
33+
34+
// MISC
35+
export const VSCE_LINK_MARKETPLACE = 'https://marketplace.visualstudio.com/items?itemName=sourcegraph.sourcegraph'
36+
export const VSCE_LINK_USER_DOCS =
37+
'https://docs.sourcegraph.com/cli/how-tos/creating_an_access_token' + VSCE_SIDEBAR_PARAMS
38+
export const VSCE_LINK_FEEDBACK = 'https://github.com/sourcegraph/sourcegraph/discussions/categories/feedback'
39+
export const VSCE_LINK_ISSUES =
40+
'https://github.com/sourcegraph/sourcegraph/issues/new?labels=team/integrations,vscode-extension&title=VSCode+Bug+report:+&projects=Integrations%20Project%20Board'
41+
export const VSCE_LINK_TROUBLESHOOT =
42+
'https://docs.sourcegraph.com/admin/how-to/troubleshoot-sg-extension#vs-code-extension'
43+
export const VSCE_SG_LOGOMARK_LIGHT =
44+
'https://raw.githubusercontent.com/sourcegraph/sourcegraph/fd431743e811ba756490e5e7bd88aa2362b6453e/client/vscode/images/logomark_light.svg'
45+
export const VSCE_SG_LOGOMARK_DARK =
46+
'https://raw.githubusercontent.com/sourcegraph/sourcegraph/2636c64c9f323d78281a68dd4bdf432d9a97835a/client/vscode/images/logomark_dark.svg'
47+
48+
// Generate sign-in and sign-up links using the above params
49+
export const VSCE_LINK_AUTH = (mode: 'sign-in' | 'sign-up'): string => {
50+
const uri = new URL(VSCE_LINK_DOTCOM)
51+
const parameters = new URLSearchParams({
52+
...VSCE_LINK_PARAMS_UTM_SIDEBAR,
53+
...VSCE_LINK_PARAMS_EDITOR,
54+
...VSCE_LINK_PARAMS_TOKEN_REDIRECT,
55+
}).toString()
56+
uri.pathname = mode
57+
uri.search = parameters
58+
return uri.href
59+
}

client/vscode/src/contract.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,23 @@ export interface ExtensionCoreAPI {
5656
* Used to send current query from panel to sidebar.
5757
*/
5858
setSidebarQueryState: (queryState: VSCEQueryState) => void
59-
59+
/**
60+
* Local Storage Item
61+
*/
6062
getLocalStorageItem: (key: string) => string
6163
setLocalStorageItem: (key: string, value: string) => Promise<boolean>
62-
63-
// For Telemetry Service
64+
/**
65+
* For Telemetry Service / logging
66+
*/
6467
logEvents: (variables: Event) => void
65-
66-
// Get EventSource Type to use based on instance version
68+
/**
69+
* Get EventSource Type to use based on instance version
70+
*/
6771
getEventSource: EventSource
72+
/**
73+
* Get EventSource Type to use based on instance version
74+
*/
75+
getEditorTheme: string
6876
}
6977

7078
export interface SearchPanelAPI {

client/vscode/src/extension.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { fetchStreamSuggestions } from '@sourcegraph/shared/src/search/suggestio
99

1010
import { observeAuthenticatedUser } from './backend/authenticatedUser'
1111
import { logEvent } from './backend/eventLogger'
12-
import { initializeInstantVersionNumber } from './backend/instanceVersion'
12+
import { initializeInstanceVersionNumber } from './backend/instanceVersion'
1313
import { requestGraphQLFromVSCode } from './backend/requestGraphQl'
1414
import { initializeSearchContexts } from './backend/searchContexts'
1515
import { initializeSourcegraphSettings } from './backend/sourcegraphSettings'
@@ -63,14 +63,14 @@ export function activate(context: vscode.ExtensionContext): void {
6363
const stateMachine = createVSCEStateMachine({ localStorageService })
6464
invalidateContextOnSettingsChange({ context, stateMachine })
6565
initializeSearchContexts({ localStorageService, stateMachine, context })
66-
const eventSourceType = initializeInstantVersionNumber(localStorageService)
6766
const sourcegraphSettings = initializeSourcegraphSettings({ context })
6867
const authenticatedUser = observeAuthenticatedUser({ context })
6968
const initialInstanceURL = endpointSetting()
70-
69+
const initialAccessToken = accessTokenSetting()
70+
const editorTheme = vscode.ColorThemeKind[vscode.window.activeColorTheme.kind]
71+
const eventSourceType = initializeInstanceVersionNumber(localStorageService, initialInstanceURL, initialAccessToken)
7172
// Sets global `EventSource` for Node, which is required for streaming search.
7273
// Used for VS Code web as well to be able to add Authorization header.
73-
const initialAccessToken = accessTokenSetting()
7474
// Add custom headers to `EventSource` Authorization header when provided
7575
const customHeaders = endpointRequestHeadersSetting()
7676
polyfillEventSource(initialAccessToken ? { Authorization: `token ${initialAccessToken}`, ...customHeaders } : {})
@@ -132,8 +132,8 @@ export function activate(context: vscode.ExtensionContext): void {
132132
setLocalStorageItem: (key: string, value: string) => localStorageService.setValue(key, value),
133133
logEvents: (variables: Event) => logEvent(variables),
134134
getEventSource: eventSourceType,
135+
getEditorTheme: editorTheme,
135136
}
136-
137137
// Also initializes code intel.
138138
registerWebviews({
139139
context,

client/vscode/src/link-commands/initialize.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { EventSource } from '@sourcegraph/shared/src/graphql-operations'
44

55
import { version } from '../../package.json'
66
import { logEvent } from '../backend/eventLogger'
7+
import { VSCE_COMMANDS_PARAMS } from '../common/links'
78
import { SourcegraphUri } from '../file-system/SourcegraphUri'
89
import { LocalStorageService, ANONYMOUS_USER_ID_KEY } from '../settings/LocalStorageService'
910

@@ -56,8 +57,7 @@ export function initializeCodeSharingCommands(
5657
}
5758
}
5859

59-
export const vsceUtms =
60-
'&utm_campaign=vscode-extension&utm_medium=direct_traffic&utm_source=vscode-extension&utm_content=vsce-commands'
60+
export const vsceUtms = '&' + VSCE_COMMANDS_PARAMS
6161

6262
export function generateSourcegraphBlobLink(
6363
uri: vscode.Uri,

client/vscode/src/settings/accessTokenSetting.ts

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export async function handleAccessTokenError(badToken?: string): Promise<void> {
2626
}
2727

2828
export async function updateAccessTokenSetting(newToken: string): Promise<boolean> {
29+
// TODO: STORE TOKEN IN KEYCHAIN AND REMOVE FROM USER CONFIG
2930
try {
3031
await readConfiguration().update('accessToken', newToken, vscode.ConfigurationTarget.Global)
3132
return true

client/vscode/src/webview/commands.ts

+20
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,26 @@ export function registerWebviews({
3737
// TODO if remote files are open from previous session, we need
3838
// to focus search sidebar to activate code intel (load extension host)
3939

40+
// Register URI Handler to resolve data sending back from Browser
41+
const handleUri = async (uri: vscode.Uri): Promise<void> => {
42+
const token = new URLSearchParams(uri.query).get('code')
43+
// const returnedNonce = new URLSearchParams(uri.query).get('nonce')
44+
// TODO: Decrypt token
45+
// TODO: Match returnedNonce to stored nonce
46+
if (token && token.length > 8) {
47+
await vscode.workspace
48+
.getConfiguration('sourcegraph')
49+
.update('accessToken', token, vscode.ConfigurationTarget.Global)
50+
await vscode.window.showInformationMessage('Token has been retreived and updated successfully')
51+
}
52+
}
53+
54+
context.subscriptions.push(
55+
vscode.window.registerUriHandler({
56+
handleUri,
57+
})
58+
)
59+
4060
// Open Sourcegraph search tab on `sourcegraph.search` command.
4161
context.subscriptions.push(
4262
vscode.commands.registerCommand('sourcegraph.search', async () => {

client/vscode/src/webview/search-panel/SearchResultsView.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { LATEST_VERSION, RepositoryMatch, SearchMatch } from '@sourcegraph/share
2525
import { globbingEnabledFromSettings } from '@sourcegraph/shared/src/util/globbing'
2626
import { buildSearchURLQuery } from '@sourcegraph/shared/src/util/url'
2727

28+
import { VSCE_LINK_AUTH } from '../../common/links'
2829
import { DISMISS_SEARCH_CTA_KEY } from '../../settings/LocalStorageService'
2930
import { SearchResultsState } from '../../state'
3031
import { WebviewPageProps } from '../platform/context'
@@ -392,8 +393,7 @@ export const SearchResultsView: React.FunctionComponent<React.PropsWithChildren<
392393
searches and more."
393394
cta={{
394395
label: 'Get started',
395-
href:
396-
'https://sourcegraph.com/sign-up?editor=vscode&utm_medium=VSCODE&utm_source=sidebar&utm_campaign=vsce-sign-up&utm_content=sign-up',
396+
href: VSCE_LINK_AUTH('sign-up'),
397397
onClick: onSignUpClick,
398398
}}
399399
icon={<SearchBetaIcon />}

0 commit comments

Comments
 (0)