Skip to content

feat: OAuth #47

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

Merged
merged 3 commits into from
Jun 30, 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
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ After installing the extension,
1. Click on the newly-added Source Academy icon on the left sidebar.
2. Launch the Source Academy panel.

<img src="./docs/images/launch-panel-from-sidebar.png" width="600">
<img src="./docs/images/launch-panel-from-sidebar.png" width="600">

Alternatively, use the `Source Academy: Show the Source Academy Panel` command.
Alternatively, use the `Source Academy: Show the Source Academy Panel` command.

Once the panel loads, you'll be prompted to log in. Afterwards, begin coding by opening any assessment.
3. Choose a login method and authenticate in your browser.

- When prompted, click **Open** to proceed to the external website.
- After login, click **Open** again to allow the extension to open the URI. Optionally, check `Do not ask me again for this extension`.

4. You may now begin coding by opening any assessment.

### Changing the frontend

Expand Down
34 changes: 17 additions & 17 deletions src/commands/showPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,24 @@ export async function showPanel(
language = LANGUAGES.SOURCE_1;
}

// Get a reference to the active editor (before the focus is switched to our newly created webview)
// firstEditor = vscode.window.activeTextEditor!;

messageHandler.panel = vscode.window.createWebviewPanel(
"source-academy-panel",
"Source Academy",
vscode.ViewColumn.Beside,
{
enableScripts: true, // Enable scripts in the webview
retainContextWhenHidden: true,
},
);
// Don't recreate the panel it already exists. There will only be one panel at anytime.
if (!messageHandler.panel) {
messageHandler.panel = vscode.window.createWebviewPanel(
"source-academy-panel",
"Source Academy",
vscode.ViewColumn.Beside,
{
enableScripts: true, // Enable scripts in w the webview
retainContextWhenHidden: true,
},
);

messageHandler.panel.webview.onDidReceiveMessage(
(message: MessageType) => messageHandler.handleMessage(context, message),
undefined,
context.subscriptions,
);
messageHandler.panel.webview.onDidReceiveMessage(
(message: MessageType) => messageHandler.handleMessage(context, message),
undefined,
context.subscriptions,
);
}

const iframeUrl = new URL(route ?? "/playground", config.frontendBaseUrl)
.href;
Expand Down
14 changes: 14 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ export function activate(context: vscode.ExtensionContext) {
"*.js": "source",
});
}

vscode.window.registerUriHandler({
handleUri(uri: vscode.Uri) {
const searchParams = new URLSearchParams(uri.query);
// The following two params are available when logging in via OAuth providers
const code = searchParams.get("code");
const clientRequestId = searchParams.get("client-request-id");

vscode.commands.executeCommand(
"source-academy.show-panel",
`/login/vscode_callback?code=${code}&client-request-id=${clientRequestId}`,
);
},
});
}

// This method is called when your extension is deactivated
Expand Down
3 changes: 3 additions & 0 deletions src/utils/messageHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ export class MessageHandler {
this.panel?.reveal(vscode.ViewColumn.Two);
}
break;
case MessageTypeNames.LoginWithBrowser:
const { route } = message;
vscode.env.openExternal(vscode.Uri.parse(route));
}
console.log(`${Date.now()} Finish handleMessage: ${message.type}`);
}
Expand Down
3 changes: 3 additions & 0 deletions src/utils/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ const Messages = createMessages({
questionId,
choice,
}),
LoginWithBrowser: (route: string) => ({
route,
}),
});

export default Messages;
Expand Down