Skip to content

Commit 11f462f

Browse files
committed
feat(purl): move purl to org scope
1 parent 2a37f7d commit 11f462f

File tree

2 files changed

+66
-12
lines changed

2 files changed

+66
-12
lines changed

src/auth.ts

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type OrgInfo = {
1919
name: string
2020
image: string | null
2121
plan: 'opensource' | 'team' | 'enterprise'
22+
slug: string
2223
}
2324

2425
type OrganizationsRecord = {
@@ -42,6 +43,16 @@ async function getOrganizations(apiKey: string): Promise<OrganizationsRecord | n
4243
return orgs
4344
}
4445

46+
const orgSlugByApiKey = new Map<string, string>()
47+
48+
function getDefaultOrg(organizations: OrganizationsRecord): OrgInfo | null {
49+
const org = Object.values(organizations.organizations)[0]
50+
if (!org || !org.slug) {
51+
return null
52+
}
53+
return org
54+
}
55+
4556
export async function activate(context: vscode.ExtensionContext, disposables: Array<vscode.Disposable>) {
4657
//#region file path/watching
4758
// responsible for watching files to know when to sync from disk
@@ -103,12 +114,13 @@ export async function activate(context: vscode.ExtensionContext, disposables: Ar
103114
const sessionOnDisk: typeof liveSessions = new Map<vscode.AuthenticationSession['accessToken'], vscode.AuthenticationSession>()
104115
if (typeof apiKey === 'string' && apiKey.length > 0 && apiKey !== SOCKET_PUBLIC_API_TOKEN) {
105116
const organizations = await getOrganizations(apiKey)
106-
const org = Object.values(organizations!.organizations)[0]
107-
if (org) {
117+
const defaultOrg = organizations ? getDefaultOrg(organizations) : null
118+
if (defaultOrg) {
108119
sessionOnDisk.set(
109120
apiKey,
110-
sessionFromAPIKey(apiKey, org)
121+
sessionFromAPIKey(apiKey, defaultOrg)
111122
)
123+
orgSlugByApiKey.set(apiKey, defaultOrg.slug)
112124
}
113125
}
114126
let added: Array<vscode.AuthenticationSession> = []
@@ -156,23 +168,41 @@ export async function activate(context: vscode.ExtensionContext, disposables: Ar
156168
return Array.from(liveSessions.values())
157169
},
158170
async createSession(scopes: readonly string[], options: vscode.AuthenticationProviderSessionOptions): Promise<vscode.AuthenticationSession> {
159-
let organizations: OrganizationsRecord
171+
let organizations: OrganizationsRecord | null = null
172+
let defaultOrg: OrgInfo | null = null
160173
let apiKey: string = await vscode.window.showInputBox({
161174
title: 'Socket Security API Token',
162175
placeHolder: 'Leave this blank to stay logged out',
163176
ignoreFocusOut: true,
164177
prompt: 'Enter your API token from https://socket.dev/',
165178
async validateInput(value) {
166-
if (!value) return
167-
organizations = (await getOrganizations(value))!
168-
if (!organizations) return 'Invalid API key'
179+
if (!value) {
180+
return
181+
}
182+
183+
organizations = await getOrganizations(value)
184+
if (!organizations) {
185+
return 'Invalid API key'
186+
}
187+
188+
defaultOrg = getDefaultOrg(organizations)
189+
if (!defaultOrg) {
190+
return 'No organizations found for API key'
191+
}
169192
}
170193
}) ?? ''
171194
if (!apiKey) {
172195
throw new Error('User did not want to provide an API key')
173196
}
174-
const org = Object.values(organizations!.organizations)[0]
175-
const session = sessionFromAPIKey(apiKey, org)
197+
if (!organizations) {
198+
organizations = await getOrganizations(apiKey)
199+
}
200+
defaultOrg = defaultOrg ?? (organizations ? getDefaultOrg(organizations) : null)
201+
if (!defaultOrg) {
202+
throw new Error('No organizations found for API key')
203+
}
204+
const session = sessionFromAPIKey(apiKey, defaultOrg)
205+
orgSlugByApiKey.set(apiKey, defaultOrg.slug)
176206
let oldSessions = Array.from(liveSessions.values())
177207
await syncLiveSessionToDisk(session)
178208
liveSessions = new Map([
@@ -195,6 +225,7 @@ export async function activate(context: vscode.ExtensionContext, disposables: Ar
195225
fs.unlinkSync(settingsPath)
196226
} catch {}
197227
if (session) {
228+
orgSlugByApiKey.delete(session.accessToken)
198229
diskSessionsChanges.fire({
199230
added: [],
200231
changed: [],
@@ -238,6 +269,24 @@ export async function getAPIKey() {
238269
}
239270
}
240271

272+
export async function getOrgSlug(apiKey?: string) {
273+
const resolvedApiKey = apiKey ?? await getAPIKey()
274+
if (!resolvedApiKey || resolvedApiKey === SOCKET_PUBLIC_API_TOKEN) {
275+
return null
276+
}
277+
const cached = orgSlugByApiKey.get(resolvedApiKey)
278+
if (cached) {
279+
return cached
280+
}
281+
const organizations = await getOrganizations(resolvedApiKey)
282+
const defaultOrg = organizations ? getDefaultOrg(organizations) : null
283+
if (!defaultOrg) {
284+
return null
285+
}
286+
orgSlugByApiKey.set(resolvedApiKey, defaultOrg.slug)
287+
return defaultOrg.slug
288+
}
289+
241290
export function getAuthHeader(apiKey: string) {
242291
return `Bearer ${apiKey}`
243292
}
@@ -256,4 +305,3 @@ function sessionFromAPIKey(apiKey: string, org: OrgInfo) {
256305
scopes: [],
257306
}
258307
}
259-

src/ui/purl-alerts-and-scores/manager.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import logger from '../../infra/log'
77
import os from 'os'
88
import path from 'path'
99
import fs from 'fs'
10-
import { getAuthHeader, getAPIKey } from '../../auth'
10+
import { getAuthHeader, getAPIKey, getOrgSlug } from '../../auth'
1111
// if this is updated update lifecycle scripts
1212
const cacheDir = path.resolve(os.homedir(), '.socket', 'vscode')
1313

@@ -160,7 +160,13 @@ export class PURLDataCache {
160160
bailPendingCacheEntries()
161161
return
162162
}
163-
const req = https.request(`https://api.socket.dev/v0/purl?alerts=true&compact=false'`, {
163+
const orgSlug = await getOrgSlug(apiKey)
164+
if (!orgSlug) {
165+
bailPendingCacheEntries(new Error('No organization available for API token'))
166+
return
167+
}
168+
const encodedOrgSlug = encodeURIComponent(orgSlug)
169+
const req = https.request(`https://api.socket.dev/v0/orgs/${encodedOrgSlug}/purl?alerts=true&compact=false`, {
164170
method: 'POST',
165171
headers: {
166172
'content-type': 'application/json',

0 commit comments

Comments
 (0)