@@ -61,17 +61,23 @@ export async function clearPassword(treeItem?: ServerTreeItem): Promise<string>
6161 return reply ;
6262}
6363
64+ interface IMigratePasswordItem extends vscode . QuickPickItem {
65+ serverName : string ;
66+ userName : string ;
67+ password : string ;
68+ } ;
69+
6470export async function migratePasswords ( secretStorage : vscode . SecretStorage ) : Promise < void > {
6571 const credentials = await Keychain . findCredentials ( ) ;
66- console . log ( credentials ) ;
6772 if ( credentials . length === 0 ) {
68- vscode . window . showInformationMessage ( 'No legacy passwords found' ) ;
73+ vscode . window . showInformationMessage ( 'No legacy stored passwords found. ' ) ;
6974 } else {
7075
7176 // Collect only those for which server definition exists with a username
7277 // and no credentials yet stored in our SecretStorage
73- const migratableCredentials = ( await Promise . all (
74- credentials . map ( async ( item ) => {
78+ const migratableCredentials : IMigratePasswordItem [ ] = [ ] ;
79+ ( await Promise . all (
80+ credentials . map ( async ( item ) : Promise < IMigratePasswordItem | undefined > => {
7581 const serverName = item . account ;
7682 const username : string | undefined = vscode . workspace . getConfiguration ( "intersystems.servers." + serverName ) . get ( "username" ) ;
7783 if ( ! username ) {
@@ -82,33 +88,48 @@ export async function migratePasswords(secretStorage: vscode.SecretStorage): Pro
8288 }
8389 const sessionId = ServerManagerAuthenticationProvider . sessionId ( serverName , username ) ;
8490 const credentialKey = ServerManagerAuthenticationProvider . credentialKey ( sessionId ) ;
85- return ( await secretStorage . get ( credentialKey ) ? { ... item , username} : undefined ) ;
91+ return ( await secretStorage . get ( credentialKey ) ? undefined : { label : ` ${ serverName } ( ${ username } )` , picked : true , serverName , userName : username , password : item . password } ) ;
8692 } )
8793 ) )
88- . filter ( ( item ) => item ) ;
94+ . forEach ( ( item ) => {
95+ if ( item ) {
96+ migratableCredentials . push ( item ) ;
97+ }
98+ } ) ;
8999 if ( migratableCredentials . length === 0 ) {
90- vscode . window . showInformationMessage ( 'No legacy passwords found for servers whose definitions specify a username' ) ;
100+ const message = 'No remaining legacy stored passwords are eligible for migration.' ;
101+ const detail = 'They are either for servers with a password already stored in the new format, or for servers whose definition does not specify a username.'
102+ await vscode . window . showWarningMessage ( message ,
103+ { modal : true , detail} ,
104+ //{title: "OK", isCloseAffordance: true}
105+ ) ;
91106 } else {
92- const disqualified = credentials . length - migratableCredentials . length ;
93- const detail = disqualified > 0 ? `${ disqualified } other ${ disqualified > 1 ? "passwords" : "password" } ignored because associated server is no longer defined, or has no username set, or already has a password in the new keystore.` : "" ;
94- const message = `Migrate ${ migratableCredentials . length } legacy stored ${ migratableCredentials . length > 1 ? "passwords" : "password" } ?` ;
95- switch ( await vscode . window . showInformationMessage ( message , { modal : true , detail} , "Yes" , "No" ) ) {
96- case undefined :
97- return ;
98-
99- case "Yes" :
100- vscode . window . showInformationMessage ( 'TODO migration' ) ;
101- break ;
102-
103- default :
104- break ;
107+ const choices = await vscode . window . showQuickPick < IMigratePasswordItem > ( migratableCredentials ,
108+ { canPickMany : true ,
109+ title : "Migrate Server Manager legacy stored passwords" ,
110+ placeHolder : "Select connections whose passwords you want to migrate"
111+ }
112+ )
113+ if ( ! choices ) {
114+ return ;
115+ } else if ( choices . length > 0 ) {
116+ await Promise . all ( choices . map ( async ( item ) => {
117+ const sessionId = ServerManagerAuthenticationProvider . sessionId ( item . serverName , item . userName ) ;
118+ const credentialKey = ServerManagerAuthenticationProvider . credentialKey ( sessionId ) ;
119+ return secretStorage . store ( credentialKey , item . password ) ;
120+ } ) ) ;
121+ vscode . window . showInformationMessage ( `Migrated ${ choices . length } ${ choices . length > 1 ? "passwords" : "password" } .` ) ;
105122 }
106123 }
107124 const detail = "Do this to tidy up your keystore once you have migrated passwords and will not be reverting to an earlier Server Manager." ;
108- if ( await vscode . window . showInformationMessage ( `Delete all legacy stored passwords?` , { modal : true , detail} , "Yes" , "No" ) === "Yes" ) {
109- vscode . window . showInformationMessage ( 'TODO deletion' ) ;
125+ if ( ( await vscode . window . showInformationMessage ( `Delete all legacy stored passwords?` , { modal : true , detail} , { title : "Yes" } , { title : "No" , isCloseAffordance : true } ) ) ?. title === "Yes" ) {
126+ await Promise . all ( credentials . map ( async ( item ) => {
127+ const keychain = new Keychain ( item . account ) ;
128+ return keychain . deletePassword ( )
129+ } ) ) ;
130+ vscode . window . showInformationMessage ( `Deleted ${ credentials . length } ${ credentials . length > 1 ? "passwords" : "password" } .` ) ;
110131 }
111- }
132+ }
112133 return ;
113134}
114135
0 commit comments