Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify jetbrains account management #6558

Merged
merged 2 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
package com.sourcegraph.cody.agent.protocol_generated;

data class ExtensionConfiguration(
val serverEndpoint: String,
val serverEndpoint: String? = null,
val proxy: String? = null,
val accessToken: String? = null,
val customHeaders: Map<String, String>,
Expand Down
2 changes: 1 addition & 1 deletion agent/src/TestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ export function setupRecording(): void {
}

export class TestClient extends MessageHandler {
private secrets = new AgentStatelessSecretStorage()
private extensionConfigurationDuringInitialization: ExtensionConfiguration | undefined
public static create({ bin = 'node', ...params }: TestClientParams): TestClient {
setupRecording()
Expand Down Expand Up @@ -180,6 +179,7 @@ export class TestClient extends MessageHandler {
public workspaceEditParams: WorkspaceEditParams[] = []
public textDocumentEditParams: TextDocumentEditParams[] = []
public expectedEvents: string[] = []
public secrets = new AgentStatelessSecretStorage()

get serverEndpoint(): string {
return this.params.credentials.serverEndpoint
Expand Down
2 changes: 1 addition & 1 deletion agent/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1492,7 +1492,7 @@ export class Agent extends MessageHandler implements ExtensionClient {
// If this is an authentication change we need to reauthenticate prior to firing events
// that update the clients
try {
if (isAuthChange || params?.forceAuthentication) {
if ((isAuthChange || params?.forceAuthentication) && config.serverEndpoint) {
await authProvider.validateAndStoreCredentials(
{
configuration: {
Expand Down
19 changes: 19 additions & 0 deletions agent/src/unauthed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ describe.skip(
expect(authStatus?.endpoint).toBe(TESTING_CREDENTIALS.dotcomUnauthed.serverEndpoint)
})

it('starts up with default andpoint and credentials if they are present in the secure store', async () => {
const newClient = TestClient.create({
workspaceRootUri: workspace.rootUri,
name: 'unauthed',
credentials: TESTING_CREDENTIALS.dotcomUnauthed,
})

newClient.secrets.store(
TESTING_CREDENTIALS.dotcom.serverEndpoint,
TESTING_CREDENTIALS.dotcom.token ?? 'invalid'
)

await newClient.beforeAll({ serverEndpoint: undefined }, { expectAuthenticated: true })
const authStatus = await newClient.request('extensionConfiguration/status', null)
expect(authStatus?.authenticated).toBe(true)
expect(authStatus?.endpoint).toBe(TESTING_CREDENTIALS.dotcom.serverEndpoint)
newClient.afterAll()
})

it('authenticates to same endpoint using valid credentials', async () => {
const authStatus = await client.request('extensionConfiguration/change', {
...client.info.extensionConfiguration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import com.intellij.testFramework.runInEdtAndWait
import com.sourcegraph.cody.agent.CodyAgentService
import com.sourcegraph.cody.agent.protocol_generated.ProtocolAuthenticatedAuthStatus
import com.sourcegraph.cody.agent.protocol_generated.ProtocolCodeLens
import com.sourcegraph.cody.auth.CodyAccount
import com.sourcegraph.cody.auth.SourcegraphServerPath
import com.sourcegraph.cody.edit.lenses.LensListener
import com.sourcegraph.cody.edit.lenses.LensesService
Expand Down Expand Up @@ -102,16 +101,13 @@ open class CodyIntegrationTextFixture : BasePlatformTestCase(), LensListener {
// change anything.
private fun initCredentialsAndAgent() {
val credentials = TestingCredentials.dotcom
val account = CodyAccount(SourcegraphServerPath.from(credentials.serverEndpoint, ""))
account.storeToken(
credentials.token ?: credentials.redactedToken,
)
CodyAccount.setActiveAccount(account)
val endpoint = SourcegraphServerPath.from(credentials.serverEndpoint, "")
val token = credentials.token ?: credentials.redactedToken

assertNotNull(
"Unable to start agent in a timely fashion!",
CodyAgentService.getInstance(project)
.startAgent(project)
.startAgent(project, endpoint, token)
.completeOnTimeout(null, ASYNC_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.get())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.sourcegraph.cody.auth.CodyAccount;
import com.intellij.openapi.project.Project;
import com.sourcegraph.cody.auth.CodyAuthService;
import com.sourcegraph.config.ConfigUtil;
import org.jetbrains.annotations.NotNull;

Expand All @@ -22,7 +23,12 @@ public boolean isDumbAware() {
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);

Project project = e.getProject();
e.getPresentation()
.setVisible(ConfigUtil.isCodyEnabled() && CodyAccount.Companion.hasActiveAccount());
.setVisible(
ConfigUtil.isCodyEnabled()
&& project != null
&& CodyAuthService.getInstance(project).isActivated());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import com.intellij.openapi.wm.ToolWindowManager;
import com.sourcegraph.Icons;
import com.sourcegraph.cody.CodyToolWindowFactory;
import com.sourcegraph.cody.auth.CodyAccount;
import com.sourcegraph.cody.auth.CodyAuthService;
import com.sourcegraph.cody.config.CodyApplicationSettings;
import com.sourcegraph.cody.initialization.Activity;
import com.sourcegraph.common.NotificationGroups;
Expand All @@ -22,7 +22,7 @@ public class CodyAuthNotificationActivity implements Activity {
@Override
public void runActivity(@NotNull Project project) {
if (!CodyApplicationSettings.getInstance().isGetStartedNotificationDismissed()
&& !CodyAccount.Companion.hasActiveAccount()) {
&& !CodyAuthService.getInstance(project).isActivated()) {
showOpenCodySidebarNotification(project);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public JBCefJSQuery.Response handle(@NotNull JsonObject request) {
try {
switch (action) {
case "getConfig":
return createSuccessResponse(ConfigUtil.getConfigAsJson());
return createSuccessResponse(ConfigUtil.getConfigAsJson(project));
case "getTheme":
JsonObject currentThemeAsJson = ThemeUtil.getCurrentThemeAsJson();
return createSuccessResponse(currentThemeAsJson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ public void actionPerformed(@NotNull AnActionEvent event) {
LogicalPosition selectionStartPosition = getSelectionStartPosition(editor);
LogicalPosition selectionEndPosition = getSelectionEndPosition(editor);

URLBuilder urlBuilder = new URLBuilder(project);

if (currentFile instanceof SourcegraphVirtualFile) {
SourcegraphVirtualFile sourcegraphFile = (SourcegraphVirtualFile) currentFile;
handleFileUri(
project,
URLBuilder.buildSourcegraphBlobUrl(
urlBuilder.buildSourcegraphBlobUrl(
sourcegraphFile.getRepoUrl(),
sourcegraphFile.getCommit(),
sourcegraphFile.getRelativePath(),
Expand All @@ -68,15 +70,15 @@ public void actionPerformed(@NotNull AnActionEvent event) {
// Our "editor" backend doesn't support Perforce, but we have all the info we
// need, so we'll go to the final URL directly.
url =
URLBuilder.buildSourcegraphBlobUrl(
urlBuilder.buildSourcegraphBlobUrl(
repoInfo.getCodeHostUrl() + "/" + repoInfo.getRepoName(),
null,
repoInfo.relativePath,
selectionStartPosition,
selectionEndPosition);
} else {
url =
URLBuilder.buildEditorFileUrl(
urlBuilder.buildEditorFileUrl(
repoInfo.remoteUrl,
repoInfo.remoteBranchName,
repoInfo.relativePath,
Expand All @@ -102,12 +104,13 @@ public void actionPerformedFromPreviewContent(

handleFileUri(
project,
URLBuilder.buildSourcegraphBlobUrl(
previewContent.getRepoUrl(),
previewContent.getCommit(),
previewContent.getPath(),
start,
end));
new URLBuilder(project)
.buildSourcegraphBlobUrl(
previewContent.getRepoUrl(),
previewContent.getCommit(),
previewContent.getPath(),
start,
end));
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
import com.intellij.vcs.log.VcsLogCommitSelection;
import com.intellij.vcs.log.VcsLogDataKeys;
import com.intellij.vcsUtil.VcsUtil;
import com.sourcegraph.cody.auth.CodyAuthService;
import com.sourcegraph.common.BrowserOpener;
import com.sourcegraph.common.ErrorNotification;
import com.sourcegraph.common.ui.DumbAwareEDTAction;
import com.sourcegraph.config.ConfigUtil;
import com.sourcegraph.vcs.RepoUtil;
import com.sourcegraph.vcs.RevisionContext;
import com.sourcegraph.vcs.VCSType;
Expand Down Expand Up @@ -89,15 +89,15 @@ public void actionPerformed(@NotNull AnActionEvent event) {
try {
url =
URLBuilder.buildCommitUrl(
ConfigUtil.getServerPath().getUrl(),
CodyAuthService.getInstance(project).getEndpoint().getUrl(),
context.getRevisionNumber(),
remoteUrl,
productName,
productVersion);
} catch (IllegalArgumentException e) {
logger.warn(
"Unable to build commit view URI for url "
+ ConfigUtil.getServerPath().getUrl()
+ CodyAuthService.getInstance(project).getEndpoint().getUrl()
+ ", revision "
+ context.getRevisionNumber()
+ ", product "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ public void actionPerformedMode(@NotNull AnActionEvent event, @NotNull Scope sco
VirtualFile currentFile = FileDocumentManager.getInstance().getFile(editor.getDocument());
assert currentFile != null; // selectedText != null, so this can't be null.

URLBuilder urlBuilder = new URLBuilder(project);
if (currentFile instanceof SourcegraphVirtualFile) {
String url;
SourcegraphVirtualFile sourcegraphFile = (SourcegraphVirtualFile) currentFile;
String repoUrl = (scope == Scope.REPOSITORY) ? sourcegraphFile.getRepoUrl() : null;
url = URLBuilder.buildEditorSearchUrl(selectedText, repoUrl, null);
url = urlBuilder.buildEditorSearchUrl(selectedText, repoUrl, null);
BrowserOpener.INSTANCE.openInBrowser(project, url);
} else {
// This cannot run on EDT (Event Dispatch Thread) because it may block for a long time.
Expand All @@ -62,9 +63,9 @@ public void actionPerformedMode(@NotNull AnActionEvent event, @NotNull Scope sco
String codeHostUrl =
(scope == Scope.REPOSITORY) ? repoInfo.getCodeHostUrl() : null;
String repoName = (scope == Scope.REPOSITORY) ? repoInfo.getRepoName() : null;
url = URLBuilder.buildDirectSearchUrl(selectedText, codeHostUrl, repoName);
url = urlBuilder.buildDirectSearchUrl(selectedText, codeHostUrl, repoName);
} else {
url = URLBuilder.buildEditorSearchUrl(selectedText, remoteUrl, remoteBranchName);
url = urlBuilder.buildEditorSearchUrl(selectedText, remoteUrl, remoteBranchName);
}
BrowserOpener.INSTANCE.openInBrowser(project, url);
});
Expand Down
24 changes: 16 additions & 8 deletions jetbrains/src/main/java/com/sourcegraph/website/URLBuilder.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.sourcegraph.website;

import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.project.Project;
import com.sourcegraph.cody.auth.CodyAuthService;
import com.sourcegraph.common.RegexEscaper;
import com.sourcegraph.config.ConfigUtil;
import java.net.URI;
Expand All @@ -10,14 +12,20 @@
import org.jetbrains.annotations.Nullable;

public class URLBuilder {
Project project;

public URLBuilder(Project project) {
this.project = project;
}

@NotNull
public static String buildEditorFileUrl(
public String buildEditorFileUrl(
@NotNull String remoteUrl,
@NotNull String branchName,
@NotNull String relativePath,
@Nullable LogicalPosition start,
@Nullable LogicalPosition end) {
return ConfigUtil.getServerPath().getUrl()
return CodyAuthService.getInstance(project).getEndpoint().getUrl()
+ "-/editor"
+ "?remote_url="
+ URLEncoder.encode(remoteUrl, StandardCharsets.UTF_8)
Expand All @@ -42,10 +50,10 @@ public static String buildEditorFileUrl(
}

@NotNull
public static String buildEditorSearchUrl(
public String buildEditorSearchUrl(
@NotNull String search, @Nullable String remoteUrl, @Nullable String remoteBranchName) {
String url =
ConfigUtil.getServerPath().getUrl()
CodyAuthService.getInstance(project).getEndpoint().getUrl()
+ "-/editor"
+ "?"
+ buildVersionParams()
Expand All @@ -63,13 +71,13 @@ public static String buildEditorSearchUrl(
}

@NotNull
public static String buildDirectSearchUrl(
public String buildDirectSearchUrl(
@NotNull String search, @Nullable String codeHost, @Nullable String repoName) {
String repoFilter =
(codeHost != null && repoName != null)
? "repo:^" + RegexEscaper.INSTANCE.escapeRegexChars(codeHost + "/" + repoName) + "$"
: null;
return ConfigUtil.getServerPath().getUrl()
return CodyAuthService.getInstance(project).getEndpoint().getUrl()
+ "/search"
+ "?patternType=literal"
+ "&q="
Expand Down Expand Up @@ -117,13 +125,13 @@ public static String buildCommitUrl(

@NotNull
// repoUrl should be like "github.com/sourcegraph/sourcegraph"
public static String buildSourcegraphBlobUrl(
public String buildSourcegraphBlobUrl(
@NotNull String repoUrl,
@Nullable String commit,
@NotNull String path,
@Nullable LogicalPosition start,
@Nullable LogicalPosition end) {
return ConfigUtil.getServerPath().getUrl()
return CodyAuthService.getInstance(project).getEndpoint().getUrl()
+ repoUrl
+ (commit != null ? "@" + commit : "")
+ "/-/blob/"
Expand Down
23 changes: 13 additions & 10 deletions jetbrains/src/main/kotlin/com/sourcegraph/cody/agent/CodyAgent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.sourcegraph.cody.agent.protocol_generated.ClientInfo
import com.sourcegraph.cody.agent.protocol_generated.CodyAgentServer
import com.sourcegraph.cody.agent.protocol_generated.ProtocolTypeAdapters
import com.sourcegraph.cody.agent.protocol_generated.WebviewNativeConfig
import com.sourcegraph.cody.auth.SourcegraphServerPath
import com.sourcegraph.cody.ui.web.WebUIServiceWebviewProvider
import com.sourcegraph.cody.vscode.CancellationToken
import com.sourcegraph.config.ConfigUtil
Expand Down Expand Up @@ -114,7 +115,11 @@ private constructor(
else -> Debuggability.NotDebuggable
}

fun create(project: Project): CompletableFuture<CodyAgent> {
fun create(
project: Project,
endpoint: SourcegraphServerPath?,
token: String?,
): CompletableFuture<CodyAgent> {
try {
val conn = startAgentProcess()
val client = CodyAgentClient(project, WebUIServiceWebviewProvider(project))
Expand All @@ -131,7 +136,8 @@ private constructor(
workspaceRootUri =
ProtocolTextDocumentExt.normalizeUriOrPath(
ConfigUtil.getWorkspaceRootPath(project).toUri().toString()),
extensionConfiguration = ConfigUtil.getAgentConfiguration(project),
extensionConfiguration =
ConfigUtil.getAgentConfiguration(project, endpoint, token),
capabilities =
ClientCapabilities(
authentication = ClientCapabilities.AuthenticationEnum.Enabled,
Expand Down Expand Up @@ -314,15 +320,13 @@ private constructor(
// undefined fields.
.serializeNulls()
// TODO: Once all protocols have migrated we can remove these
// legacy enum
// conversions
// legacy enum conversions
.registerTypeAdapter(URI::class.java, uriDeserializer)
.registerTypeAdapter(URI::class.java, uriSerializer)

ProtocolTypeAdapters.register(gsonBuilder)
// This ensures that by default all enums are always serialized to their
// string
// equivalents
// string equivalents string equivalents
gsonBuilder.registerTypeAdapterFactory(EnumTypeAdapterFactory())
}
}
Expand Down Expand Up @@ -385,10 +389,9 @@ private constructor(
return try {
binaryTarget?.toFile()?.deleteOnExit()
token.onFinished {
// Important: delete the file from disk after the process exists
// Ideally, we should eventually replace this temporary file with a permanent
// location
// in the plugin directory.
// Important: delete the file from disk after the process exists Ideally, we
// should eventually replace this temporary file with a permanent location in
// the plugin directory.
Files.deleteIfExists(binaryTarget)
}
logger.info("Extracting Node binary to " + binaryTarget.toAbsolutePath())
Expand Down
Loading
Loading