mirror of
https://github.com/Eugeny/tabby
synced 2024-11-15 17:28:06 +00:00
ssh plugin fixes
This commit is contained in:
parent
5cdb7527c8
commit
f783e1ab06
3 changed files with 70 additions and 22 deletions
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ module.exports = {
|
||||||
'fs',
|
'fs',
|
||||||
'node-ssh',
|
'node-ssh',
|
||||||
'xkeychain',
|
'xkeychain',
|
||||||
|
'wincredmgr',
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
/^@ng-bootstrap/,
|
/^@ng-bootstrap/,
|
||||||
|
|
Loading…
Reference in a new issue