ssh plugin fixes

This commit is contained in:
Eugene Pankov 2017-11-27 17:29:45 +01:00
parent 5cdb7527c8
commit f783e1ab06
3 changed files with 70 additions and 22 deletions

View file

@ -17,9 +17,6 @@ export class SSHSettingsTabComponent {
this.connections = this.config.store.ssh.connections this.connections = this.config.store.ssh.connections
} }
async ngOnInit () {
}
createConnection () { createConnection () {
let connection: SSHConnection = { let connection: SSHConnection = {
name: '', name: '',
@ -31,6 +28,7 @@ export class SSHSettingsTabComponent {
modal.result.then(result => { modal.result.then(result => {
this.connections.push(result) this.connections.push(result)
this.config.store.ssh.connections = this.connections this.config.store.ssh.connections = this.connections
this.config.save()
}) })
} }
@ -47,6 +45,7 @@ export class SSHSettingsTabComponent {
if (confirm(`Delete "${connection.name}"?`)) { if (confirm(`Delete "${connection.name}"?`)) {
this.connections = this.connections.filter(x => x !== connection) this.connections = this.connections.filter(x => x !== connection)
this.config.store.ssh.connections = this.connections this.config.store.ssh.connections = this.connections
this.config.save()
} }
} }
} }

View file

@ -8,7 +8,19 @@ import { SSHConnection, SSHSession } from '../api'
import { PromptModalComponent } from '../components/promptModal.component' import { PromptModalComponent } from '../components/promptModal.component'
const { SSH2Stream } = require('ssh2-streams') const { SSH2Stream } = require('ssh2-streams')
const keychain = require('xkeychain')
let xkeychain
let wincredmgr
try {
console.log(1)
xkeychain = require('xkeychain')
} catch (error) {
try {
wincredmgr = require('wincredmgr')
} catch (error2) {
console.warn('No keychain manager available')
}
}
@Injectable() @Injectable()
export class SSHService { export class SSHService {
@ -19,23 +31,71 @@ export class SSHService {
) { ) {
} }
savePassword (connection: SSHConnection, password: string) {
if (xkeychain) {
xkeychain.setPassword({
account: connection.user,
service: `ssh@${connection.host}`,
password
}, () => null)
} else {
wincredmgr.WriteCredentials(
'user',
password,
`ssh:${connection.user}@${connection.host}`,
)
}
}
deletePassword (connection: SSHConnection) {
if (xkeychain) {
xkeychain.deletePassword({
account: connection.user,
service: `ssh@${connection.host}`,
}, () => null)
} else {
wincredmgr.DeleteCredentials(
`ssh:${connection.user}@${connection.host}`,
)
}
}
loadPassword (connection: SSHConnection): Promise<string> {
return new Promise(resolve => {
if (xkeychain) {
xkeychain.getPassword({
account: connection.user,
service: `ssh@${connection.host}`,
}, (_, result) => resolve(result))
} else {
try {
resolve(wincredmgr.ReadCredentials(`ssh:${connection.user}@${connection.host}`).password)
} catch (error) {
resolve(null)
}
}
})
}
async connect (connection: SSHConnection): Promise<TerminalTabComponent> { async connect (connection: SSHConnection): Promise<TerminalTabComponent> {
let privateKey: string = null let privateKey: string = null
if (connection.privateKey) { if (connection.privateKey) {
try { try {
privateKey = (await fs.readFile(connection.privateKey)).toString() privateKey = (await fs.readFile(connection.privateKey)).toString()
} catch (error) { } catch (error) { }
}
} }
let ssh = new Client() let ssh = new Client()
let connected = false let connected = false
let savedPassword: string = null
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
ssh.on('ready', () => { ssh.on('ready', () => {
connected = true connected = true
this.savePassword(connection, savedPassword)
this.zone.run(resolve) this.zone.run(resolve)
}) })
ssh.on('error', error => { ssh.on('error', error => {
this.deletePassword(connection)
this.zone.run(() => { this.zone.run(() => {
if (connected) { if (connected) {
alert(`SSH error: ${error}`) alert(`SSH error: ${error}`)
@ -70,13 +130,8 @@ export class SSHService {
return connection.password return connection.password
} }
if (!keychainPasswordUsed && keychain.isSupported()) { if (!keychainPasswordUsed && (wincredmgr || xkeychain.isSupported())) {
let password = await new Promise(resolve => { let password = await this.loadPassword(connection)
keychain.getPassword({
account: connection.user,
service: `ssh@${connection.host}`,
}, (_, result) => resolve(result))
})
if (password) { if (password) {
keychainPasswordUsed = true keychainPasswordUsed = true
return password return password
@ -86,15 +141,8 @@ export class SSHService {
let modal = this.ngbModal.open(PromptModalComponent) let modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = `Password for ${connection.user}@${connection.host}` modal.componentInstance.prompt = `Password for ${connection.user}@${connection.host}`
modal.componentInstance.password = true modal.componentInstance.password = true
let password = await modal.result savedPassword = await modal.result
return savedPassword
keychain.setPassword({
account: connection.user,
service: `ssh@${connection.host}`,
password
}, () => null)
return password
}) })
}) })

View file

@ -38,6 +38,7 @@ module.exports = {
'fs', 'fs',
'node-ssh', 'node-ssh',
'xkeychain', 'xkeychain',
'wincredmgr',
/^rxjs/, /^rxjs/,
/^@angular/, /^@angular/,
/^@ng-bootstrap/, /^@ng-bootstrap/,