From 25977026763b62622b9ef4236b9eb997f73eda27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2020 17:56:11 +0000 Subject: [PATCH 01/18] Bump electron from 8.2.5 to 8.5.2 Bumps [electron](https://github.com/electron/electron) from 8.2.5 to 8.5.2. - [Release notes](https://github.com/electron/electron/releases) - [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md) - [Commits](https://github.com/electron/electron/compare/v8.2.5...v8.5.2) Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 57ae9a25..59d929c0 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "core-js": "^3.6.5", "cross-env": "7.0.2", "css-loader": "3.4.2", - "electron": "^8.2.5", + "electron": "^8.5.2", "electron-builder": "22.6.1", "electron-download": "^4.1.1", "electron-installer-snap": "^5.0.0", diff --git a/yarn.lock b/yarn.lock index b6df62a3..d16cfc99 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2112,10 +2112,10 @@ electron-rebuild@^1.10.1: spawn-rx "^3.0.0" yargs "^14.2.0" -electron@^8.2.5: - version "8.2.5" - resolved "https://registry.yarnpkg.com/electron/-/electron-8.2.5.tgz#ae3cb23d5517b2189fd35298e487198d65d1a291" - integrity sha512-LxSCUwmlfJtRwthd3ofpYaZ+1C2hQSW8Ep1DD9K3VbnDItO+kb3t1z35daJgAab78j54aOwo9gMxJtvU0Ftj6w== +electron@^8.5.2: + version "8.5.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-8.5.2.tgz#7b0246c6676a39df0e5e384b11cfe854fe5917f0" + integrity sha512-VU+zZnmCzxoZ5UfBg2UGVm+nyxlNlQOQkotMLfk7FCtnkIOhX+sosl618OCxUWjOvPc+Mpg5MEkEmxPU5ziW4Q== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" From 5c7256ffe5004780d754939b4664df391602c924 Mon Sep 17 00:00:00 2001 From: TakuroOnoda Date: Sun, 18 Oct 2020 18:48:10 +0900 Subject: [PATCH 02/18] Adding Tab Location "left" --- .../src/components/appRoot.component.pug | 206 ++++++++++-------- .../src/components/appRoot.component.scss | 28 ++- .../src/components/tabHeader.component.scss | 5 + .../src/components/settingsTab.component.pug | 7 + .../src/components/settingsTab.component.ts | 2 +- terminus-ssh/package.json | 2 +- .../src/api/baseTerminalTab.component.ts | 2 +- 7 files changed, 162 insertions(+), 90 deletions(-) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 21e018cc..887dfaf6 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -3,99 +3,133 @@ title-bar( [class.inset]='hostApp.platform == Platform.macOS' ) -.content( - [class.tabs-on-top]='config.store.appearance.tabsLocation == "top"' -) - .tab-bar - .inset.background(*ngIf='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"') - .tabs( - dnd-sortable-container, - [sortableData]='app.tabs', - ) - tab-header( - *ngFor='let tab of app.tabs; let idx = index', - dnd-sortable, - [sortableIndex]='idx', - (onDragStart)='onTabDragStart()', - (onDragEnd)='onTabDragEnd()', +.wrap + .tab-bar.vertical( + *ngIf='config.store.appearance.tabsLocation == "left"' + ) + .inset.background(*ngIf='hostApp.platform == Platform.macOS \ + && config.store.appearance.frame == "thin"') + .tabs.vertical( + dnd-sortable-container, + [sortableData]='app.tabs', + ) + tab-header( + *ngFor='let tab of app.tabs; let idx = index', + dnd-sortable, + [sortableIndex]='idx', + (onDragStart)='onTabDragStart()', + (onDragEnd)='onTabDragEnd()', - [index]='idx', - [tab]='tab', - [active]='tab == app.activeTab', - [hasActivity]='tab.activity$|async', - @animateTab, - (click)='app.selectTab(tab)', - [class.fully-draggable]='hostApp.platform != Platform.macOS', - [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', - ) + [index]='idx', + [tab]='tab', + [active]='tab == app.activeTab', + [hasActivity]='tab.activity$|async', + @animateTab, + (click)='app.selectTab(tab)', + [class.fully-draggable]='hostApp.platform != Platform.macOS', + [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', + [class.vertical]='true', + ) - .btn-group.background - .d-flex( - *ngFor='let button of leftToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') + .content( + [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"', + [class.with-side-tab]='config.store.appearance.tabsLocation == "left"', + ) + .tab-bar + .inset.background(*ngIf='hostApp.platform == Platform.macOS \ + && config.store.appearance.frame == "thin" \ + && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') + .tabs( + *ngIf='config.store.appearance.tabsLocation != "left"' + dnd-sortable-container, + [sortableData]='app.tabs', + ) + tab-header( + *ngFor='let tab of app.tabs; let idx = index', + dnd-sortable, + [sortableIndex]='idx', + (onDragStart)='onTabDragStart()', + (onDragEnd)='onTabDragEnd()', - .btn-group.background - .d-flex( - *ngFor='let button of rightToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} + [index]='idx', + [tab]='tab', + [active]='tab == app.activeTab', + [hasActivity]='tab.activity$|async', + @animateTab, + (click)='app.selectTab(tab)', + [class.fully-draggable]='hostApp.platform != Platform.macOS', + [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', + ) - button.btn.btn-secondary.btn-tab-bar.btn-update( - *ngIf='updatesAvailable', - title='Update available - Click to install', - (click)='updateApp()', - [fastHtmlBind]='updateIcon' - ) + .btn-group.background + .d-flex( + *ngFor='let button of leftToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - window-controls.background( - *ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', - ) + .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') - start-page(*ngIf='ready && app.tabs.length == 0') + .btn-group.background + .d-flex( + *ngFor='let button of rightToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - tab-body( - *ngFor='let tab of unsortedTabs', - [active]='tab == app.activeTab', - [tab]='tab', - ) + button.btn.btn-secondary.btn-tab-bar.btn-update( + *ngIf='updatesAvailable', + title='Update available - Click to install', + (click)='updateApp()', + [fastHtmlBind]='updateIcon' + ) + + window-controls.background( + *ngIf='config.store.appearance.frame == "thin" \ + && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', + ) + + start-page(*ngIf='ready && app.tabs.length == 0') + + tab-body( + *ngFor='let tab of unsortedTabs', + [active]='tab == app.activeTab', + [tab]='tab', + ) ng-template(ngbModalContainer) diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss index 689fc7f4..ddb38bf1 100644 --- a/terminus-core/src/components/appRoot.component.scss +++ b/terminus-core/src/components/appRoot.component.scss @@ -15,10 +15,18 @@ $tabs-height: 38px; $tab-border-radius: 4px; +$side-tab-width: 200px; +.wrap { + display: flex; + width: 100vw; + height: 100vh; + flex-direction: row; +} .content { - height: 100%; + width: 100vw; + height: 100vh; flex: auto; display: flex; flex-direction: column-reverse; @@ -26,12 +34,24 @@ $tab-border-radius: 4px; &.tabs-on-top { flex-direction: column; } + + &.with-side-tab { + width: calc(100% - #{$side-tab-width}); + } + } .tab-bar { flex: none; height: $tabs-height; display: flex; + width: 100%; + &.vertical { + height: 100%; + width: $side-tab-width; + overflow-y: auto; + overflow-x: hidden; + } .btn-tab-bar { line-height: $tabs-height + 2px; @@ -59,6 +79,12 @@ $tab-border-radius: 4px; flex: 0 1 auto; display: flex; min-width: 0; + + &.vertical { + width: $side-tab-width; + flex: auto; + flex-direction: column; + } } &>.drag-space { diff --git a/terminus-core/src/components/tabHeader.component.scss b/terminus-core/src/components/tabHeader.component.scss index 09ed4c87..1c5c45e5 100644 --- a/terminus-core/src/components/tabHeader.component.scss +++ b/terminus-core/src/components/tabHeader.component.scss @@ -13,6 +13,11 @@ $tabs-height: 38px; overflow: hidden; + &.vertical { + flex: none; + height: $tabs-height; + } + .index { flex: none; font-weight: bold; diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index 841e8744..b6369316 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -51,6 +51,13 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') [value]='"bottom"' ) | At the bottom + label.btn.btn-secondary(ngbButtonLabel) + input( + type='radio', + ngbButton, + [value]='"left"' + ) + | At the left .form-line .header diff --git a/terminus-settings/src/components/settingsTab.component.ts b/terminus-settings/src/components/settingsTab.component.ts index 4f26efd2..a10ad4ec 100644 --- a/terminus-settings/src/components/settingsTab.component.ts +++ b/terminus-settings/src/components/settingsTab.component.ts @@ -65,7 +65,7 @@ export class SettingsTabComponent extends BaseTabComponent { const onConfigChange = () => { this.configFile = config.readRaw() this.padWindowControls = hostApp.platform === Platform.macOS - && config.store.appearance.tabsLocation === 'bottom' + && config.store.appearance.tabsLocation !== 'top' } this.configSubscription = config.changed$.subscribe(onConfigChange) diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json index 481b8097..bf0f2bcf 100644 --- a/terminus-ssh/package.json +++ b/terminus-ssh/package.json @@ -10,7 +10,7 @@ "scripts": { "build": "webpack --progress --color", "watch": "webpack --progress --color --watch", - "postinstall": "xcopy /i node_modules\\ssh2\\util\\pagent.exe util\\" + "postinstall": "xcopy /i /y node_modules\\ssh2\\util\\pagent.exe util\\" }, "files": [ "dist", diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts index d949146a..16bd9dc5 100644 --- a/terminus-terminal/src/api/baseTerminalTab.component.ts +++ b/terminus-terminal/src/api/baseTerminalTab.component.ts @@ -348,7 +348,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit this.topPadded = this.hostApp.platform === Platform.macOS && this.config.store.appearance.frame === 'thin' - && this.config.store.appearance.tabsLocation === 'bottom' + && this.config.store.appearance.tabsLocation !== 'top' if (this.config.store.terminal.background === 'colorScheme') { if (this.config.store.terminal.colorScheme.background) { From 4aa79a76ead698d7fc80edd54770d42745f3a566 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 24 Nov 2020 04:23:53 +0000 Subject: [PATCH 03/18] Bump @sentry/electron from 1.5.1 to 2.0.4 Bumps [@sentry/electron](https://github.com/getsentry/sentry-electron) from 1.5.1 to 2.0.4. - [Release notes](https://github.com/getsentry/sentry-electron/releases) - [Changelog](https://github.com/getsentry/sentry-electron/blob/master/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-electron/compare/v1.5.1...2.0.4) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 225 ++++++++++++++++----------------------------------- 2 files changed, 72 insertions(+), 155 deletions(-) diff --git a/package.json b/package.json index 57ae9a25..4b23f820 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "devDependencies": { "@fortawesome/fontawesome-free": "^5.13.0", "@sentry/cli": "^1.52.3", - "@sentry/electron": "^1.5.1", + "@sentry/electron": "^2.0.4", "@types/electron-config": "^3.2.2", "@types/electron-debug": "^2.1.0", "@types/js-yaml": "^3.12.4", diff --git a/yarn.lock b/yarn.lock index b6df62a3..50de4ad7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -65,26 +65,14 @@ dependencies: mkdirp "^1.0.4" -"@sentry/apm@5.20.1": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.20.1.tgz#2126407ec8ecc6f78f42a8a8de99b90dec982036" - integrity sha512-oqfyYqRR1CaM/U5qZg3KY9MxCe4OWYs3uiOvVGMOHCyx50dYsDZziM5DDVUvi6pOuokLCNbyXO9xGROSmploBQ== +"@sentry/browser@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.27.6.tgz#54fe177e9986246586b0761eb38cbad1ad07ecb5" + integrity sha512-pqrojE2ZmLUVz7l/ogtogK0+M2pK3bigYm0fja7vG7F7kXnCAwqAHDYfkFXEvFI8WvNwH+niy28lSoV95lnm0Q== dependencies: - "@sentry/browser" "5.20.1" - "@sentry/hub" "5.20.1" - "@sentry/minimal" "5.20.1" - "@sentry/types" "5.20.1" - "@sentry/utils" "5.20.1" - tslib "^1.9.3" - -"@sentry/browser@5.20.1", "@sentry/browser@~5.20.0": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.20.1.tgz#be59522d0914d58309e1367d997d4b3cd5385d7e" - integrity sha512-ClykuvrEsMKgAvifx5VHzRjchwYbJFX8YiIicYx+Wr3MXL2jLG6OEfHHJwJeyBL2C3vxd5O0KPK3pGMR9wPMLA== - dependencies: - "@sentry/core" "5.20.1" - "@sentry/types" "5.20.1" - "@sentry/utils" "5.20.1" + "@sentry/core" "5.27.6" + "@sentry/types" "5.27.6" + "@sentry/utils" "5.27.6" tslib "^1.9.3" "@sentry/cli@^1.52.3": @@ -98,77 +86,85 @@ progress "^2.0.3" proxy-from-env "^1.1.0" -"@sentry/core@5.20.1", "@sentry/core@~5.20.0": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.20.1.tgz#857cc7186931c37ff032a1bcb573600ebacde961" - integrity sha512-gG622/UY2TePruF6iUzgVrbIX5vN8w2cjlWFo1Est8MvCfQsz8agGaLMCAyl5hCGJ6K2qTUZDOlbCNIKoMclxg== +"@sentry/core@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.27.6.tgz#3ceeb58acd857f1e17d52d3087bfecb506adc1f7" + integrity sha512-izCS5iyc6HAfpW1AsGXLAKetx82C1Sq1siAh97tOlSK58PVJAEH/WMiej9WuZJxCDTOtj94QtoLflssrZyAtFg== dependencies: - "@sentry/hub" "5.20.1" - "@sentry/minimal" "5.20.1" - "@sentry/types" "5.20.1" - "@sentry/utils" "5.20.1" + "@sentry/hub" "5.27.6" + "@sentry/minimal" "5.27.6" + "@sentry/types" "5.27.6" + "@sentry/utils" "5.27.6" tslib "^1.9.3" -"@sentry/electron@^1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-1.5.1.tgz#99027268353f9f25a4d69b4a615879cf8b4c2f37" - integrity sha512-+NxUIC0TQb8scDzccciOfA9xg1ipPUopbZEtuwjgg0Q3Ry9TMCf/GTYHtIOSn+6LTvdijO2Jk//7aL8VTSWGKA== +"@sentry/electron@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.0.4.tgz#1259f5c38ea6190dd24138379518db1bb283557d" + integrity sha512-mniKLrAC2S8VdXvUYvo/ZN6pr/bQScF8c4r3hv0uLN6w6D4zPIrIsn2ph/etigwqhW4xanyPkxc+Pafl1fFr0Q== dependencies: - "@sentry/browser" "~5.20.0" - "@sentry/core" "~5.20.0" - "@sentry/minimal" "~5.20.0" - "@sentry/node" "~5.20.0" - "@sentry/types" "~5.20.0" - "@sentry/utils" "~5.20.0" - electron-fetch "^1.4.0" - form-data "2.5.1" - tslib "^1.9.3" - util.promisify "1.0.1" - -"@sentry/hub@5.20.1": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.20.1.tgz#05e83ba972a96e9d7225a64c7d3728aa9fcefc4e" - integrity sha512-Nv5BXf14BEc08acDguW6eSqkAJLVf8wki283FczEvTsQZZuSBHM9cJ5Hnehr6n+mr8wWpYLgUUYM0oXXigUmzQ== - dependencies: - "@sentry/types" "5.20.1" - "@sentry/utils" "5.20.1" + "@sentry/browser" "5.27.6" + "@sentry/core" "5.27.6" + "@sentry/minimal" "5.27.6" + "@sentry/node" "5.27.6" + "@sentry/types" "5.27.6" + "@sentry/utils" "5.27.6" tslib "^1.9.3" -"@sentry/minimal@5.20.1", "@sentry/minimal@~5.20.0": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.20.1.tgz#2e2b63d9cd265b7e2f593f3eab4e9874bd87eeef" - integrity sha512-2PeJKDTHNsUd1jtSLQBJ6oRI+xrIJrYDQmsyK/qs9D7HqHfs+zNAMUjYseiVeSAFGas5IcNSuZbPRV4BnuoZ0w== +"@sentry/hub@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.27.6.tgz#a94adbe32c45dda7ad5adf742b82e0a022eb9c2f" + integrity sha512-bOMky3iu7zEghSaWmTayfme5tCpUok841qDCGxGKuyAtOhBDsgGNS/ApNEEDF2fyX0oo4G1cHYPWhX90ZFf/xA== dependencies: - "@sentry/hub" "5.20.1" - "@sentry/types" "5.20.1" + "@sentry/types" "5.27.6" + "@sentry/utils" "5.27.6" tslib "^1.9.3" -"@sentry/node@~5.20.0": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.20.1.tgz#c38dd8c1f8f227420abb0c04354177d7296535bf" - integrity sha512-43YFDnD7Rv+vGHV+Fmb3LaSSWrFzsPmFRu3wmf9eYMgWiuDks6c6/kWRCgkqX9Np9ImC89wcTZs/V6S4MlOm4g== +"@sentry/minimal@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.27.6.tgz#783012ed94668be168f2b521e0ea6295c76ce2b0" + integrity sha512-pKhzVQX9nL4m1dcnb2i2Y47IWVNs+K3wiYLgCB9hl9+ApxppfOc+fquiFoCloST3IuaD4yly2TtbOJgAMWcMxQ== dependencies: - "@sentry/apm" "5.20.1" - "@sentry/core" "5.20.1" - "@sentry/hub" "5.20.1" - "@sentry/types" "5.20.1" - "@sentry/utils" "5.20.1" + "@sentry/hub" "5.27.6" + "@sentry/types" "5.27.6" + tslib "^1.9.3" + +"@sentry/node@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.27.6.tgz#a9ab20bf305d802914b41040ef3b328c2b681120" + integrity sha512-ogKL4F3wSZuzNeHOGKPqQPbZ87Bd/dC8wk7Rwbui3SIMgtoUmO3rSOR4Edwar6mf330cA6CY9roylWdcaSqmZA== + dependencies: + "@sentry/core" "5.27.6" + "@sentry/hub" "5.27.6" + "@sentry/tracing" "5.27.6" + "@sentry/types" "5.27.6" + "@sentry/utils" "5.27.6" cookie "^0.4.1" https-proxy-agent "^5.0.0" lru_map "^0.3.3" tslib "^1.9.3" -"@sentry/types@5.20.1", "@sentry/types@~5.20.0": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.20.1.tgz#ccc4fa4c9d0f94d93014b04e674762d5d5cd30a2" - integrity sha512-OU+i/lcjGpDJv0XkNpsKrI2r1VPp8qX0H6Knq8NuZrlZe3AbvO3jRJJK0pH14xFv8Xok5jbZZpKKoQLxYfxqsw== - -"@sentry/utils@5.20.1", "@sentry/utils@~5.20.0": - version "5.20.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.20.1.tgz#68cfae0d0e3b321b4649b59f30265024b29eae63" - integrity sha512-dhK6IdO6g7Q2CoxCbB+q8gwUapDUH5VjraFg0UBzgkrtNhtHLylqmwx0sWQvXCcp14Q/3MuzEbb4euvoh8o8oA== +"@sentry/tracing@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.27.6.tgz#34a827c6e7a819b0eb0e409063203209abd19dad" + integrity sha512-ms3vprEId+hi8hcqtf8weqsNGASaDXAZzIOT4g2gASGpwLb5hLuScpM8z6Yhu5FGjb8DektlW5OrXJSsStIozw== dependencies: - "@sentry/types" "5.20.1" + "@sentry/hub" "5.27.6" + "@sentry/minimal" "5.27.6" + "@sentry/types" "5.27.6" + "@sentry/utils" "5.27.6" + tslib "^1.9.3" + +"@sentry/types@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.27.6.tgz#b5054eafcb8ac11d4bc4787c7bc7fc113cad8b80" + integrity sha512-XOW9W8DrMk++4Hk7gWi9o5VR0o/GrqGfTKyFsHSIjqt2hL6kiMPvKeb2Hhmp7Iq37N2bDmRdWpM5m+68S2Jk6w== + +"@sentry/utils@5.27.6": + version "5.27.6" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.27.6.tgz#cd8486469ae9716a21a4bc7e828e5aeee0ed9727" + integrity sha512-/QMVLv+zrTfiIj2PU+SodSbSzD5MmamMOaljkDsRIVsj6gpkm1/VG1g2+40TZ0FbQ4hCW2F+iR7cnqzZBNmchA== + dependencies: + "@sentry/types" "5.27.6" tslib "^1.9.3" "@sindresorhus/is@^0.14.0": @@ -2018,13 +2014,6 @@ electron-download@^4.1.1: semver "^5.4.1" sumchecker "^2.0.2" -electron-fetch@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/electron-fetch/-/electron-fetch-1.4.0.tgz#a830d400f8ad358acba9b3c591e6ed477916bac5" - integrity sha512-rednYIpMbuzekTroNndQOFl95c4I/wMEbH9jxGoDEoKrM07b7FWydy6I3pbiAbCxDcYpmHtzMY6ykyLagR7JHw== - dependencies: - encoding "^0.1.12" - electron-installer-common@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/electron-installer-common/-/electron-installer-common-0.10.0.tgz#e57b9cac3637fc312d28f3e45f197f5c1743c931" @@ -2145,7 +2134,7 @@ encodeurl@^1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -encoding@^0.1.11, encoding@^0.1.12: +encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" dependencies: @@ -2241,23 +2230,6 @@ es-abstract@^1.17.0-next.1: string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" -es-abstract@^1.17.2, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" - object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -2695,15 +2667,6 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -form-data@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" @@ -3461,11 +3424,6 @@ is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== -is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== - is-ci@^1.0.10: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" @@ -3642,13 +3600,6 @@ is-regex@^1.0.5: dependencies: has "^1.0.3" -is-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" - integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== - dependencies: - has-symbols "^1.0.1" - is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -4907,14 +4858,6 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.getownpropertydescriptors@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -6547,14 +6490,6 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^5.2.0" -string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -6571,14 +6506,6 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -7255,16 +7182,6 @@ util-extend@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" -util.promisify@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" - uuid@^3.0.0, uuid@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" From 225760a9a59341570473cbb2c3b862f9304d3da4 Mon Sep 17 00:00:00 2001 From: Harsh Gadgil Date: Thu, 3 Dec 2020 19:09:26 -0500 Subject: [PATCH 04/18] Update api.ts Fix typos --- terminus-ssh/src/api.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terminus-ssh/src/api.ts b/terminus-ssh/src/api.ts index 34a424ba..4e9d662b 100644 --- a/terminus-ssh/src/api.ts +++ b/terminus-ssh/src/api.ts @@ -246,7 +246,7 @@ export class SSHSession extends BaseSession { fw.targetPort, (err, stream) => { if (err) { - this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwaded connection via ${fw}: ${err}`) + this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwarded connection via ${fw}: ${err}`) socket.destroy() return } @@ -263,7 +263,7 @@ export class SSHSession extends BaseSession { } ) }).then(() => { - this.emitServiceMessage(colors.bgGreen.black(' -> ') + ` Forwaded ${fw}`) + this.emitServiceMessage(colors.bgGreen.black(' -> ') + ` Forwarded ${fw}`) this.forwardedPorts.push(fw) }).catch(e => { this.emitServiceMessage(colors.bgRed.black(' X ') + ` Failed to forward port ${fw}: ${e}`) @@ -280,7 +280,7 @@ export class SSHSession extends BaseSession { resolve() }) }) - this.emitServiceMessage(colors.bgGreen.black(' <- ') + ` Forwaded ${fw}`) + this.emitServiceMessage(colors.bgGreen.black(' <- ') + ` Forwarded ${fw}`) this.forwardedPorts.push(fw) } } From dd3e7a0f89c0f7f07f1f90984a1f86d849c58d9f Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 15:39:49 +0100 Subject: [PATCH 05/18] fixed #2558 --- app/lib/window.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/lib/window.ts b/app/lib/window.ts index cc1d4fac..feed335b 100644 --- a/app/lib/window.ts +++ b/app/lib/window.ts @@ -211,9 +211,7 @@ export class Window { } handleSecondInstance (argv: string[], cwd: string): void { - if (!this.configStore.appearance?.dock) { - this.send('host:second-instance', parseArgs(argv, cwd), cwd) - } + this.send('host:second-instance', parseArgs(argv, cwd), cwd) } private setupWindowManagement () { From 86b503093cd1f05fc515b895c760dd03098e1f83 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 17:03:07 +0100 Subject: [PATCH 06/18] only send args to the most recent window --- app/lib/app.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/lib/app.ts b/app/lib/app.ts index a1c016c8..10e89b19 100644 --- a/app/lib/app.ts +++ b/app/lib/app.ts @@ -139,9 +139,7 @@ export class Application { handleSecondInstance (argv: string[], cwd: string): void { this.presentAllWindows() - for (let window of this.windows) { - window.handleSecondInstance(argv, cwd) - } + this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd) } private setupMenu () { From 7977c1d644e64da0cd26e5ce3887590fe27a8880 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 17:27:45 +0100 Subject: [PATCH 07/18] cleanup --- terminus-core/src/components/tabHeader.component.pug | 4 ++-- terminus-ssh/package.json | 5 ++++- terminus-ssh/yarn.lock | 5 +++++ .../src/components/appearanceSettingsTab.component.pug | 8 ++++---- terminus-terminal/src/config.ts | 4 ++-- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/terminus-core/src/components/tabHeader.component.pug b/terminus-core/src/components/tabHeader.component.pug index 676a495a..76447550 100644 --- a/terminus-core/src/components/tabHeader.component.pug +++ b/terminus-core/src/components/tabHeader.component.pug @@ -1,7 +1,7 @@ .progressbar([style.width]='progress + "%"', *ngIf='progress != null') -.index(*ngIf='!config.store.terminal.disableTabIndex', +.index(*ngIf='!config.store.terminal.hideTabIndex', #handle, [style.background-color]='tab.color', ) {{index + 1}} .name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}} -button(*ngIf='!config.store.terminal.disableCloseButton',(click)='app.closeTab(tab, true)') × +button(*ngIf='!config.store.terminal.hideCloseButton',(click)='app.closeTab(tab, true)') × diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json index 39a6357f..a1e7d0fe 100644 --- a/terminus-ssh/package.json +++ b/terminus-ssh/package.json @@ -10,7 +10,9 @@ "scripts": { "build": "webpack --progress --color", "watch": "webpack --progress --color --watch", - "postinstall:win32": "xcopy /i node_modules\\ssh2\\util\\pagent.exe util\\" + "postinstall": "run-script-os", + "postinstall:win32": "xcopy /i node_modules\\ssh2\\util\\pagent.exe util\\", + "postinstall:darwin:linux": "exit" }, "files": [ "dist", @@ -23,6 +25,7 @@ "@types/ssh2": "^0.5.35", "ansi-colors": "^4.1.1", "cli-spinner": "^0.2.10", + "run-script-os": "^1.1.3", "ssh2": "^0.8.2", "ssh2-streams": "Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5", "sshpk": "^1.16.1", diff --git a/terminus-ssh/yarn.lock b/terminus-ssh/yarn.lock index 392a7188..c0387d7d 100644 --- a/terminus-ssh/yarn.lock +++ b/terminus-ssh/yarn.lock @@ -157,6 +157,11 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" +run-script-os@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/run-script-os/-/run-script-os-1.1.3.tgz#1069b418307f4fd36ff056b5eda309c273fca8b0" + integrity sha512-xPlzE6533nvWVea5z7e5J7+JAIepfpxTu/HLGxcjJYlemVukOCWJBaRCod/DWXJFRIWEFOgSGbjd2m1QWTJi5w== + safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" diff --git a/terminus-terminal/src/components/appearanceSettingsTab.component.pug b/terminus-terminal/src/components/appearanceSettingsTab.component.pug index d4b7c5a9..9cb61770 100644 --- a/terminus-terminal/src/components/appearanceSettingsTab.component.pug +++ b/terminus-terminal/src/components/appearanceSettingsTab.component.pug @@ -111,19 +111,19 @@ h3.mb-3 Appearance .form-line .header - .title Disable tab index + .title Hide tab index toggle( - [(ngModel)]='config.store.terminal.disableTabIndex', + [(ngModel)]='config.store.terminal.hideTabIndex', (ngModelChange)='config.save();', ) .form-line .header - .title Disable tab close button + .title Hide tab close button toggle( - [(ngModel)]='config.store.terminal.disableCloseButton', + [(ngModel)]='config.store.terminal.hideCloseButton', (ngModelChange)='config.save();', ) diff --git a/terminus-terminal/src/config.ts b/terminus-terminal/src/config.ts index 5983266f..ae7a500b 100644 --- a/terminus-terminal/src/config.ts +++ b/terminus-terminal/src/config.ts @@ -23,8 +23,8 @@ export class TerminalConfigProvider extends ConfigProvider { ligatures: false, cursor: 'block', cursorBlink: true, - disableTabIndex: false, - disableCloseButton: false, + hideTabIndex: false, + hideCloseButton: false, customShell: '', rightClick: 'menu', pasteOnMiddleClick: true, From 9a60b4d102b08679a551c4eadf66fdf3e519cfcb Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 16:28:08 +0000 Subject: [PATCH 08/18] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 94012030..868ad12c 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Jonathan Beverley

💻
Zenghai Liang

💻
Mateusz Tracz

💻 +
pinpin

💻 From c6188a49f573a1e4830c42e79e4c1cd95ad3082e Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 16:28:09 +0000 Subject: [PATCH 09/18] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 6b8737a5..6a3ac35c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -316,6 +316,15 @@ "contributions": [ "code" ] + }, + { + "login": "pinpins", + "name": "pinpin", + "avatar_url": "https://avatars3.githubusercontent.com/u/36234677?v=4", + "profile": "https://zergpool.com", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, From e6fd31e0b00c22a6cc6aba400e2c5d019e185e26 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 17:43:00 +0100 Subject: [PATCH 10/18] don't try to load the private key if not selected - fixes #2968 --- terminus-ssh/src/services/ssh.service.ts | 39 +++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/terminus-ssh/src/services/ssh.service.ts b/terminus-ssh/src/services/ssh.service.ts index d65658d2..ee8098c3 100644 --- a/terminus-ssh/src/services/ssh.service.ts +++ b/terminus-ssh/src/services/ssh.service.ts @@ -22,6 +22,11 @@ try { var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var } catch { } + +// eslint-disable-next-line @typescript-eslint/no-type-alias +export type SSHLogCallback = (message: string) => void + + @Injectable({ providedIn: 'root' }) export class SSHService { private logger: Logger @@ -46,33 +51,24 @@ export class SSHService { return session } - async connectSession (session: SSHSession, logCallback?: (s: any) => void): Promise { + async loadPrivateKeyForSession (session: SSHSession, logCallback?: SSHLogCallback): Promise { let privateKey: string|null = null let privateKeyPath = session.connection.privateKey - if (!logCallback) { - logCallback = () => null - } - - const log = (s: any) => { - logCallback!(s) - this.logger.info(s) - } - if (!privateKeyPath) { const userKeyPath = path.join(process.env.HOME as string, '.ssh', 'id_rsa') if (await fs.exists(userKeyPath)) { - log('Using user\'s default private key') + logCallback?.('Using user\'s default private key') privateKeyPath = userKeyPath } } if (privateKeyPath) { - log('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' ')) + logCallback?.('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' ')) try { privateKey = (await fs.readFile(privateKeyPath)).toString() } catch (error) { - log(colors.bgRed.black(' X ') + 'Could not read the private key file') + logCallback?.(colors.bgRed.black(' X ') + 'Could not read the private key file') this.toastr.error('Could not read the private key file') } @@ -83,7 +79,7 @@ export class SSHService { } catch (e) { if (e instanceof sshpk.KeyEncryptedError) { const modal = this.ngbModal.open(PromptModalComponent) - log(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase') + logCallback?.(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase') modal.componentInstance.prompt = 'Private key passphrase' modal.componentInstance.password = true let passphrase = '' @@ -131,6 +127,20 @@ export class SSHService { fs.unlink(temp.path) } } + return privateKey + } + + async connectSession (session: SSHSession, logCallback?: SSHLogCallback): Promise { + if (!logCallback) { + logCallback = () => null + } + + const log = (s: any) => { + logCallback!(s) + this.logger.info(s) + } + + let privateKey: string|null = null const ssh = new Client() session.ssh = ssh @@ -213,6 +223,7 @@ export class SSHService { const authMethodsLeft = ['none'] if (!session.connection.auth || session.connection.auth === 'publicKey') { + privateKey = await this.loadPrivateKeyForSession(session, log) if (!privateKey) { log('\r\nPrivate key auth selected, but no key is loaded\r\n') } else { From 17f52a257ebc688397b45a0480f1b88ad10ab35c Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 18:11:15 +0100 Subject: [PATCH 11/18] PS ctrl-left, ctrl-right and ctrl-del bindings (#507, #2739) --- .../src/api/baseTerminalTab.component.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts index d949146a..b622b020 100644 --- a/terminus-terminal/src/api/baseTerminalTab.component.ts +++ b/terminus-terminal/src/api/baseTerminalTab.component.ts @@ -156,16 +156,28 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit this.resetZoom() break case 'previous-word': - this.sendInput('\x1bb') + this.sendInput({ + [Platform.Windows]: '\x1b[1;5D', + [Platform.macOS]: '\x1bb', + [Platform.Linux]: '\x1bb', + }[this.hostApp.platform]) break case 'next-word': - this.sendInput('\x1bf') + this.sendInput({ + [Platform.Windows]: '\x1b[1;5C', + [Platform.macOS]: '\x1bf', + [Platform.Linux]: '\x1bf', + }[this.hostApp.platform]) break case 'delete-previous-word': this.sendInput('\x1b\x7f') break case 'delete-next-word': - this.sendInput('\x1bd') + this.sendInput({ + [Platform.Windows]: '\x1bd\x1b[3;5~', + [Platform.macOS]: '\x1bd', + [Platform.Linux]: '\x1bd', + }[this.hostApp.platform]) break case 'search': this.showSearchPanel = true From dff6a2470c8bd081163a4ff0951c2c83d98ec600 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 19:12:15 +0100 Subject: [PATCH 12/18] refined vertical tabs --- .../src/components/appRoot.component.pug | 212 ++++++++---------- .../src/components/appRoot.component.scss | 48 ++-- .../src/components/appRoot.component.ts | 4 + .../src/components/settingsTab.component.pug | 13 +- 4 files changed, 140 insertions(+), 137 deletions(-) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 887dfaf6..7630ade9 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -3,133 +3,105 @@ title-bar( [class.inset]='hostApp.platform == Platform.macOS' ) -.wrap - .tab-bar.vertical( - *ngIf='config.store.appearance.tabsLocation == "left"' - ) - .inset.background(*ngIf='hostApp.platform == Platform.macOS \ - && config.store.appearance.frame == "thin"') - .tabs.vertical( - dnd-sortable-container, - [sortableData]='app.tabs', - ) - tab-header( - *ngFor='let tab of app.tabs; let idx = index', - dnd-sortable, - [sortableIndex]='idx', - (onDragStart)='onTabDragStart()', - (onDragEnd)='onTabDragEnd()', +.content( + [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"', + [class.tabs-on-side]='hasVerticalTabs()', +) + .tab-bar + .inset.background(*ngIf='hostApp.platform == Platform.macOS \ + && config.store.appearance.frame == "thin" \ + && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') + .tabs( + *ngIf='config.store.appearance.tabsLocation != "bottom"' + dnd-sortable-container, + [sortableData]='app.tabs', + ) + tab-header( + *ngFor='let tab of app.tabs; let idx = index', + dnd-sortable, + [sortableIndex]='idx', + (onDragStart)='onTabDragStart()', + (onDragEnd)='onTabDragEnd()', - [index]='idx', - [tab]='tab', - [active]='tab == app.activeTab', - [hasActivity]='tab.activity$|async', - @animateTab, - (click)='app.selectTab(tab)', - [class.fully-draggable]='hostApp.platform != Platform.macOS', - [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', - [class.vertical]='true', - ) + [index]='idx', + [tab]='tab', + [active]='tab == app.activeTab', + [hasActivity]='tab.activity$|async', + @animateTab, + [@.disabled]='hasVerticalTabs()', + (click)='app.selectTab(tab)', + [class.fully-draggable]='hostApp.platform != Platform.macOS', + [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', + ) + .btn-group.background + .d-flex( + *ngFor='let button of leftToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - .content( - [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"', - [class.with-side-tab]='config.store.appearance.tabsLocation == "left"', - ) - .tab-bar - .inset.background(*ngIf='hostApp.platform == Platform.macOS \ - && config.store.appearance.frame == "thin" \ - && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') - .tabs( - *ngIf='config.store.appearance.tabsLocation != "left"' - dnd-sortable-container, - [sortableData]='app.tabs', - ) - tab-header( - *ngFor='let tab of app.tabs; let idx = index', - dnd-sortable, - [sortableIndex]='idx', - (onDragStart)='onTabDragStart()', - (onDragEnd)='onTabDragEnd()', + .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') - [index]='idx', - [tab]='tab', - [active]='tab == app.activeTab', - [hasActivity]='tab.activity$|async', - @animateTab, - (click)='app.selectTab(tab)', - [class.fully-draggable]='hostApp.platform != Platform.macOS', - [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', - ) + .btn-group.background + .d-flex( + *ngFor='let button of rightToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - .btn-group.background - .d-flex( - *ngFor='let button of leftToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} + button.btn.btn-secondary.btn-tab-bar.btn-update( + *ngIf='updatesAvailable', + title='Update available - Click to install', + (click)='updateApp()', + [fastHtmlBind]='updateIcon' + ) - .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') + window-controls.background( + *ngIf='config.store.appearance.frame == "thin" \ + && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', + ) - .btn-group.background - .d-flex( - *ngFor='let button of rightToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} + start-page(*ngIf='ready && app.tabs.length == 0') - button.btn.btn-secondary.btn-tab-bar.btn-update( - *ngIf='updatesAvailable', - title='Update available - Click to install', - (click)='updateApp()', - [fastHtmlBind]='updateIcon' - ) - - window-controls.background( - *ngIf='config.store.appearance.frame == "thin" \ - && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', - ) - - start-page(*ngIf='ready && app.tabs.length == 0') - - tab-body( - *ngFor='let tab of unsortedTabs', - [active]='tab == app.activeTab', - [tab]='tab', - ) + tab-body( + *ngFor='let tab of unsortedTabs', + [active]='tab == app.activeTab', + [tab]='tab', + ) ng-template(ngbModalContainer) diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss index ddb38bf1..76daa36b 100644 --- a/terminus-core/src/components/appRoot.component.scss +++ b/terminus-core/src/components/appRoot.component.scss @@ -35,26 +35,49 @@ $side-tab-width: 200px; flex-direction: column; } - &.with-side-tab { - width: calc(100% - #{$side-tab-width}); + &.tabs-on-side { + flex-direction: row-reverse; + + &.tabs-on-top { + flex-direction: row; + } } } +.content.tabs-on-side > .tab-bar { + height: 100%; + width: $side-tab-width; + overflow-y: auto; + overflow-x: hidden; + flex-direction: column; + background: rgba(0, 0, 0, 0.25); + + .tabs { + width: $side-tab-width; + flex: none; + flex-direction: column; + + tab-header { + flex: 0 0 $tabs-height; + } + } + + .drag-space { + flex: auto; + } +} + + .tab-bar { flex: none; height: $tabs-height; display: flex; width: 100%; - &.vertical { - height: 100%; - width: $side-tab-width; - overflow-y: auto; - overflow-x: hidden; - } .btn-tab-bar { line-height: $tabs-height + 2px; + height: $tabs-height; cursor: pointer; display: flex; @@ -79,12 +102,6 @@ $side-tab-width: 200px; flex: 0 1 auto; display: flex; min-width: 0; - - &.vertical { - width: $side-tab-width; - flex: auto; - flex-direction: column; - } } &>.drag-space { @@ -100,7 +117,10 @@ $side-tab-width: 200px; & > .inset { width: 85px; + height: $tabs-height; flex: none; + opacity: 0; + -webkit-app-region: drag; } window-controls { diff --git a/terminus-core/src/components/appRoot.component.ts b/terminus-core/src/components/appRoot.component.ts index 0ae1171f..16c06999 100644 --- a/terminus-core/src/components/appRoot.component.ts +++ b/terminus-core/src/components/appRoot.component.ts @@ -184,6 +184,10 @@ export class AppRootComponent { return false } + hasVerticalTabs () { + return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right' + } + async updateApp () { if ((await this.electron.showMessageBox( this.hostApp.getWindow(), diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index b6369316..7a787471 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -43,21 +43,28 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') ngbButton, [value]='"top"' ) - | On the top + | Top label.btn.btn-secondary(ngbButtonLabel) input( type='radio', ngbButton, [value]='"bottom"' ) - | At the bottom + | Bottom label.btn.btn-secondary(ngbButtonLabel) input( type='radio', ngbButton, [value]='"left"' ) - | At the left + | Left + label.btn.btn-secondary(ngbButtonLabel) + input( + type='radio', + ngbButton, + [value]='"right"' + ) + | Right .form-line .header From bbe6b61d63a6e2ba7908b718ab4e03be56ab51e8 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 18:20:36 +0000 Subject: [PATCH 13/18] docs: update README.md [skip ci] --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 868ad12c..b01351e5 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Mateusz Tracz

💻
pinpin

💻 + +
Takuro Onoda

💻 + From 326901b7e835faab368307300b070580eca9350b Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 6 Dec 2020 18:20:37 +0000 Subject: [PATCH 14/18] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 6a3ac35c..910e8b6c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -325,6 +325,15 @@ "contributions": [ "code" ] + }, + { + "login": "TakuroOnoda", + "name": "Takuro Onoda", + "avatar_url": "https://avatars0.githubusercontent.com/u/1407926?v=4", + "profile": "https://github.com/TakuroOnoda", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, From 66558290a0fabb5ac5b1686e0f3bb1bf5ed70a78 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Wed, 9 Dec 2020 09:30:20 +0100 Subject: [PATCH 15/18] fixed missing tabs at the bottom --- terminus-core/src/components/appRoot.component.pug | 2 -- 1 file changed, 2 deletions(-) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 7630ade9..32485671 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -12,7 +12,6 @@ title-bar( && config.store.appearance.frame == "thin" \ && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') .tabs( - *ngIf='config.store.appearance.tabsLocation != "bottom"' dnd-sortable-container, [sortableData]='app.tabs', ) @@ -22,7 +21,6 @@ title-bar( [sortableIndex]='idx', (onDragStart)='onTabDragStart()', (onDragEnd)='onTabDragEnd()', - [index]='idx', [tab]='tab', [active]='tab == app.activeTab', From b75775283f84f5652d072a7d5a27d8c126bd0fd4 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 13 Dec 2020 12:21:28 +0100 Subject: [PATCH 16/18] use run-script-os for xcopy --- terminus-ssh/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json index 673d5328..5fbecdeb 100644 --- a/terminus-ssh/package.json +++ b/terminus-ssh/package.json @@ -10,7 +10,9 @@ "scripts": { "build": "webpack --progress --color", "watch": "webpack --progress --color --watch", - "postinstall": "xcopy /i /y node_modules\\ssh2\\util\\pagent.exe util\\" + "postinstall": "run-script-os", + "postinstall:darwin:linux": "exit", + "postinstall:win32": "xcopy /i /y node_modules\\ssh2\\util\\pagent.exe util\\" }, "files": [ "dist", From 51d54a84773e058470b6bb9899b6e0eeb8fc7a44 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 13 Dec 2020 13:36:09 +0100 Subject: [PATCH 17/18] fixed compact theme icon size (fixes #3196, fixes #3197) --- terminus-core/src/theme.compact.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/terminus-core/src/theme.compact.scss b/terminus-core/src/theme.compact.scss index b3ed92ed..a871c75a 100644 --- a/terminus-core/src/theme.compact.scss +++ b/terminus-core/src/theme.compact.scss @@ -6,6 +6,7 @@ app-root { .btn-tab-bar { line-height: 29px !important; + height: 27px !important; svg { height: 14px; From 0971a85db4f57f072df571c14f8f3ee3d4ba0632 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 13 Dec 2020 13:36:37 +0100 Subject: [PATCH 18/18] ssh: added dynamic port forwarding (fixes #2077) --- terminus-ssh/package.json | 4 +- terminus-ssh/src/api.ts | 70 ++++++++---- .../sshPortForwardingModal.component.pug | 21 +++- terminus-ssh/src/services/ssh.service.ts | 3 +- terminus-ssh/webpack.config.js | 1 + terminus-ssh/yarn.lock | 106 +++++++++++++++++- 6 files changed, 180 insertions(+), 25 deletions(-) diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json index 5fbecdeb..91977e66 100644 --- a/terminus-ssh/package.json +++ b/terminus-ssh/package.json @@ -26,9 +26,11 @@ "ansi-colors": "^4.1.1", "cli-spinner": "^0.2.10", "run-script-os": "^1.1.3", - "ssh2": "^0.8.2", + "socksv5": "^0.0.6", + "ssh2": "^0.8.9", "ssh2-streams": "Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5", "sshpk": "^1.16.1", + "strip-ansi": "^6.0.0", "temp": "^0.9.1", "terminus-terminal": "^1.0.98-nightly.0" }, diff --git a/terminus-ssh/src/api.ts b/terminus-ssh/src/api.ts index 4e9d662b..d94b69e3 100644 --- a/terminus-ssh/src/api.ts +++ b/terminus-ssh/src/api.ts @@ -1,4 +1,6 @@ import colors from 'ansi-colors' +import stripAnsi from 'strip-ansi' +import socksv5 from 'socksv5' import { BaseSession } from 'terminus-terminal' import { Server, Socket, createServer, createConnection } from 'net' import { Client, ClientChannel } from 'ssh2' @@ -43,7 +45,7 @@ export interface SSHConnection { } export enum PortForwardType { - Local, Remote + Local, Remote, Dynamic } export class ForwardedPort { @@ -55,13 +57,40 @@ export class ForwardedPort { private listener: Server - async startLocalListener (callback: (Socket) => void): Promise { - this.listener = createServer(callback) - return new Promise((resolve, reject) => { - this.listener.listen(this.port, '127.0.0.1') - this.listener.on('error', reject) - this.listener.on('listening', resolve) - }) + async startLocalListener (callback: (accept: () => Socket, reject: () => void, sourceAddress: string|null, sourcePort: number|null, targetAddress: string, targetPort: number) => void): Promise { + if (this.type === PortForwardType.Local) { + this.listener = createServer(s => callback( + () => s, + () => s.destroy(), + s.remoteAddress ?? null, + s.remotePort ?? null, + this.targetAddress, + this.targetPort, + )) + return new Promise((resolve, reject) => { + this.listener.listen(this.port, this.host) + this.listener.on('error', reject) + this.listener.on('listening', resolve) + }) + } else if (this.type === PortForwardType.Dynamic) { + return new Promise((resolve, reject) => { + this.listener = socksv5.createServer((info, accept, reject) => { + callback( + () => accept(true), + () => reject(), + null, + null, + info.dstAddr, + info.dstPort, + ) + }) + this.listener.on('error', reject) + this.listener.listen(this.port, this.host, resolve) + ;(this.listener as any).useAuth(socksv5.auth.None()) + }) + } else { + throw new Error('Invalid forward type for a local listener') + } } stopLocalListener (): void { @@ -71,8 +100,10 @@ export class ForwardedPort { toString (): string { if (this.type === PortForwardType.Local) { return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}` - } else { + } if (this.type === PortForwardType.Remote) { return `(remote) ${this.host}:${this.port} → (local) ${this.targetAddress}:${this.targetPort}` + } else { + return `(dynamic) ${this.host}:${this.port}` } } } @@ -232,25 +263,26 @@ export class SSHSession extends BaseSession { emitServiceMessage (msg: string): void { this.serviceMessage.next(msg) - this.logger.info(msg) + this.logger.info(stripAnsi(msg)) } async addPortForward (fw: ForwardedPort): Promise { - if (fw.type === PortForwardType.Local) { - await fw.startLocalListener((socket: Socket) => { + if (fw.type === PortForwardType.Local || fw.type === PortForwardType.Dynamic) { + await fw.startLocalListener((accept, reject, sourceAddress, sourcePort, targetAddress, targetPort) => { this.logger.info(`New connection on ${fw}`) this.ssh.forwardOut( - socket.remoteAddress || '127.0.0.1', - socket.remotePort || 0, - fw.targetAddress, - fw.targetPort, + sourceAddress || '127.0.0.1', + sourcePort || 0, + targetAddress, + targetPort, (err, stream) => { if (err) { - this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwarded connection via ${fw}: ${err}`) - socket.destroy() + this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwarded connection to ${targetAddress}:${targetPort} via ${fw}: ${err}`) + reject() return } if (stream) { + const socket = accept() stream.pipe(socket) socket.pipe(stream) stream.on('close', () => { @@ -286,7 +318,7 @@ export class SSHSession extends BaseSession { } async removePortForward (fw: ForwardedPort): Promise { - if (fw.type === PortForwardType.Local) { + if (fw.type === PortForwardType.Local || fw.type === PortForwardType.Dynamic) { fw.stopLocalListener() this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw) } diff --git a/terminus-ssh/src/components/sshPortForwardingModal.component.pug b/terminus-ssh/src/components/sshPortForwardingModal.component.pug index f5afe02c..270ece9d 100644 --- a/terminus-ssh/src/components/sshPortForwardingModal.component.pug +++ b/terminus-ssh/src/components/sshPortForwardingModal.component.pug @@ -6,12 +6,22 @@ .list-group-item.d-flex.align-items-center(*ngFor='let fw of session.forwardedPorts') strong(*ngIf='fw.type === PortForwardType.Local') Local strong(*ngIf='fw.type === PortForwardType.Remote') Remote - .ml-3 {{fw.host}}:{{fw.port}} → {{fw.targetAddress}}:{{fw.targetPort}} + strong(*ngIf='fw.type === PortForwardType.Dynamic') Dynamic + .ml-3 {{fw.host}}:{{fw.port}} + .ml-2 → + .ml-2(*ngIf='fw.type !== PortForwardType.Dynamic') {{fw.targetAddress}}:{{fw.targetPort}} + .ml-2(*ngIf='fw.type === PortForwardType.Dynamic') SOCKS proxy button.btn.btn-link.ml-auto((click)='remove(fw)') i.fas.fa-trash-alt.mr-2 span Remove - .input-group.mb-2 + .input-group.mb-2(*ngIf='newForward.type === PortForwardType.Dynamic') + input.form-control(type='text', [(ngModel)]='newForward.host') + .input-group-append + .input-group-text : + input.form-control(type='number', [(ngModel)]='newForward.port') + + .input-group.mb-2(*ngIf='newForward.type !== PortForwardType.Dynamic') input.form-control(type='text', [(ngModel)]='newForward.host') .input-group-append .input-group-text : @@ -42,6 +52,13 @@ [value]='PortForwardType.Remote' ) | Remote + label.btn.btn-secondary.m-0(ngbButtonLabel) + input( + type='radio', + ngbButton, + [value]='PortForwardType.Dynamic' + ) + | Dynamic button.btn.btn-primary((click)='addForward()') i.fas.fa-check.mr-2 diff --git a/terminus-ssh/src/services/ssh.service.ts b/terminus-ssh/src/services/ssh.service.ts index ee8098c3..2be929ff 100644 --- a/terminus-ssh/src/services/ssh.service.ts +++ b/terminus-ssh/src/services/ssh.service.ts @@ -1,4 +1,5 @@ import colors from 'ansi-colors' +import stripAnsi from 'strip-ansi' import { open as openTemp } from 'temp' import { Injectable, NgZone } from '@angular/core' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' @@ -137,7 +138,7 @@ export class SSHService { const log = (s: any) => { logCallback!(s) - this.logger.info(s) + this.logger.info(stripAnsi(s)) } let privateKey: string|null = null diff --git a/terminus-ssh/webpack.config.js b/terminus-ssh/webpack.config.js index b0ef1451..482f99ee 100644 --- a/terminus-ssh/webpack.config.js +++ b/terminus-ssh/webpack.config.js @@ -50,6 +50,7 @@ module.exports = { 'keytar', 'path', 'ngx-toastr', + 'socksv5', 'windows-native-registry', 'windows-process-tree/build/Release/windows_process_tree.node', /^rxjs/, diff --git a/terminus-ssh/yarn.lock b/terminus-ssh/yarn.lock index c0387d7d..101f8e1f 100644 --- a/terminus-ssh/yarn.lock +++ b/terminus-ssh/yarn.lock @@ -32,6 +32,11 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + asn1@~0.2.0, asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -44,6 +49,11 @@ assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +async@0.2.x: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -69,11 +79,42 @@ cli-spinner@^0.2.10: resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47" integrity sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q== +cli@0.4.x: + version "0.4.5" + resolved "https://registry.yarnpkg.com/cli/-/cli-0.4.5.tgz#78f9485cd161b566e9a6c72d7170c4270e81db61" + integrity sha1-ePlIXNFhtWbppsctcXDEJw6B22E= + dependencies: + glob ">= 3.1.4" + +cliff@0.1.x: + version "0.1.10" + resolved "https://registry.yarnpkg.com/cliff/-/cliff-0.1.10.tgz#53be33ea9f59bec85609ee300ac4207603e52013" + integrity sha1-U74z6p9ZvshWCe4wCsQgdgPlIBM= + dependencies: + colors "~1.0.3" + eyes "~0.1.8" + winston "0.8.x" + +colors@0.6.x: + version "0.6.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" + integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w= + +colors@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +cycle@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -89,6 +130,11 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +eyes@0.1.x, eyes@~0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -101,7 +147,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob@^7.1.3: +"glob@>= 3.1.4", glob@^7.1.3: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -126,6 +172,20 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ipv6@*: + version "3.1.3" + resolved "https://registry.yarnpkg.com/ipv6/-/ipv6-3.1.3.tgz#4d9064f9c2dafa0dd10b8b7d76ffca4aad31b3b9" + integrity sha1-TZBk+cLa+g3RC4t9dv/KSq0xs7k= + dependencies: + cli "0.4.x" + cliff "0.1.x" + sprintf "0.1.x" + +isstream@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -150,6 +210,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +pkginfo@0.3.x: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE= + rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -167,6 +232,18 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +socksv5@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/socksv5/-/socksv5-0.0.6.tgz#1327235ff7e8de21ac434a0a579dc69c3f071061" + integrity sha1-EycjX/fo3iGsQ0oKV53GnD8HEGE= + dependencies: + ipv6 "*" + +sprintf@0.1.x: + version "0.1.5" + resolved "https://registry.yarnpkg.com/sprintf/-/sprintf-0.1.5.tgz#8f83e39a9317c1a502cb7db8050e51c679f6edcf" + integrity sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8= + ssh2-streams@Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5: version "0.4.10" resolved "https://codeload.github.com/Eugeny/ssh2-streams/tar.gz/75f6d3425d071ac73a18fd46e2f5e738bfe897c5" @@ -184,7 +261,7 @@ ssh2-streams@~0.4.10: bcrypt-pbkdf "^1.0.2" streamsearch "~0.1.2" -ssh2@^0.8.2: +ssh2@^0.8.9: version "0.8.9" resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3" integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw== @@ -206,11 +283,23 @@ sshpk@^1.16.1: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + streamsearch@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + temp@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.1.tgz#2d666114fafa26966cd4065996d7ceedd4dd4697" @@ -228,6 +317,19 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +winston@0.8.x: + version "0.8.3" + resolved "https://registry.yarnpkg.com/winston/-/winston-0.8.3.tgz#64b6abf4cd01adcaefd5009393b1d8e8bec19db0" + integrity sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA= + dependencies: + async "0.2.x" + colors "0.6.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"