@@ -7,14 +7,15 @@ import { IncomingMessage } from 'node:http'
77import { text } from 'node:stream/consumers'
88import constants from '@socketsecurity/registry/lib/constants'
99import { addDisposablesTo } from '../util'
10+ import { log } from 'node:console'
1011
1112const { SOCKET_PUBLIC_API_TOKEN } = constants
1213
1314export type APIConfig = {
1415 apiKey : string
1516}
1617
17- let apiConf : APIConfig | { } | undefined
18+ let apiConf : APIConfig | undefined
1819
1920let dataHome = process . platform === 'win32'
2021 ? process . env [ 'LOCALAPPDATA' ]
@@ -97,18 +98,19 @@ async function loadConfig(update?: boolean) {
9798
9899async function findAPIConfig ( ) {
99100 if ( ! apiConf ) {
100- apiConf = { }
101+ apiConf = undefined
101102 let keyInfo : OrganizationsRecord | null
102103 const envKey = process . env . SOCKET_SECURITY_API_TOKEN ?? process . env . SOCKET_SECURITY_API_KEY
103104 if ( envKey ) {
104105 keyInfo = await getOrganizations ( envKey )
105- if ( keyInfo ) {
106- apiConf = getConfigFromSettings ( envKey )
106+ apiConf = {
107+ apiKey : envKey
107108 }
109+ } else {
110+ await loadConfig ( )
108111 }
109- if ( ! ( apiConf as APIConfig ) . apiKey ) await loadConfig ( )
110112 }
111- return ( apiConf as APIConfig ) . apiKey ? apiConf as APIConfig : null
113+ return ( apiConf as APIConfig ) ? .apiKey ? apiConf as APIConfig : null
112114}
113115
114116let existingFindCall : Promise < APIConfig | null > | null = null
@@ -121,64 +123,87 @@ export async function getExistingAPIConfig() {
121123 return result
122124}
123125
124- export async function usePublicConfig ( force ?: boolean ) {
125- if ( force || ! getExistingAPIConfig ( ) ) {
126- const apiKey = SOCKET_PUBLIC_API_TOKEN
127- await saveConfig ( apiKey , [ ] )
128- changeAPIConf . fire ( )
129- }
130- return apiConf as APIConfig
131- }
132-
133- export async function getAPIConfig ( force ?: boolean ) {
134- if ( ! force ) {
135- const existingConf = await getExistingAPIConfig ( )
136- if ( existingConf ) return existingConf
126+ let pendingNewConfig : Promise < APIConfig | null > | null = null
127+ export async function getAPIConfig ( ) {
128+ const existingConf = await getExistingAPIConfig ( )
129+ if ( existingConf ) {
130+ return existingConf
137131 }
138- let organizations : OrganizationsRecord
139- let apiKey = await vscode . window . showInputBox ( {
140- title : 'Socket Security API Token' ,
141- placeHolder : 'Leave this blank to use a public token' ,
142- prompt : 'Enter your API token from https://socket.dev/' ,
143- async validateInput ( value ) {
144- if ( ! value ) return
145- organizations = ( await getOrganizations ( value ) ) !
146- if ( ! organizations ) return 'Invalid API key'
147- }
148- } )
149- if ( apiKey === undefined ) {
150- return null
132+ if ( pendingNewConfig ) {
133+ return pendingNewConfig
151134 }
152- let enforcedOrgs : string [ ] = [ ]
153- if ( ! apiKey ) {
154- apiKey = SOCKET_PUBLIC_API_TOKEN
155- organizations = ( await getOrganizations ( apiKey ) ) !
156- } else {
157- let organizationsList = Object . values ( organizations ! . organizations ! )
158- if ( organizationsList . length ) {
159- ( organizationsList [ 0 ] as OrgInfo )
160- const options : ( vscode . QuickPickItem & { id : string | null } ) [ ] = [
161- ...organizationsList . map ( org => {
162- return {
163- label : org . name ,
164- id : org . id ,
135+ async function getNewConfig ( ) {
136+ let organizations : OrganizationsRecord
137+ let apiKey = null
138+ while ( true ) {
139+ const loginChoice = await vscode . window . showInformationMessage ( 'Socket Security requires authentication for full functionality.' ,
140+ 'Authenticate' ,
141+ 'Stay logged out'
142+ )
143+ // they chose to ignore the prompt or opted to be logged out
144+ // it will come back later
145+ if ( loginChoice === 'Stay logged out' || ! loginChoice ) {
146+ break
147+ }
148+ if ( loginChoice === 'Authenticate' ) {
149+ apiKey = await vscode . window . showInputBox ( {
150+ title : 'Socket Security API Token' ,
151+ placeHolder : 'Leave this blank to stay logged out' ,
152+ prompt : 'Enter your API token from https://socket.dev/' ,
153+ async validateInput ( value ) {
154+ if ( ! value ) return
155+ organizations = ( await getOrganizations ( value ) ) !
156+ if ( ! organizations ) return 'Invalid API key'
165157 }
166- } ) ,
167- {
168- label : 'None' ,
169- id : null
158+ } )
159+ // vscode gives undefined if focus is lost, this is error prone UX
160+ // show the informative message again that they can ignore
161+ // only consider the user to have made a choice if they enter a value
162+ if ( typeof apiKey === 'string' ) {
163+ break
170164 }
171- ]
172- const result = await vscode . window . showQuickPick ( options , {
173- title : 'Which organization\'s policies should Socket enforce system-wide?'
174- } )
175- if ( result ?. id ) enforcedOrgs = [ result . id ]
165+ }
176166 }
167+ let enforcedOrgs : string [ ] = [ ]
168+ if ( ! apiKey || apiKey === SOCKET_PUBLIC_API_TOKEN ) {
169+ // dont save to disk and don't ask for orgs
170+ apiConf = {
171+ apiKey : SOCKET_PUBLIC_API_TOKEN
172+ }
173+ changeAPIConf . fire ( )
174+ return apiConf
175+ } else {
176+ let organizationsList = Object . values ( organizations ! . organizations ! )
177+ if ( organizationsList . length ) {
178+ ( organizationsList [ 0 ] as OrgInfo )
179+ const options : ( vscode . QuickPickItem & { id : string | null } ) [ ] = [
180+ ...organizationsList . map ( org => {
181+ return {
182+ label : org . name ,
183+ id : org . id ,
184+ }
185+ } ) ,
186+ {
187+ label : 'None' ,
188+ id : null
189+ }
190+ ]
191+ const result = await vscode . window . showQuickPick ( options , {
192+ title : 'Which organization\'s policies should Socket enforce system-wide?'
193+ } )
194+ if ( result ?. id ) enforcedOrgs = [ result . id ]
195+ }
196+ }
197+ await saveConfig ( apiKey , enforcedOrgs )
198+ apiConf = getConfigFromSettings ( apiKey )
199+ changeAPIConf . fire ( )
200+ return apiConf
177201 }
178- await saveConfig ( apiKey , enforcedOrgs )
179- apiConf = getConfigFromSettings ( apiKey )
180- changeAPIConf . fire ( )
181- return apiConf as APIConfig
202+ pendingNewConfig = getNewConfig ( )
203+ pendingNewConfig . finally ( ( ) => {
204+ pendingNewConfig = null
205+ } )
206+ return pendingNewConfig
182207}
183208
184209export function init ( disposables ?: vscode . Disposable [ ] ) {
@@ -194,7 +219,7 @@ export function init(disposables?: vscode.Disposable[]) {
194219 watcher . onDidChange ( ( ) => loadConfig ( true ) ) ,
195220 watcher . onDidCreate ( ( ) => loadConfig ( true ) ) ,
196221 watcher . onDidDelete ( ( ) => {
197- apiConf = { }
222+ apiConf = undefined
198223 } )
199224 )
200225}
0 commit comments