mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-12 02:15:01 +00:00
Move Teleport Connect over to Vite (#36921)
* Move Teleport connect over to Vite * Clean up the Electron Vite config * Add mts to prettier/eslint * Add license headers * Dedupe @babel scope * Remove console.log from mainProcess * Set suggestedReviewers on CreateAccessRequestRequest * Remove unneeded code added from strict null checks * Move out dir to build/app On masted it's build/app/dist. We don't want to use build directly, as the app is being packaged in build/release. * Move Node-only deps to dependencies https://electron-vite.org/guide/dev#dependencies-vs-devdependencies cross-env has been removed since it's not needed at all. * Remove eval warning suppression * Fix default path of tsh * Rename dev-term to start-term-skip-native-deps * Use correct `oneofKind` value for `ptyEventOneOfIsStartError` * Undo strict null check changes * Correctly construct env vars struct for shell Based on https://stackoverflow.com/a/66989401 * Allow reloading renderer app * Move JSDoc for TshdEventContextBridgeService to correct position * Remove outdated comment about type casting in tshdEvents/index.ts * Drop type cast for error.cause['message'] * Ignore teleterm's build dir in .eslintignore **/dist/** has been removed from ignorePatterns because it's no longer necessary, neither Web UI nor Connect build in a dir matching this pattern. * Define NODE_ENV for main and renderer * Define only NODE_ENV, not whole process.env Otherwise process.env in the main process is always replaced with an object containing just NODE_ENV. We need process.env to be properly populated since it's then used when spawning tsh daemon and other processes. Using define like this guarantees that only callsites using process.env.NODE_ENV directly will be affected. * Add support for the cluster preferences backend mismatch from the gRPC UserPreferences object * Return resourceIds from preferences, convert preferences before updating * Future proof all of the clusterPreferences object getting converted correctly * Fix cluster preferences for leaf clusters * Use correct `AssistViewMode` enum, remove the old one and unused interface * Lint fix * Add back in JS protobuf stuff, it can be removed in a later PR * Remove `List` from property * Add license header * Remove console.logs --------- Co-authored-by: Rafał Cieślak <[email protected]> Co-authored-by: Grzegorz Zdunek <[email protected]>
This commit is contained in:
co-authored by
Rafał Cieślak
Grzegorz Zdunek
parent
8360fc5e25
commit
200553c474
@@ -3,3 +3,5 @@
|
||||
|
||||
# Ignore WASM generated files:
|
||||
web/packages/teleport/src/ironrdp/pkg
|
||||
|
||||
web/packages/teleterm/build
|
||||
|
||||
+4
-3
@@ -10,6 +10,7 @@
|
||||
"start-teleport-e": "yarn workspace @gravitational/teleport.e start",
|
||||
"build-term": "yarn workspace @gravitational/teleterm build",
|
||||
"start-term": "yarn workspace @gravitational/teleterm start",
|
||||
"start-term-skip-native-deps": "yarn workspace @gravitational/teleterm start-skip-native-deps",
|
||||
"package-term": "yarn workspace @gravitational/teleterm package",
|
||||
"storybook": "start-storybook -p 9002 -c web/.storybook -s web/.storybook/public",
|
||||
"storybook-smoke-test": "yarn storybook --ci --smoke-test",
|
||||
@@ -18,10 +19,10 @@
|
||||
"test-update-snapshot": "yarn test -- --updateSnapshot",
|
||||
"tdd": "jest --watch",
|
||||
"lint": "yarn prettier-check && yarn eslint",
|
||||
"eslint": "eslint --quiet '+(e|web)/**/*.{ts,tsx,js,jsx}'",
|
||||
"eslint": "eslint --quiet '+(e|web)/**/*.{ts,tsx,js,jsx,mts}'",
|
||||
"type-check": "NODE_OPTIONS='--max-old-space-size=4096' tsc --noEmit",
|
||||
"prettier-check": "yarn prettier --check '+(e|web)/**/*.{ts,tsx,js,jsx}'",
|
||||
"prettier-write": "yarn prettier --write --loglevel silent '+(e|web)/**/*.{ts,tsx,js,jsx}'",
|
||||
"prettier-check": "yarn prettier --check '+(e|web)/**/*.{ts,tsx,js,jsx,mts}'",
|
||||
"prettier-write": "yarn prettier --write --loglevel silent '+(e|web)/**/*.{ts,tsx,js,jsx,mts}'",
|
||||
"process-icons": "node web/packages/design/src/Icon/script/script.js & yarn prettier --loglevel silent --write 'web/packages/design/src/Icon/Icons/*.tsx'",
|
||||
"nop": "exit 0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
export function cspPlugin(csp: string): Plugin {
|
||||
return {
|
||||
name: 'teleport-connect-html-plugin',
|
||||
transformIndexHtml(html) {
|
||||
return {
|
||||
html,
|
||||
tags: [
|
||||
{
|
||||
tag: 'meta',
|
||||
attrs: {
|
||||
'http-equiv': 'Content-Security-Policy',
|
||||
content: csp,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -157,6 +157,7 @@ function createDefaultConfig() {
|
||||
design: path.join(__dirname, '/../../design/src'),
|
||||
shared: path.join(__dirname, '/../../shared'),
|
||||
'gen-proto-js': path.join(__dirname, '/../../../../gen/proto/js'),
|
||||
'gen-proto-ts': path.join(__dirname, '/../../../../gen/proto/ts'),
|
||||
},
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,19 +24,20 @@ import {
|
||||
|
||||
import { KeysEnum, storageService } from 'teleport/services/storageService';
|
||||
|
||||
import { ThemePreference } from 'teleport/services/userPreferences/types';
|
||||
import cfg from 'teleport/config';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import { darkTheme, lightTheme, bblpTheme } from '../theme';
|
||||
|
||||
import { GlobalStyle } from './globals';
|
||||
|
||||
function themePreferenceToTheme(themePreference: ThemePreference) {
|
||||
return themePreference === ThemePreference.Light ? lightTheme : darkTheme;
|
||||
function themePreferenceToTheme(themePreference: Theme) {
|
||||
return themePreference === Theme.LIGHT ? lightTheme : darkTheme;
|
||||
}
|
||||
|
||||
const ThemeProvider = props => {
|
||||
const [themePreference, setThemePreference] = useState<ThemePreference>(
|
||||
const [themePreference, setThemePreference] = useState<Theme>(
|
||||
storageService.getThemePreference()
|
||||
);
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ import {
|
||||
ArrowsOut,
|
||||
} from 'design/Icon';
|
||||
|
||||
import { ViewMode } from 'shared/services/unifiedResourcePreferences';
|
||||
import { ViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import { HoverTooltip } from 'shared/components/ToolTip';
|
||||
|
||||
import { FilterKind } from './UnifiedResources';
|
||||
@@ -132,7 +133,7 @@ export function FilterPanel({
|
||||
<Flex mr={1}>{BulkActions}</Flex>
|
||||
{!hideViewModeOptions && (
|
||||
<>
|
||||
{currentViewMode === ViewMode.VIEW_MODE_LIST && (
|
||||
{currentViewMode === ViewMode.LIST && (
|
||||
<ButtonBorder
|
||||
size="small"
|
||||
css={`
|
||||
@@ -468,10 +469,8 @@ function ViewModeSwitch({
|
||||
return (
|
||||
<ViewModeSwitchContainer>
|
||||
<ViewModeSwitchButton
|
||||
className={
|
||||
currentViewMode === ViewMode.VIEW_MODE_CARD ? 'selected' : ''
|
||||
}
|
||||
onClick={() => setCurrentViewMode(ViewMode.VIEW_MODE_CARD)}
|
||||
className={currentViewMode === ViewMode.CARD ? 'selected' : ''}
|
||||
onClick={() => setCurrentViewMode(ViewMode.CARD)}
|
||||
css={`
|
||||
border-right: 1px solid
|
||||
${props => props.theme.colors.spotBackground[2]};
|
||||
@@ -482,10 +481,8 @@ function ViewModeSwitch({
|
||||
<SquaresFour size="small" color="text.main" />
|
||||
</ViewModeSwitchButton>
|
||||
<ViewModeSwitchButton
|
||||
className={
|
||||
currentViewMode === ViewMode.VIEW_MODE_LIST ? 'selected' : ''
|
||||
}
|
||||
onClick={() => setCurrentViewMode(ViewMode.VIEW_MODE_LIST)}
|
||||
className={currentViewMode === ViewMode.LIST ? 'selected' : ''}
|
||||
onClick={() => setCurrentViewMode(ViewMode.LIST)}
|
||||
css={`
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
|
||||
@@ -30,11 +30,11 @@ import { UrlResourcesParams } from 'teleport/config';
|
||||
import { ResourcesResponse } from 'teleport/services/agents';
|
||||
|
||||
import {
|
||||
UnifiedResourcePreferences,
|
||||
DefaultTab,
|
||||
ViewMode,
|
||||
LabelsViewMode,
|
||||
} from 'shared/services/unifiedResourcePreferences';
|
||||
UnifiedResourcePreferences,
|
||||
ViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import { makeErrorAttempt, makeProcessingAttempt } from 'shared/hooks/useAsync';
|
||||
|
||||
@@ -97,9 +97,9 @@ const story = ({
|
||||
};
|
||||
return () => {
|
||||
const [userPrefs, setUserPrefs] = useState<UnifiedResourcePreferences>({
|
||||
defaultTab: DefaultTab.DEFAULT_TAB_ALL,
|
||||
viewMode: ViewMode.VIEW_MODE_CARD,
|
||||
labelsViewMode: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
defaultTab: DefaultTab.ALL,
|
||||
viewMode: ViewMode.CARD,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
});
|
||||
const { fetch, attempt, resources } = useUnifiedResourcesFetch({
|
||||
fetchFunc,
|
||||
|
||||
@@ -43,10 +43,11 @@ import { ResourcesResponse } from 'teleport/services/agents';
|
||||
|
||||
import {
|
||||
DefaultTab,
|
||||
ViewMode,
|
||||
UnifiedResourcePreferences,
|
||||
LabelsViewMode,
|
||||
} from 'shared/services/unifiedResourcePreferences';
|
||||
UnifiedResourcePreferences,
|
||||
ViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import { HoverTooltip } from 'shared/components/ToolTip';
|
||||
import {
|
||||
makeEmptyAttempt,
|
||||
@@ -90,11 +91,11 @@ export const PINNING_NOT_SUPPORTED_MESSAGE =
|
||||
const tabs: { label: string; value: DefaultTab }[] = [
|
||||
{
|
||||
label: 'All Resources',
|
||||
value: DefaultTab.DEFAULT_TAB_ALL,
|
||||
value: DefaultTab.ALL,
|
||||
},
|
||||
{
|
||||
label: 'Pinned Resources',
|
||||
value: DefaultTab.DEFAULT_TAB_PINNED,
|
||||
value: DefaultTab.PINNED,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -304,7 +305,7 @@ export function UnifiedResources(props: UnifiedResourcesProps) {
|
||||
};
|
||||
|
||||
const selectTab = (value: DefaultTab) => {
|
||||
const pinnedOnly = value === DefaultTab.DEFAULT_TAB_PINNED;
|
||||
const pinnedOnly = value === DefaultTab.PINNED;
|
||||
setParams({
|
||||
...params,
|
||||
pinnedOnly,
|
||||
@@ -366,8 +367,7 @@ export function UnifiedResources(props: UnifiedResourcesProps) {
|
||||
};
|
||||
|
||||
const expandAllLabels =
|
||||
unifiedResourcePreferences.labelsViewMode ===
|
||||
LabelsViewMode.LABELS_VIEW_MODE_EXPANDED;
|
||||
unifiedResourcePreferences.labelsViewMode === LabelsViewMode.EXPANDED;
|
||||
|
||||
useEffect(() => {
|
||||
const resizeObserver = new ResizeObserver(entries => {
|
||||
@@ -386,8 +386,7 @@ export function UnifiedResources(props: UnifiedResourcesProps) {
|
||||
}, []);
|
||||
|
||||
const ViewComponent =
|
||||
unifiedResourcePreferences.viewMode === ViewMode.VIEW_MODE_CARD ||
|
||||
forceCardView
|
||||
unifiedResourcePreferences.viewMode === ViewMode.CARD || forceCardView
|
||||
? CardsView
|
||||
: ListView;
|
||||
|
||||
@@ -448,9 +447,7 @@ export function UnifiedResources(props: UnifiedResourcesProps) {
|
||||
ClusterDropdown={ClusterDropdown}
|
||||
setExpandAllLabels={expandAllLabels => {
|
||||
setLabelsViewMode(
|
||||
expandAllLabels
|
||||
? LabelsViewMode.LABELS_VIEW_MODE_EXPANDED
|
||||
: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED
|
||||
expandAllLabels ? LabelsViewMode.EXPANDED : LabelsViewMode.COLLAPSED
|
||||
);
|
||||
}}
|
||||
hideViewModeOptions={forceCardView}
|
||||
@@ -498,14 +495,14 @@ export function UnifiedResources(props: UnifiedResourcesProps) {
|
||||
key={tab.value}
|
||||
onClick={() => selectTab(tab.value)}
|
||||
disabled={
|
||||
tab.value === DefaultTab.DEFAULT_TAB_PINNED &&
|
||||
tab.value === DefaultTab.PINNED &&
|
||||
pinning.kind === 'not-supported'
|
||||
}
|
||||
title={tab.label}
|
||||
isSelected={
|
||||
params.pinnedOnly
|
||||
? tab.value === DefaultTab.DEFAULT_TAB_PINNED
|
||||
: tab.value === DefaultTab.DEFAULT_TAB_ALL
|
||||
? tab.value === DefaultTab.PINNED
|
||||
: tab.value === DefaultTab.ALL
|
||||
}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Should be kept in sync with
|
||||
// https://github.com/gravitational/teleport/blob/cc330931e2b691b7438bfee73587e828e874fa47/api/proto/teleport/userpreferences/v1/unified_resource_preferences.proto
|
||||
//
|
||||
// The exported enums and types have the same names and values/properties as
|
||||
// the values generated by protogen.
|
||||
// It allows using them interchangeably with the generated values.
|
||||
//
|
||||
// Ideally, we should use the generated values, but it was a challenge
|
||||
// to make them work with Vite (the generated files are in CommonJS format);
|
||||
// additionally, they increased the bundle size significantly.
|
||||
|
||||
/** Preferences related to the Unified Resource view. */
|
||||
export interface UnifiedResourcePreferences {
|
||||
/** Default tab selected in the unified resource view. */
|
||||
defaultTab: DefaultTab;
|
||||
/** View mode selected in the unified resource view (Cards/List). */
|
||||
viewMode: ViewMode;
|
||||
/** Labels view mode is whether the labels for resources should all be collapsed or expanded. This only applies to the list view. */
|
||||
labelsViewMode: LabelsViewMode;
|
||||
}
|
||||
|
||||
export enum DefaultTab {
|
||||
DEFAULT_TAB_UNSPECIFIED = 0,
|
||||
DEFAULT_TAB_ALL = 1,
|
||||
DEFAULT_TAB_PINNED = 2,
|
||||
}
|
||||
|
||||
export enum ViewMode {
|
||||
VIEW_MODE_UNSPECIFIED = 0,
|
||||
VIEW_MODE_CARD = 1,
|
||||
VIEW_MODE_LIST = 2,
|
||||
}
|
||||
|
||||
export enum LabelsViewMode {
|
||||
LABELS_VIEW_MODE_UNSPECIFIED = 0,
|
||||
LABELS_VIEW_MODE_EXPANDED = 1,
|
||||
LABELS_VIEW_MODE_COLLAPSED = 2,
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import React, { useEffect, useState } from 'react';
|
||||
import styled, { keyframes } from 'styled-components';
|
||||
import { sharedStyles } from 'design/theme/themes/sharedStyles';
|
||||
|
||||
import { AssistViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { Header } from 'teleport/Assist/Header';
|
||||
import { ConversationHistory } from 'teleport/Assist/ConversationHistory';
|
||||
import {
|
||||
@@ -28,7 +30,6 @@ import {
|
||||
} from 'teleport/Assist/context/AssistContext';
|
||||
import { ConversationList } from 'teleport/Assist/ConversationList';
|
||||
import { useLayout } from 'teleport/Main/LayoutContext';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
import { Settings } from 'teleport/Assist/Settings';
|
||||
import { ErrorBanner, ErrorList } from 'teleport/Assist/ErrorBanner';
|
||||
import { useUser } from 'teleport/User/UserContext';
|
||||
@@ -60,9 +61,9 @@ const slideIn = keyframes`
|
||||
}
|
||||
`;
|
||||
|
||||
function variables(props: { viewMode: ViewMode }) {
|
||||
function variables(props: { viewMode: AssistViewMode }) {
|
||||
switch (props.viewMode) {
|
||||
case ViewMode.Popup:
|
||||
case AssistViewMode.POPUP:
|
||||
return {
|
||||
'--assist-gutter': '20px',
|
||||
'--assist-border-radius': '15px',
|
||||
@@ -76,8 +77,8 @@ function variables(props: { viewMode: ViewMode }) {
|
||||
'--assist-bottom-padding': '5px',
|
||||
};
|
||||
|
||||
case ViewMode.PopupExpanded:
|
||||
case ViewMode.PopupExpandedSidebarVisible:
|
||||
case AssistViewMode.POPUP_EXPANDED:
|
||||
case AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE:
|
||||
return {
|
||||
'--assist-gutter': '20px',
|
||||
'--assist-border-radius': '15px',
|
||||
@@ -91,7 +92,7 @@ function variables(props: { viewMode: ViewMode }) {
|
||||
'--assist-bottom-padding': '5px',
|
||||
};
|
||||
|
||||
case ViewMode.Docked:
|
||||
case AssistViewMode.DOCKED:
|
||||
return {
|
||||
'--assist-gutter': '0',
|
||||
'--assist-border-radius': '0',
|
||||
@@ -108,11 +109,11 @@ function variables(props: { viewMode: ViewMode }) {
|
||||
}
|
||||
|
||||
function sidebarVariables(props: {
|
||||
viewMode: ViewMode;
|
||||
viewMode: AssistViewMode;
|
||||
sidebarVisible: boolean;
|
||||
}) {
|
||||
switch (props.viewMode) {
|
||||
case ViewMode.Popup:
|
||||
case AssistViewMode.POPUP:
|
||||
if (props.sidebarVisible) {
|
||||
return {
|
||||
'--conversation-width': '550px',
|
||||
@@ -134,8 +135,8 @@ function sidebarVariables(props: {
|
||||
'--conversation-list-position': 'absolute',
|
||||
};
|
||||
|
||||
case ViewMode.PopupExpanded:
|
||||
case ViewMode.PopupExpandedSidebarVisible:
|
||||
case AssistViewMode.POPUP_EXPANDED:
|
||||
case AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE:
|
||||
if (props.sidebarVisible) {
|
||||
return {
|
||||
'--conversation-list-margin': '0',
|
||||
@@ -157,7 +158,7 @@ function sidebarVariables(props: {
|
||||
'--conversation-list-position': 'absolute',
|
||||
};
|
||||
|
||||
case ViewMode.Docked:
|
||||
case AssistViewMode.DOCKED:
|
||||
if (props.sidebarVisible) {
|
||||
return {
|
||||
'--conversation-width': `${dockedAssistWidth}px`,
|
||||
@@ -301,11 +302,17 @@ function AssistContent(props: AssistProps) {
|
||||
const { hasDockedElement, setHasDockedElement } = useLayout();
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasDockedElement && preferences.assist.viewMode === ViewMode.Docked) {
|
||||
if (
|
||||
!hasDockedElement &&
|
||||
preferences.assist.viewMode === AssistViewMode.DOCKED
|
||||
) {
|
||||
setHasDockedElement(true);
|
||||
}
|
||||
|
||||
if (hasDockedElement && preferences.assist.viewMode !== ViewMode.Docked) {
|
||||
if (
|
||||
hasDockedElement &&
|
||||
preferences.assist.viewMode !== AssistViewMode.DOCKED
|
||||
) {
|
||||
setHasDockedElement(false);
|
||||
}
|
||||
}, [hasDockedElement, preferences.assist.viewMode]);
|
||||
@@ -320,8 +327,8 @@ function AssistContent(props: AssistProps) {
|
||||
}
|
||||
|
||||
if (
|
||||
preferences.assist.viewMode === ViewMode.Popup ||
|
||||
preferences.assist.viewMode === ViewMode.Docked
|
||||
preferences.assist.viewMode === AssistViewMode.POPUP ||
|
||||
preferences.assist.viewMode === AssistViewMode.DOCKED
|
||||
) {
|
||||
toggleSidebar(false);
|
||||
}
|
||||
@@ -333,7 +340,8 @@ function AssistContent(props: AssistProps) {
|
||||
|
||||
if (
|
||||
sidebarVisible &&
|
||||
preferences.assist.viewMode !== ViewMode.PopupExpandedSidebarVisible
|
||||
preferences.assist.viewMode !==
|
||||
AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE
|
||||
) {
|
||||
toggleSidebar(false);
|
||||
}
|
||||
@@ -365,7 +373,7 @@ function AssistContent(props: AssistProps) {
|
||||
</ErrorBanner>
|
||||
));
|
||||
|
||||
const docked = preferences.assist.viewMode === ViewMode.Docked;
|
||||
const docked = preferences.assist.viewMode === AssistViewMode.DOCKED;
|
||||
|
||||
return (
|
||||
<Container onClick={handleClose} docked={docked}>
|
||||
|
||||
@@ -19,14 +19,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { AssistViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { useAssist } from 'teleport/Assist/context/AssistContext';
|
||||
import { ConversationHistoryItem } from 'teleport/Assist/ConversationHistory/ConversationHistoryItem';
|
||||
import { DeleteConversationDialog } from 'teleport/Assist/ConversationHistory/DeleteConversationDialog';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
|
||||
interface ConversationHistoryProps {
|
||||
onConversationSelect: (id: string) => void;
|
||||
viewMode: ViewMode;
|
||||
viewMode: AssistViewMode;
|
||||
onError: (message: string) => void;
|
||||
}
|
||||
|
||||
@@ -58,10 +59,10 @@ const List = styled.ul.attrs({ 'data-scrollbar': 'default' })`
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
function isExpanded(viewMode: ViewMode) {
|
||||
function isExpanded(viewMode: AssistViewMode) {
|
||||
return (
|
||||
viewMode === ViewMode.PopupExpanded ||
|
||||
viewMode === ViewMode.PopupExpandedSidebarVisible
|
||||
viewMode === AssistViewMode.POPUP_EXPANDED ||
|
||||
viewMode === AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { AssistViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { Conversation } from 'teleport/Assist/Conversation';
|
||||
import { useAssist } from 'teleport/Assist/context/AssistContext';
|
||||
import { MessageBox } from 'teleport/Assist/MessageBox';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
|
||||
interface ConversationListProps {
|
||||
viewMode: ViewMode;
|
||||
viewMode: AssistViewMode;
|
||||
}
|
||||
|
||||
const Container = styled.div.attrs({ 'data-scrollbar': 'default' })`
|
||||
|
||||
@@ -26,13 +26,14 @@ import {
|
||||
SettingsIcon,
|
||||
} from 'design/SVGIcon';
|
||||
|
||||
import { AssistViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { useAssist } from 'teleport/Assist/context/AssistContext';
|
||||
import { Tooltip } from 'teleport/Assist/shared/Tooltip';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
import { HeaderIcon } from 'teleport/Assist/shared';
|
||||
|
||||
interface HeaderProps {
|
||||
viewMode: ViewMode;
|
||||
viewMode: AssistViewMode;
|
||||
sidebarVisible: boolean;
|
||||
onClose: () => void;
|
||||
onToggleSidebar: () => void;
|
||||
|
||||
@@ -19,14 +19,15 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { AssistViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import logoLight from 'teleport/Navigation/logoLight.svg';
|
||||
import logoDark from 'teleport/Navigation/logoDark.svg';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
import { Description, Title } from 'teleport/Assist/Settings/shared';
|
||||
|
||||
interface DisplaySettingsProps {
|
||||
viewMode: ViewMode;
|
||||
onChange: (viewMode: ViewMode) => void;
|
||||
viewMode: AssistViewMode;
|
||||
onChange: (viewMode: AssistViewMode) => void;
|
||||
}
|
||||
|
||||
const ViewModes = styled.div`
|
||||
@@ -241,8 +242,8 @@ export function DisplaySettings(props: DisplaySettingsProps) {
|
||||
|
||||
<ViewModes>
|
||||
<ViewModeContainer
|
||||
active={props.viewMode === ViewMode.Popup}
|
||||
onClick={() => props.onChange(ViewMode.Popup)}
|
||||
active={props.viewMode === AssistViewMode.POPUP}
|
||||
onClick={() => props.onChange(AssistViewMode.POPUP)}
|
||||
>
|
||||
<ViewModeExample>
|
||||
<DimmedBackground />
|
||||
@@ -256,8 +257,8 @@ export function DisplaySettings(props: DisplaySettingsProps) {
|
||||
Popup
|
||||
</ViewModeContainer>
|
||||
<ViewModeContainer
|
||||
active={props.viewMode === ViewMode.Docked}
|
||||
onClick={() => props.onChange(ViewMode.Docked)}
|
||||
active={props.viewMode === AssistViewMode.DOCKED}
|
||||
onClick={() => props.onChange(AssistViewMode.DOCKED)}
|
||||
>
|
||||
<ViewModeExample>
|
||||
<MockPage />
|
||||
@@ -269,8 +270,8 @@ export function DisplaySettings(props: DisplaySettingsProps) {
|
||||
Docked
|
||||
</ViewModeContainer>
|
||||
<ViewModeContainer
|
||||
active={props.viewMode === ViewMode.PopupExpanded}
|
||||
onClick={() => props.onChange(ViewMode.PopupExpanded)}
|
||||
active={props.viewMode === AssistViewMode.POPUP_EXPANDED}
|
||||
onClick={() => props.onChange(AssistViewMode.POPUP_EXPANDED)}
|
||||
>
|
||||
<ViewModeExample>
|
||||
<DimmedBackground />
|
||||
@@ -284,8 +285,12 @@ export function DisplaySettings(props: DisplaySettingsProps) {
|
||||
Expanded popup
|
||||
</ViewModeContainer>
|
||||
<ViewModeContainer
|
||||
active={props.viewMode === ViewMode.PopupExpandedSidebarVisible}
|
||||
onClick={() => props.onChange(ViewMode.PopupExpandedSidebarVisible)}
|
||||
active={
|
||||
props.viewMode === AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE
|
||||
}
|
||||
onClick={() =>
|
||||
props.onChange(AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE)
|
||||
}
|
||||
>
|
||||
<ViewModeExample>
|
||||
<DimmedBackground />
|
||||
|
||||
@@ -23,7 +23,11 @@ import { CloseIcon, DisplayIcon, TerminalIcon } from 'design/SVGIcon';
|
||||
|
||||
import Flex from 'design/Flex';
|
||||
|
||||
import { AssistUserPreferences, ViewMode } from 'teleport/Assist/types';
|
||||
import {
|
||||
AssistUserPreferences,
|
||||
AssistViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { useAssist } from 'teleport/Assist/context/AssistContext';
|
||||
import { Tooltip } from 'teleport/Assist/shared/Tooltip';
|
||||
import { HeaderIcon } from 'teleport/Assist/shared';
|
||||
@@ -40,7 +44,7 @@ interface SettingsProps {
|
||||
onDebugMenuToggle: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
const Container = styled.div<{ viewMode: ViewMode }>`
|
||||
const Container = styled.div<{ viewMode: AssistViewMode }>`
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -169,12 +173,12 @@ export function Settings(props: SettingsProps) {
|
||||
savingTimeoutRef.current = window.setTimeout(() => setSaving(false), 500);
|
||||
}
|
||||
|
||||
function handleChangeViewMode(viewMode: ViewMode) {
|
||||
function handleChangeViewMode(viewMode: AssistViewMode) {
|
||||
if (viewMode === preferences.assist.viewMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleSidebar(viewMode === ViewMode.PopupExpandedSidebarVisible);
|
||||
toggleSidebar(viewMode === AssistViewMode.POPUP_EXPANDED_SIDEBAR_VISIBLE);
|
||||
saveSettings({ viewMode });
|
||||
}
|
||||
|
||||
|
||||
@@ -275,15 +275,3 @@ export interface ExecuteRemoteCommandPayload {
|
||||
labels?: { key: string; value: string }[];
|
||||
nodes?: string[];
|
||||
}
|
||||
|
||||
export enum ViewMode {
|
||||
Docked = 1,
|
||||
Popup = 2,
|
||||
PopupExpanded = 3,
|
||||
PopupExpandedSidebarVisible = 4,
|
||||
}
|
||||
|
||||
export interface AssistUserPreferences {
|
||||
preferredLogins: string[];
|
||||
viewMode: ViewMode;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import { MemoryRouter } from 'react-router';
|
||||
|
||||
import { render, screen } from 'design/utils/testing';
|
||||
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import TeleportContextProvider from 'teleport/TeleportContextProvider';
|
||||
import { Discover } from 'teleport/Discover/Discover';
|
||||
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
|
||||
@@ -40,8 +42,6 @@ import {
|
||||
DATABASES_UNGUIDED_DOC,
|
||||
} from 'teleport/Discover/SelectResource/databases';
|
||||
|
||||
import { ClusterResource } from 'teleport/services/userPreferences/types';
|
||||
|
||||
import { mockUserContextProviderWith } from 'teleport/User/testHelpers/mockUserContextWith';
|
||||
import { makeTestUserContext } from 'teleport/User/testHelpers/makeTestUserContext';
|
||||
|
||||
@@ -55,7 +55,7 @@ beforeEach(() => {
|
||||
|
||||
type createProps = {
|
||||
initialEntry?: string;
|
||||
preferredResource?: ClusterResource;
|
||||
preferredResource?: Resource;
|
||||
};
|
||||
|
||||
const create = ({ initialEntry = '', preferredResource }: createProps) => {
|
||||
@@ -113,7 +113,7 @@ test('displays all resources by default', () => {
|
||||
test('location state applies filter/search', () => {
|
||||
create({
|
||||
initialEntry: 'desktop',
|
||||
preferredResource: ClusterResource.RESOURCE_WEB_APPLICATIONS,
|
||||
preferredResource: Resource.WEB_APPLICATIONS,
|
||||
});
|
||||
|
||||
expect(screen.getAllByTestId(ResourceKind.Desktop)).toHaveLength(
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb';
|
||||
|
||||
import {
|
||||
createTeleportContext,
|
||||
getAcl,
|
||||
@@ -30,10 +34,6 @@ import { UserContext } from 'teleport/User/UserContext';
|
||||
|
||||
import { makeDefaultUserPreferences } from 'teleport/services/userPreferences/userPreferences';
|
||||
|
||||
import {
|
||||
ClusterResource,
|
||||
UserPreferences,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
import { Acl } from 'teleport/services/user';
|
||||
|
||||
import { SelectResource } from './SelectResource';
|
||||
@@ -86,7 +86,7 @@ export const InitRouteEntryServer = () => (
|
||||
type ProviderProps = {
|
||||
customAcl?: Acl;
|
||||
entity?: string;
|
||||
resources?: ClusterResource[];
|
||||
resources?: Resource[];
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
|
||||
import { Platform, UserAgent } from 'design/platform';
|
||||
|
||||
import {
|
||||
OnboardUserPreferences,
|
||||
Resource,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { makeDefaultUserPreferences } from 'teleport/services/userPreferences/userPreferences';
|
||||
|
||||
import {
|
||||
ClusterResource,
|
||||
OnboardUserPreferences,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
import { OnboardDiscover } from 'teleport/services/user';
|
||||
|
||||
import { ResourceKind } from '../Shared';
|
||||
@@ -228,12 +229,12 @@ describe('preferred resources', () => {
|
||||
|
||||
const testCases: {
|
||||
name: string;
|
||||
preferred: ClusterResource[];
|
||||
preferred: Resource[];
|
||||
expected: ResourceSpec[];
|
||||
}[] = [
|
||||
{
|
||||
name: 'preferred server/ssh',
|
||||
preferred: [ClusterResource.RESOURCE_SERVER_SSH],
|
||||
preferred: [Resource.SERVER_SSH],
|
||||
expected: [
|
||||
// preferred first
|
||||
f_Server,
|
||||
@@ -255,7 +256,7 @@ describe('preferred resources', () => {
|
||||
},
|
||||
{
|
||||
name: 'preferred databases',
|
||||
preferred: [ClusterResource.RESOURCE_DATABASES],
|
||||
preferred: [Resource.DATABASES],
|
||||
expected: [
|
||||
// preferred first
|
||||
a_Database,
|
||||
@@ -277,7 +278,7 @@ describe('preferred resources', () => {
|
||||
},
|
||||
{
|
||||
name: 'preferred windows',
|
||||
preferred: [ClusterResource.RESOURCE_WINDOWS_DESKTOPS],
|
||||
preferred: [Resource.WINDOWS_DESKTOPS],
|
||||
expected: [
|
||||
// preferred first
|
||||
i_Desktop,
|
||||
@@ -299,7 +300,7 @@ describe('preferred resources', () => {
|
||||
},
|
||||
{
|
||||
name: 'preferred applications',
|
||||
preferred: [ClusterResource.RESOURCE_WEB_APPLICATIONS],
|
||||
preferred: [Resource.WEB_APPLICATIONS],
|
||||
expected: [
|
||||
// preferred first
|
||||
c_Application,
|
||||
@@ -321,7 +322,7 @@ describe('preferred resources', () => {
|
||||
},
|
||||
{
|
||||
name: 'preferred kubernetes',
|
||||
preferred: [ClusterResource.RESOURCE_KUBERNETES],
|
||||
preferred: [Resource.KUBERNETES],
|
||||
expected: [
|
||||
// preferred first; guided before unguided
|
||||
j_Kubernetes,
|
||||
@@ -369,7 +370,7 @@ describe('marketing params', () => {
|
||||
{
|
||||
name: 'marketing params instead of preferred resources',
|
||||
preferred: {
|
||||
preferredResources: [ClusterResource.RESOURCE_WEB_APPLICATIONS],
|
||||
preferredResources: [Resource.WEB_APPLICATIONS],
|
||||
marketingParams: {
|
||||
campaign: 'kubernetes',
|
||||
source: '',
|
||||
|
||||
@@ -24,6 +24,10 @@ import styled from 'styled-components';
|
||||
import { Box, Flex, Link, Text } from 'design';
|
||||
import { getPlatform, Platform } from 'design/platform';
|
||||
|
||||
import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb';
|
||||
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import useTeleport from 'teleport/useTeleport';
|
||||
import { ToolTipNoPermBadge } from 'teleport/components/ToolTipNoPermBadge';
|
||||
import { Acl, AuthType, OnboardDiscover } from 'teleport/services/user';
|
||||
@@ -41,11 +45,6 @@ import AddApp from 'teleport/Apps/AddApp';
|
||||
import { useUser } from 'teleport/User/UserContext';
|
||||
import { storageService } from 'teleport/services/storageService';
|
||||
|
||||
import {
|
||||
ClusterResource,
|
||||
UserPreferences,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
|
||||
import { resourceKindToPreferredResource } from 'teleport/Discover/Shared/ResourceKind';
|
||||
|
||||
import { getMarketingTermMatches } from './getMarketingTermMatches';
|
||||
@@ -544,7 +543,7 @@ function getPrioritizedResources(
|
||||
const preferredResources = preferences.onboard.preferredResources || [];
|
||||
|
||||
// hasPreferredResources will be false if all resources are selected
|
||||
const maxResources = Object.keys(ClusterResource).length / 2 - 1;
|
||||
const maxResources = Object.keys(Resource).length / 2 - 1;
|
||||
const selectedAll = preferredResources.length === maxResources;
|
||||
|
||||
return {
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ClusterResource } from 'teleport/services/userPreferences/types';
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { SearchResource } from 'teleport/Discover/SelectResource/types';
|
||||
|
||||
export const resourceMapping: { [key in ClusterResource]: SearchResource } = {
|
||||
[ClusterResource.RESOURCE_UNSPECIFIED]: SearchResource.UNSPECIFIED,
|
||||
[ClusterResource.RESOURCE_DATABASES]: SearchResource.DATABASE,
|
||||
[ClusterResource.RESOURCE_KUBERNETES]: SearchResource.KUBERNETES,
|
||||
[ClusterResource.RESOURCE_SERVER_SSH]: SearchResource.SERVER,
|
||||
[ClusterResource.RESOURCE_WEB_APPLICATIONS]: SearchResource.APPLICATION,
|
||||
[ClusterResource.RESOURCE_WINDOWS_DESKTOPS]: SearchResource.DESKTOP,
|
||||
export const resourceMapping: { [key in Resource]: SearchResource } = {
|
||||
[Resource.UNSPECIFIED]: SearchResource.UNSPECIFIED,
|
||||
[Resource.DATABASES]: SearchResource.DATABASE,
|
||||
[Resource.KUBERNETES]: SearchResource.KUBERNETES,
|
||||
[Resource.SERVER_SSH]: SearchResource.SERVER,
|
||||
[Resource.WEB_APPLICATIONS]: SearchResource.APPLICATION,
|
||||
[Resource.WINDOWS_DESKTOPS]: SearchResource.DESKTOP,
|
||||
};
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
ClusterResource,
|
||||
MarketingParams,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { MarketingParams } from 'teleport/services/userPreferences/types';
|
||||
|
||||
import { getMarketingTermMatches } from './getMarketingTermMatches';
|
||||
|
||||
@@ -27,116 +26,107 @@ describe('getMarketingMatches', () => {
|
||||
const testCases: {
|
||||
name: string;
|
||||
param: MarketingParams;
|
||||
expected: ClusterResource[];
|
||||
expected: Resource[];
|
||||
}[] = [
|
||||
{
|
||||
name: 'database matches RESOURCE_DATABASES & k8s matches RESOURCE_KUBERNETES',
|
||||
name: 'database matches DATABASES & k8s matches KUBERNETES',
|
||||
param: {
|
||||
campaign: 'foodatabasebar',
|
||||
source: 'k8ski',
|
||||
medium: '',
|
||||
intent: '',
|
||||
},
|
||||
expected: [
|
||||
ClusterResource.RESOURCE_DATABASES,
|
||||
ClusterResource.RESOURCE_KUBERNETES,
|
||||
],
|
||||
expected: [Resource.DATABASES, Resource.KUBERNETES],
|
||||
},
|
||||
{
|
||||
name: 'app matches RESOURCE_WEB_APPLICATIONS',
|
||||
name: 'app matches WEB_APPLICATIONS',
|
||||
param: {
|
||||
campaign: '',
|
||||
source: 'baz',
|
||||
medium: '',
|
||||
intent: 'fooappbar',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_WEB_APPLICATIONS],
|
||||
expected: [Resource.WEB_APPLICATIONS],
|
||||
},
|
||||
{
|
||||
name: 'windows matches RESOURCE_WINDOWS_DESKTOPS',
|
||||
name: 'windows matches WINDOWS_DESKTOPS',
|
||||
param: {
|
||||
campaign: 'foowindowsbar',
|
||||
source: '',
|
||||
medium: '',
|
||||
intent: 'aws',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_WINDOWS_DESKTOPS],
|
||||
expected: [Resource.WINDOWS_DESKTOPS],
|
||||
},
|
||||
{
|
||||
name: 'desktop matches RESOURCE_WINDOWS_DESKTOPS',
|
||||
name: 'desktop matches WINDOWS_DESKTOPS',
|
||||
param: {
|
||||
campaign: '',
|
||||
source: '',
|
||||
medium: 'foodesktopbar',
|
||||
intent: 'shoo',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_WINDOWS_DESKTOPS],
|
||||
expected: [Resource.WINDOWS_DESKTOPS],
|
||||
},
|
||||
{
|
||||
name: 'ssh matches RESOURCE_SERVER_SSH',
|
||||
name: 'ssh matches SERVER_SSH',
|
||||
param: {
|
||||
campaign: '',
|
||||
source: 'foosshbar',
|
||||
medium: 'bar',
|
||||
intent: '',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_SERVER_SSH],
|
||||
expected: [Resource.SERVER_SSH],
|
||||
},
|
||||
{
|
||||
name: 'server matches RESOURCE_SERVER_SSH',
|
||||
name: 'server matches SERVER_SSH',
|
||||
param: {
|
||||
campaign: 'fooserverbar',
|
||||
source: '',
|
||||
medium: '',
|
||||
intent: 'ser',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_SERVER_SSH],
|
||||
expected: [Resource.SERVER_SSH],
|
||||
},
|
||||
{
|
||||
name: 'kube matches RESOURCE_KUBERNETES and windows matches RESOURCE_WINDOWS_DESKTOPS',
|
||||
name: 'kube matches KUBERNETES and windows matches WINDOWS_DESKTOPS',
|
||||
param: {
|
||||
campaign: 'fookubebar',
|
||||
source: '',
|
||||
medium: 'windows',
|
||||
intent: '',
|
||||
},
|
||||
expected: [
|
||||
ClusterResource.RESOURCE_KUBERNETES,
|
||||
ClusterResource.RESOURCE_WINDOWS_DESKTOPS,
|
||||
],
|
||||
expected: [Resource.KUBERNETES, Resource.WINDOWS_DESKTOPS],
|
||||
},
|
||||
{
|
||||
name: 'kubernetes matches RESOURCE_KUBERNETES',
|
||||
name: 'kubernetes matches KUBERNETES',
|
||||
param: {
|
||||
campaign: 'kubernetes',
|
||||
source: '',
|
||||
medium: '',
|
||||
intent: '',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_KUBERNETES],
|
||||
expected: [Resource.KUBERNETES],
|
||||
},
|
||||
{
|
||||
name: 'kube matches RESOURCE_KUBERNETES',
|
||||
name: 'kube matches KUBERNETES',
|
||||
param: {
|
||||
campaign: '',
|
||||
source: 'kube',
|
||||
medium: '',
|
||||
intent: '',
|
||||
},
|
||||
expected: [ClusterResource.RESOURCE_KUBERNETES],
|
||||
expected: [Resource.KUBERNETES],
|
||||
},
|
||||
{
|
||||
name: 'k8s matches RESOURCE_KUBERNETES and ssh matches RESOURCE_SERVER_SSH',
|
||||
name: 'k8s matches KUBERNETES and ssh matches SERVER_SSH',
|
||||
param: {
|
||||
campaign: '',
|
||||
source: '',
|
||||
medium: 'fook8sbar',
|
||||
intent: 'ssh',
|
||||
},
|
||||
expected: [
|
||||
ClusterResource.RESOURCE_KUBERNETES,
|
||||
ClusterResource.RESOURCE_SERVER_SSH,
|
||||
],
|
||||
expected: [Resource.KUBERNETES, Resource.SERVER_SSH],
|
||||
},
|
||||
{
|
||||
name: 'aws does not match',
|
||||
|
||||
@@ -16,21 +16,20 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
ClusterResource,
|
||||
MarketingParams,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { MarketingParams } from 'teleport/services/userPreferences/types';
|
||||
|
||||
/**
|
||||
* Returns a list of resource kinds that match provided marketing parameters.
|
||||
*
|
||||
* @param marketingParams - MarketingParams from cluster user preferences which are set at signup
|
||||
* @returns an array of ClusterResource associated with the marketing params for resource discoverability
|
||||
* @returns an array of Resource associated with the marketing params for resource discoverability
|
||||
*
|
||||
*/
|
||||
export const getMarketingTermMatches = (
|
||||
marketingParams: MarketingParams
|
||||
): ClusterResource[] => {
|
||||
): Resource[] => {
|
||||
const params = [];
|
||||
if (marketingParams) {
|
||||
marketingParams.campaign && params.push(marketingParams.campaign);
|
||||
@@ -42,7 +41,7 @@ export const getMarketingTermMatches = (
|
||||
return [];
|
||||
}
|
||||
|
||||
const matches = new Set<ClusterResource>();
|
||||
const matches = new Set<Resource>();
|
||||
params.forEach(p => {
|
||||
Object.values(TermMatch).forEach(m => {
|
||||
const clusterResource = matchTerm(m);
|
||||
@@ -68,22 +67,22 @@ export enum TermMatch {
|
||||
AWS = 'aws',
|
||||
}
|
||||
|
||||
const matchTerm = (m: string): ClusterResource => {
|
||||
const matchTerm = (m: string): Resource => {
|
||||
switch (m) {
|
||||
case TermMatch.App:
|
||||
return ClusterResource.RESOURCE_WEB_APPLICATIONS;
|
||||
return Resource.WEB_APPLICATIONS;
|
||||
case TermMatch.Database:
|
||||
return ClusterResource.RESOURCE_DATABASES;
|
||||
return Resource.DATABASES;
|
||||
case TermMatch.Kube:
|
||||
case TermMatch.Kubernetes:
|
||||
case TermMatch.K8s:
|
||||
return ClusterResource.RESOURCE_KUBERNETES;
|
||||
return Resource.KUBERNETES;
|
||||
case TermMatch.SSH:
|
||||
case TermMatch.Server:
|
||||
return ClusterResource.RESOURCE_SERVER_SSH;
|
||||
return Resource.SERVER_SSH;
|
||||
case TermMatch.Desktop:
|
||||
case TermMatch.Windows:
|
||||
return ClusterResource.RESOURCE_WINDOWS_DESKTOPS;
|
||||
return Resource.WINDOWS_DESKTOPS;
|
||||
// currently we have no resource kind nor cluster resource defined for AWS
|
||||
// in the future, we can search the resources based on this term.
|
||||
case TermMatch.AWS:
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
import { Platform } from 'design/platform';
|
||||
|
||||
import { ClusterResource } from 'teleport/services/userPreferences/types';
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { AuthType } from 'teleport/services/user';
|
||||
|
||||
import { ResourceKind } from '../Shared/ResourceKind';
|
||||
@@ -132,6 +133,6 @@ export enum SearchResource {
|
||||
}
|
||||
|
||||
export type PrioritizedResources = {
|
||||
preferredResources: ClusterResource[];
|
||||
preferredResources: Resource[];
|
||||
hasPreferredResources: boolean;
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ClusterResource } from 'teleport/services/userPreferences/types';
|
||||
import { Resource } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import type { JoinRole } from 'teleport/services/joinToken';
|
||||
|
||||
@@ -50,23 +50,21 @@ export function resourceKindToJoinRole(kind: ResourceKind): JoinRole {
|
||||
}
|
||||
}
|
||||
|
||||
export function resourceKindToPreferredResource(
|
||||
kind: ResourceKind
|
||||
): ClusterResource {
|
||||
export function resourceKindToPreferredResource(kind: ResourceKind): Resource {
|
||||
switch (kind) {
|
||||
case ResourceKind.Application:
|
||||
return ClusterResource.RESOURCE_WEB_APPLICATIONS;
|
||||
return Resource.WEB_APPLICATIONS;
|
||||
case ResourceKind.Database:
|
||||
return ClusterResource.RESOURCE_DATABASES;
|
||||
return Resource.DATABASES;
|
||||
case ResourceKind.Desktop:
|
||||
return ClusterResource.RESOURCE_WINDOWS_DESKTOPS;
|
||||
return Resource.WINDOWS_DESKTOPS;
|
||||
case ResourceKind.Kubernetes:
|
||||
return ClusterResource.RESOURCE_KUBERNETES;
|
||||
return Resource.KUBERNETES;
|
||||
case ResourceKind.Server:
|
||||
return ClusterResource.RESOURCE_SERVER_SSH;
|
||||
return Resource.SERVER_SSH;
|
||||
case ResourceKind.Discovery:
|
||||
return ClusterResource.RESOURCE_UNSPECIFIED;
|
||||
return Resource.UNSPECIFIED;
|
||||
case ResourceKind.ConnectMyComputer:
|
||||
return ClusterResource.RESOURCE_SERVER_SSH;
|
||||
return Resource.SERVER_SSH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ import { matchPath, useHistory } from 'react-router';
|
||||
import Dialog from 'design/Dialog';
|
||||
import { sharedStyles } from 'design/theme/themes/sharedStyles';
|
||||
|
||||
import { AssistViewMode } from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { Redirect, Route, Switch } from 'teleport/components/Router';
|
||||
import { CatchError } from 'teleport/components/CatchError';
|
||||
import cfg from 'teleport/config';
|
||||
@@ -54,7 +56,6 @@ import {
|
||||
import { NavigationCategory } from 'teleport/Navigation/categories';
|
||||
import { TopBarProps } from 'teleport/TopBar/TopBar';
|
||||
import { useUser } from 'teleport/User/UserContext';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
import { QuestionnaireProps } from 'teleport/Welcome/NewCredentials';
|
||||
|
||||
import { MainContainer } from './MainContainer';
|
||||
@@ -196,7 +197,7 @@ export function Main(props: MainProps) {
|
||||
<MainContainer>
|
||||
<Navigation />
|
||||
<HorizontalSplit
|
||||
dockedView={showAssist && viewMode === ViewMode.Docked}
|
||||
dockedView={showAssist && viewMode === AssistViewMode.DOCKED}
|
||||
hasSidebar={feature?.category === NavigationCategory.Management}
|
||||
>
|
||||
<ContentMinWidth>
|
||||
|
||||
@@ -27,9 +27,10 @@ import {
|
||||
useUnifiedResourcesFetch,
|
||||
UnifiedResourcesPinning,
|
||||
} from 'shared/components/UnifiedResources';
|
||||
import { DefaultTab } from 'shared/services/unifiedResourcePreferences';
|
||||
import { ClusterDropdown } from 'shared/components/ClusterDropdown/ClusterDropdown';
|
||||
|
||||
import { DefaultTab } from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import useStickyClusterId from 'teleport/useStickyClusterId';
|
||||
import { storageService } from 'teleport/services/storageService';
|
||||
import { useUser } from 'teleport/User/UserContext';
|
||||
@@ -123,8 +124,7 @@ function ClusterResources({
|
||||
dir: 'ASC',
|
||||
},
|
||||
pinnedOnly:
|
||||
preferences?.unifiedResourcePreferences?.defaultTab ===
|
||||
DefaultTab.DEFAULT_TAB_PINNED,
|
||||
preferences?.unifiedResourcePreferences?.defaultTab === DefaultTab.PINNED,
|
||||
});
|
||||
|
||||
const getCurrentClusterPinnedResources = useCallback(
|
||||
|
||||
@@ -26,11 +26,12 @@ import { render, screen, waitFor } from '@testing-library/react';
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import cfg from 'teleport/config';
|
||||
|
||||
import { UserContextProvider } from 'teleport/User';
|
||||
|
||||
import { ThemePreference } from 'teleport/services/userPreferences/types';
|
||||
import { useUser } from 'teleport/User/UserContext';
|
||||
import { KeysEnum } from 'teleport/services/storageService';
|
||||
|
||||
@@ -38,9 +39,7 @@ function ThemeName() {
|
||||
const { preferences } = useUser();
|
||||
|
||||
return (
|
||||
<div>
|
||||
theme: {preferences.theme === ThemePreference.Light ? 'light' : 'dark'}
|
||||
</div>
|
||||
<div>theme: {preferences.theme === Theme.LIGHT ? 'light' : 'dark'}</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,7 +48,7 @@ describe('user context - success state', () => {
|
||||
rest.get(cfg.api.userPreferencesPath, (req, res, ctx) => {
|
||||
return res(
|
||||
ctx.json({
|
||||
theme: ThemePreference.Light,
|
||||
theme: Theme.LIGHT,
|
||||
assist: {},
|
||||
})
|
||||
);
|
||||
@@ -76,7 +75,7 @@ describe('user context - success state', () => {
|
||||
});
|
||||
|
||||
it('should migrate the previous theme setting from local storage', async () => {
|
||||
let updateBody: { theme?: ThemePreference } = {};
|
||||
let updateBody: { theme?: Theme } = {};
|
||||
|
||||
server.use(
|
||||
rest.put(cfg.api.userPreferencesPath, async (req, res, ctx) => {
|
||||
@@ -96,7 +95,7 @@ describe('user context - success state', () => {
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
await waitFor(() => expect(updateBody.theme).toEqual(ThemePreference.Dark));
|
||||
await waitFor(() => expect(updateBody.theme).toEqual(Theme.DARK));
|
||||
|
||||
const theme = await screen.findByText(/theme: dark/i);
|
||||
|
||||
|
||||
@@ -30,6 +30,12 @@ import useAttempt from 'shared/hooks/useAttemptNext';
|
||||
|
||||
import { Indicator } from 'design';
|
||||
|
||||
import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb';
|
||||
|
||||
import { ClusterUserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/cluster_preferences_pb';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import { StyledIndicator } from 'teleport/Main';
|
||||
|
||||
import * as service from 'teleport/services/userPreferences';
|
||||
@@ -37,18 +43,10 @@ import cfg from 'teleport/config';
|
||||
|
||||
import { KeysEnum, storageService } from 'teleport/services/storageService';
|
||||
|
||||
import {
|
||||
deprecatedThemeToThemePreference,
|
||||
ThemePreference,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
import { deprecatedThemeToThemePreference } from 'teleport/services/userPreferences/types';
|
||||
|
||||
import { makeDefaultUserPreferences } from 'teleport/services/userPreferences/userPreferences';
|
||||
|
||||
import type {
|
||||
UserClusterPreferences,
|
||||
UserPreferences,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
|
||||
export interface UserContextValue {
|
||||
preferences: UserPreferences;
|
||||
updatePreferences: (preferences: Partial<UserPreferences>) => Promise<void>;
|
||||
@@ -69,7 +67,7 @@ export function UserContextProvider(props: PropsWithChildren<unknown>) {
|
||||
const { attempt, run } = useAttempt('processing');
|
||||
// because we have to update cluster preferences with itself during the update
|
||||
// we useRef here to prevent infinite rerenders
|
||||
const clusterPreferences = useRef<Record<string, UserClusterPreferences>>({});
|
||||
const clusterPreferences = useRef<Record<string, ClusterUserPreferences>>({});
|
||||
|
||||
const [preferences, setPreferences] = useState<UserPreferences>(
|
||||
makeDefaultUserPreferences()
|
||||
@@ -80,12 +78,12 @@ export function UserContextProvider(props: PropsWithChildren<unknown>) {
|
||||
// we know that pinned resources is supported because we've already successfully
|
||||
// fetched their pinned resources once before
|
||||
window.localStorage.removeItem(KeysEnum.PINNED_RESOURCES_NOT_SUPPORTED);
|
||||
return clusterPreferences.current[clusterId].pinnedResources;
|
||||
return clusterPreferences.current[clusterId].pinnedResources.resourceIds;
|
||||
}
|
||||
const prefs = await service.getUserClusterPreferences(clusterId);
|
||||
if (prefs) {
|
||||
clusterPreferences.current[clusterId] = prefs;
|
||||
return prefs.pinnedResources;
|
||||
return prefs.pinnedResources.resourceIds;
|
||||
}
|
||||
return null;
|
||||
}, []);
|
||||
@@ -95,9 +93,12 @@ export function UserContextProvider(props: PropsWithChildren<unknown>) {
|
||||
pinnedResources: string[]
|
||||
) => {
|
||||
if (!clusterPreferences.current[clusterId]) {
|
||||
clusterPreferences.current[clusterId] = { pinnedResources: [] };
|
||||
clusterPreferences.current[clusterId] = {
|
||||
pinnedResources: { resourceIds: [] },
|
||||
};
|
||||
}
|
||||
clusterPreferences.current[clusterId].pinnedResources = pinnedResources;
|
||||
clusterPreferences.current[clusterId].pinnedResources.resourceIds =
|
||||
pinnedResources;
|
||||
|
||||
return service.updateUserClusterPreferences(clusterId, {
|
||||
...preferences,
|
||||
@@ -121,7 +122,7 @@ export function UserContextProvider(props: PropsWithChildren<unknown>) {
|
||||
if (theme) {
|
||||
preferences.theme = deprecatedThemeToThemePreference(theme);
|
||||
|
||||
if (preferences.theme !== ThemePreference.Light) {
|
||||
if (preferences.theme !== Theme.LIGHT) {
|
||||
// the light theme is the default, so only update the backend if it is not light
|
||||
updatePreferences(preferences);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import {
|
||||
fireEvent,
|
||||
} from 'design/utils/testing';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import cfg from 'teleport/config';
|
||||
|
||||
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
|
||||
@@ -38,8 +40,6 @@ import TeleportContext from 'teleport/teleportContext';
|
||||
|
||||
import { makeUserContext } from 'teleport/services/user';
|
||||
|
||||
import { ThemePreference } from 'teleport/services/userPreferences/types';
|
||||
|
||||
import { mockUserContextProviderWith } from 'teleport/User/testHelpers/mockUserContextWith';
|
||||
import { makeTestUserContext } from 'teleport/User/testHelpers/makeTestUserContext';
|
||||
|
||||
@@ -49,7 +49,7 @@ const server = setupServer(
|
||||
rest.get(cfg.api.userPreferencesPath, (req, res, ctx) => {
|
||||
return res(
|
||||
ctx.json({
|
||||
theme: ThemePreference.Light,
|
||||
theme: Theme.LIGHT,
|
||||
assist: {},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -23,11 +23,12 @@ import { Moon, Sun, ChevronDown, Logout as LogoutIcon } from 'design/Icon';
|
||||
import { Text } from 'design';
|
||||
import { useRefClickOutside } from 'shared/hooks/useRefClickOutside';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import session from 'teleport/services/websession';
|
||||
import { useFeatures } from 'teleport/FeaturesContext';
|
||||
import { useTeleport } from 'teleport';
|
||||
import { useUser } from 'teleport/User/UserContext';
|
||||
import { ThemePreference } from 'teleport/services/userPreferences/types';
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
@@ -124,9 +125,7 @@ export function UserMenuNav({ username }: UserMenuNavProps) {
|
||||
|
||||
const onThemeChange = () => {
|
||||
const nextTheme =
|
||||
preferences.theme === ThemePreference.Light
|
||||
? ThemePreference.Dark
|
||||
: ThemePreference.Light;
|
||||
preferences.theme === Theme.LIGHT ? Theme.DARK : Theme.LIGHT;
|
||||
|
||||
updatePreferences({ theme: nextTheme });
|
||||
setOpen(false);
|
||||
@@ -180,14 +179,9 @@ export function UserMenuNav({ username }: UserMenuNavProps) {
|
||||
<DropdownItem open={open} $transitionDelay={transitionDelay}>
|
||||
<DropdownItemButton onClick={onThemeChange}>
|
||||
<DropdownItemIcon>
|
||||
{preferences.theme === ThemePreference.Dark ? (
|
||||
<Sun />
|
||||
) : (
|
||||
<Moon />
|
||||
)}
|
||||
{preferences.theme === Theme.DARK ? <Sun /> : <Moon />}
|
||||
</DropdownItemIcon>
|
||||
Switch to{' '}
|
||||
{preferences.theme === ThemePreference.Dark ? 'Light' : 'Dark'}{' '}
|
||||
Switch to {preferences.theme === Theme.DARK ? 'Light' : 'Dark'}{' '}
|
||||
Theme
|
||||
</DropdownItemButton>
|
||||
</DropdownItem>
|
||||
|
||||
@@ -18,14 +18,20 @@
|
||||
|
||||
import { DeprecatedThemeOption } from 'design/theme/types';
|
||||
|
||||
import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import { OnboardUserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import { BearerToken } from 'teleport/services/websession';
|
||||
import { OnboardDiscover } from 'teleport/services/user';
|
||||
|
||||
import {
|
||||
OnboardUserPreferences,
|
||||
ThemePreference,
|
||||
UserPreferences,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
BackendUserPreferences,
|
||||
convertBackendUserPreferences,
|
||||
isBackendUserPreferences,
|
||||
} from 'teleport/services/userPreferences/userPreferences';
|
||||
|
||||
import { CloudUserInvites, KeysEnum, LocalStorageSurvey } from './types';
|
||||
|
||||
@@ -107,7 +113,17 @@ export const storageService = {
|
||||
getUserPreferences(): UserPreferences {
|
||||
const preferences = window.localStorage.getItem(KeysEnum.USER_PREFERENCES);
|
||||
if (preferences) {
|
||||
return JSON.parse(preferences);
|
||||
const parsed: UserPreferences | BackendUserPreferences =
|
||||
JSON.parse(preferences);
|
||||
|
||||
// TODO(ryan): DELETE in v17: remove reference to `BackendUserPreferences` - all
|
||||
// locally stored copies of user preferences should be `UserPreferences` by then
|
||||
// (they are updated on every login)
|
||||
if (isBackendUserPreferences(parsed)) {
|
||||
return convertBackendUserPreferences(parsed);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -161,7 +177,7 @@ export const storageService = {
|
||||
window.localStorage.removeItem(KeysEnum.CLOUD_USER_INVITES);
|
||||
},
|
||||
|
||||
getThemePreference(): ThemePreference {
|
||||
getThemePreference(): Theme {
|
||||
const userPreferences = storageService.getUserPreferences();
|
||||
if (userPreferences) {
|
||||
return userPreferences.theme;
|
||||
@@ -169,10 +185,10 @@ export const storageService = {
|
||||
|
||||
const theme = this.getDeprecatedThemePreference();
|
||||
if (theme) {
|
||||
return theme === 'light' ? ThemePreference.Light : ThemePreference.Dark;
|
||||
return theme === 'light' ? Theme.LIGHT : Theme.DARK;
|
||||
}
|
||||
|
||||
return ThemePreference.Light;
|
||||
return Theme.LIGHT;
|
||||
},
|
||||
|
||||
getOnboardUserPreference(): OnboardUserPreferences {
|
||||
|
||||
@@ -18,23 +18,7 @@
|
||||
|
||||
import { DeprecatedThemeOption } from 'design/theme';
|
||||
|
||||
import type { UnifiedResourcePreferences } from 'shared/services/unifiedResourcePreferences';
|
||||
|
||||
import type { AssistUserPreferences } from 'teleport/Assist/types';
|
||||
|
||||
export enum ThemePreference {
|
||||
Light = 1,
|
||||
Dark = 2,
|
||||
}
|
||||
|
||||
export enum ClusterResource {
|
||||
RESOURCE_UNSPECIFIED = 0,
|
||||
RESOURCE_WINDOWS_DESKTOPS = 1,
|
||||
RESOURCE_SERVER_SSH = 2,
|
||||
RESOURCE_DATABASES = 3,
|
||||
RESOURCE_KUBERNETES = 4,
|
||||
RESOURCE_WEB_APPLICATIONS = 5,
|
||||
}
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
export type MarketingParams = {
|
||||
campaign: string;
|
||||
@@ -43,36 +27,13 @@ export type MarketingParams = {
|
||||
intent: string;
|
||||
};
|
||||
|
||||
export type OnboardUserPreferences = {
|
||||
preferredResources: ClusterResource[];
|
||||
marketingParams: MarketingParams;
|
||||
};
|
||||
|
||||
export interface UserPreferences {
|
||||
theme: ThemePreference;
|
||||
assist: AssistUserPreferences;
|
||||
onboard: OnboardUserPreferences;
|
||||
clusterPreferences: UserClusterPreferences;
|
||||
unifiedResourcePreferences: UnifiedResourcePreferences;
|
||||
}
|
||||
|
||||
// UserClusterPreferences are user preferences that are
|
||||
// different per cluster.
|
||||
export interface UserClusterPreferences {
|
||||
// pinnedResources is an array of resource IDs.
|
||||
pinnedResources: string[];
|
||||
}
|
||||
|
||||
export type GetUserClusterPreferencesResponse = UserClusterPreferences;
|
||||
export type GetUserPreferencesResponse = UserPreferences;
|
||||
|
||||
export function deprecatedThemeToThemePreference(
|
||||
theme: DeprecatedThemeOption
|
||||
): ThemePreference {
|
||||
): Theme {
|
||||
switch (theme) {
|
||||
case 'light':
|
||||
return ThemePreference.Light;
|
||||
return Theme.LIGHT;
|
||||
case 'dark':
|
||||
return ThemePreference.Dark;
|
||||
return Theme.DARK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb';
|
||||
|
||||
import {
|
||||
BackendUserPreferences,
|
||||
convertBackendUserPreferences,
|
||||
convertUserPreferences,
|
||||
isBackendUserPreferences,
|
||||
} from 'teleport/services/userPreferences/userPreferences';
|
||||
|
||||
test('should convert the old cluster user preferences format to the new one', () => {
|
||||
// this is how the backend currently returns cluster preferences - as an array of strings
|
||||
// instead of the protobuf representation of an object with a `resourceIds` field that contains
|
||||
// that array of strings
|
||||
const oldBackendPreferences: BackendUserPreferences = {
|
||||
theme: Theme.LIGHT,
|
||||
clusterPreferences: {
|
||||
pinnedResources: ['resource1', 'resource2'],
|
||||
},
|
||||
};
|
||||
|
||||
const actualUserPreferences: UserPreferences = {
|
||||
theme: Theme.LIGHT,
|
||||
clusterPreferences: {
|
||||
pinnedResources: { resourceIds: ['resource1', 'resource2'] },
|
||||
},
|
||||
};
|
||||
|
||||
// when we grab the user preferences from the local storage, we check if it is in the old format
|
||||
expect(isBackendUserPreferences(oldBackendPreferences)).toBe(true);
|
||||
expect(isBackendUserPreferences(actualUserPreferences)).toBe(false);
|
||||
|
||||
// and convert it to the new format if it is
|
||||
const newPreferences = convertBackendUserPreferences(oldBackendPreferences);
|
||||
|
||||
expect(newPreferences.clusterPreferences.pinnedResources.resourceIds).toEqual(
|
||||
oldBackendPreferences.clusterPreferences.pinnedResources
|
||||
);
|
||||
});
|
||||
|
||||
test('should convert the user preferences back to the old format when updating', () => {
|
||||
// the backend still expects the old format when updating user preferences
|
||||
|
||||
const actualUserPreferences: UserPreferences = {
|
||||
theme: Theme.LIGHT,
|
||||
clusterPreferences: {
|
||||
pinnedResources: { resourceIds: ['resource1', 'resource2'] },
|
||||
},
|
||||
};
|
||||
|
||||
const convertedPreferences = convertUserPreferences(actualUserPreferences);
|
||||
|
||||
expect(convertedPreferences.clusterPreferences.pinnedResources).toEqual(
|
||||
actualUserPreferences.clusterPreferences.pinnedResources.resourceIds
|
||||
);
|
||||
});
|
||||
@@ -16,40 +16,63 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as unifiedResourcePreferences from 'shared/services/unifiedResourcePreferences';
|
||||
import {
|
||||
DefaultTab,
|
||||
LabelsViewMode,
|
||||
UnifiedResourcePreferences,
|
||||
ViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import {
|
||||
AssistUserPreferences,
|
||||
AssistViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/assist_pb';
|
||||
|
||||
import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb';
|
||||
|
||||
import { ClusterUserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/cluster_preferences_pb';
|
||||
|
||||
import { Theme } from 'gen-proto-ts/teleport/userpreferences/v1/theme_pb';
|
||||
|
||||
import { OnboardUserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/onboard_pb';
|
||||
|
||||
import cfg from 'teleport/config';
|
||||
import api from 'teleport/services/api';
|
||||
import { ViewMode } from 'teleport/Assist/types';
|
||||
|
||||
import { KeysEnum } from '../storageService';
|
||||
|
||||
import { ThemePreference } from './types';
|
||||
interface BackendClusterUserPreferences {
|
||||
pinnedResources?: string[];
|
||||
}
|
||||
|
||||
import type {
|
||||
GetUserPreferencesResponse,
|
||||
UserClusterPreferences,
|
||||
UserPreferences,
|
||||
} from 'teleport/services/userPreferences/types';
|
||||
export interface BackendUserPreferences {
|
||||
assist?: AssistUserPreferences;
|
||||
theme: Theme;
|
||||
onboard?: OnboardUserPreferences;
|
||||
clusterPreferences?: BackendClusterUserPreferences;
|
||||
unifiedResourcePreferences?: UnifiedResourcePreferences;
|
||||
}
|
||||
|
||||
export async function getUserPreferences() {
|
||||
const res: GetUserPreferencesResponse = await api.get(
|
||||
export async function getUserPreferences(): Promise<UserPreferences> {
|
||||
const res: BackendUserPreferences = await api.get(
|
||||
cfg.api.userPreferencesPath
|
||||
);
|
||||
|
||||
return res;
|
||||
return convertBackendUserPreferences(res);
|
||||
}
|
||||
|
||||
export async function getUserClusterPreferences(clusterId: string) {
|
||||
export async function getUserClusterPreferences(
|
||||
clusterId: string
|
||||
): Promise<ClusterUserPreferences> {
|
||||
return await api
|
||||
.get(cfg.getUserClusterPreferencesUrl(clusterId))
|
||||
.then(res => {
|
||||
.then((res: BackendClusterUserPreferences) => {
|
||||
// TODO (avatus) DELETE IN 16
|
||||
// this item is used to disabled the pinned resources button if they
|
||||
// haven't upgraded to 14.1.0 yet. Anything lower than 14 doesn't matter
|
||||
// because the unified resource view isn't enabled so pinning isn't there either
|
||||
localStorage.removeItem(KeysEnum.PINNED_RESOURCES_NOT_SUPPORTED);
|
||||
return res;
|
||||
return convertBackendClusterUserPreferences(res);
|
||||
})
|
||||
.catch(res => {
|
||||
if (res.response?.status === 403 || res.response?.status === 404) {
|
||||
@@ -68,18 +91,24 @@ export function updateUserClusterPreferences(
|
||||
clusterId: string,
|
||||
preferences: UserPreferences
|
||||
) {
|
||||
return api.put(cfg.getUserClusterPreferencesUrl(clusterId), preferences);
|
||||
return api.put(
|
||||
cfg.getUserClusterPreferencesUrl(clusterId),
|
||||
convertUserPreferences(preferences)
|
||||
);
|
||||
}
|
||||
|
||||
export function updateUserPreferences(preferences: Partial<UserPreferences>) {
|
||||
return api.put(cfg.api.userPreferencesPath, preferences);
|
||||
return api.put(
|
||||
cfg.api.userPreferencesPath,
|
||||
convertUserPreferences(preferences as UserPreferences)
|
||||
);
|
||||
}
|
||||
|
||||
export function makeDefaultUserPreferences(): UserPreferences {
|
||||
return {
|
||||
theme: ThemePreference.Light,
|
||||
theme: Theme.LIGHT,
|
||||
assist: {
|
||||
viewMode: ViewMode.Docked,
|
||||
viewMode: AssistViewMode.DOCKED,
|
||||
preferredLogins: [],
|
||||
},
|
||||
onboard: {
|
||||
@@ -92,17 +121,61 @@ export function makeDefaultUserPreferences(): UserPreferences {
|
||||
},
|
||||
},
|
||||
unifiedResourcePreferences: {
|
||||
defaultTab: unifiedResourcePreferences.DefaultTab.DEFAULT_TAB_ALL,
|
||||
viewMode: unifiedResourcePreferences.ViewMode.VIEW_MODE_CARD,
|
||||
labelsViewMode:
|
||||
unifiedResourcePreferences.LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
defaultTab: DefaultTab.ALL,
|
||||
viewMode: ViewMode.CARD,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
},
|
||||
clusterPreferences: makeDefaultUserClusterPreferences(),
|
||||
};
|
||||
}
|
||||
|
||||
export function makeDefaultUserClusterPreferences(): UserClusterPreferences {
|
||||
export function makeDefaultUserClusterPreferences(): ClusterUserPreferences {
|
||||
return {
|
||||
pinnedResources: [],
|
||||
pinnedResources: {
|
||||
resourceIds: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function convertUserPreferences(
|
||||
preferences: UserPreferences
|
||||
): BackendUserPreferences {
|
||||
return {
|
||||
...preferences,
|
||||
clusterPreferences: {
|
||||
...preferences.clusterPreferences,
|
||||
pinnedResources:
|
||||
preferences.clusterPreferences?.pinnedResources?.resourceIds ?? [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function convertBackendUserPreferences(
|
||||
preferences: BackendUserPreferences
|
||||
): UserPreferences {
|
||||
return {
|
||||
...preferences,
|
||||
clusterPreferences: convertBackendClusterUserPreferences(
|
||||
preferences.clusterPreferences
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function convertBackendClusterUserPreferences(
|
||||
clusterPreferences: BackendClusterUserPreferences
|
||||
): ClusterUserPreferences {
|
||||
return {
|
||||
...clusterPreferences,
|
||||
pinnedResources: {
|
||||
resourceIds: clusterPreferences?.pinnedResources ?? [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function isBackendUserPreferences(
|
||||
preferences: UserPreferences | BackendUserPreferences
|
||||
): preferences is BackendUserPreferences {
|
||||
return Array.isArray(
|
||||
(preferences as BackendUserPreferences).clusterPreferences?.pinnedResources
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
const baseCfg = require('@gravitational/build/.babelrc');
|
||||
|
||||
baseCfg.presets = [
|
||||
['@babel/preset-env', { targets: { node: 'current' } }],
|
||||
['@babel/preset-react', { runtime: 'automatic' }],
|
||||
'@babel/preset-typescript',
|
||||
];
|
||||
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return baseCfg;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export function getConnectCsp(development: boolean) {
|
||||
// feedbackAddress needs to be kept in sync with the same property in staticConfig.ts.
|
||||
const feedbackAddress = development
|
||||
? 'https://kcwm2is93l.execute-api.us-west-2.amazonaws.com/prod'
|
||||
: 'https://usage.teleport.dev';
|
||||
|
||||
let csp = `
|
||||
default-src 'self';
|
||||
connect-src 'self' ${feedbackAddress};
|
||||
style-src 'self' 'unsafe-inline';
|
||||
img-src 'self' data: blob:;
|
||||
object-src 'none';
|
||||
font-src 'self' data:;
|
||||
`
|
||||
.replaceAll('\n', ' ')
|
||||
.trim();
|
||||
|
||||
if (development) {
|
||||
// Required to make source maps work in dev mode.
|
||||
csp += " script-src 'self' 'unsafe-eval' 'unsafe-inline';";
|
||||
}
|
||||
|
||||
return csp;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
files: [
|
||||
'build/app/dist',
|
||||
'build/app',
|
||||
// node-pty creates some files that differ across architecture builds causing
|
||||
// the error "can't reconcile the non-macho files" as they cant be combined
|
||||
// with lipo for a universal build. They aren't needed so skip them.
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import { defineConfig, externalizeDepsPlugin, UserConfig } from 'electron-vite';
|
||||
|
||||
import { cspPlugin } from '../build/vite/csp';
|
||||
|
||||
import { getStyledComponentsConfig } from '../build/vite/styled';
|
||||
|
||||
import { getConnectCsp } from './csp';
|
||||
|
||||
const rootDirectory = resolve(__dirname, '../../..');
|
||||
const outputDirectory = resolve(__dirname, 'build', 'app');
|
||||
|
||||
// these dependencies don't play well unless they're externalized
|
||||
// if Vite complains about a dependency, add it here
|
||||
const externalizeDeps = ['strip-ansi', 'ansi-regex', 'd3-color'];
|
||||
|
||||
const config = defineConfig(env => {
|
||||
const tsConfigPathsPlugin = tsconfigPaths({
|
||||
projects: [resolve(rootDirectory, 'tsconfig.json')],
|
||||
});
|
||||
|
||||
const commonPlugins = [
|
||||
externalizeDepsPlugin({ exclude: externalizeDeps }),
|
||||
tsConfigPathsPlugin,
|
||||
];
|
||||
|
||||
const config: UserConfig = {
|
||||
main: {
|
||||
build: {
|
||||
outDir: resolve(outputDirectory, 'main'),
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: resolve(__dirname, 'src/main.ts'),
|
||||
sharedProcess: resolve(
|
||||
__dirname,
|
||||
'src/sharedProcess/sharedProcess.ts'
|
||||
),
|
||||
agentCleanupDaemon: resolve(
|
||||
__dirname,
|
||||
'src/agentCleanupDaemon/agentCleanupDaemon.js'
|
||||
),
|
||||
},
|
||||
output: {
|
||||
manualChunks,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: commonPlugins,
|
||||
define: {
|
||||
// It's not common to pre-process Node code with NODE_ENV, but this is what our Webpack
|
||||
// config used to do, so for compatibility purposes we kept the Vite config this way.
|
||||
//
|
||||
// If we were to get rid of this, we'd somehow need to set NODE_ENV when the packaged app
|
||||
// gets started.
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||
},
|
||||
},
|
||||
preload: {
|
||||
build: {
|
||||
outDir: resolve(outputDirectory, 'preload'),
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: resolve(__dirname, 'src/preload.ts'),
|
||||
},
|
||||
output: {
|
||||
manualChunks,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: commonPlugins,
|
||||
define: {
|
||||
// Preload is also mean to be run by Node, see the comment for define under main.
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||
},
|
||||
},
|
||||
renderer: {
|
||||
root: '.',
|
||||
build: {
|
||||
outDir: resolve(outputDirectory, 'renderer'),
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: resolve(__dirname, 'index.html'),
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 8080,
|
||||
fs: {
|
||||
allow: [rootDirectory, '.'],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
react({
|
||||
plugins: [
|
||||
[
|
||||
'@swc/plugin-styled-components',
|
||||
getStyledComponentsConfig(env.mode),
|
||||
],
|
||||
],
|
||||
}),
|
||||
cspPlugin(getConnectCsp(env.mode === 'development')),
|
||||
tsConfigPathsPlugin,
|
||||
],
|
||||
define: {
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (env.mode === 'development') {
|
||||
if (process.env.VITE_HTTPS_KEY && process.env.VITE_HTTPS_CERT) {
|
||||
config.renderer.server.https = {
|
||||
key: readFileSync(process.env.VITE_HTTPS_KEY),
|
||||
cert: readFileSync(process.env.VITE_HTTPS_CERT),
|
||||
};
|
||||
} else {
|
||||
const certsDirectory = resolve(rootDirectory, 'web/certs');
|
||||
|
||||
if (!existsSync(certsDirectory)) {
|
||||
throw new Error(
|
||||
'Could not find SSL certificates. Please follow web/README.md to generate certificates.'
|
||||
);
|
||||
}
|
||||
|
||||
const keyPath = resolve(certsDirectory, 'server.key');
|
||||
const certPath = resolve(certsDirectory, 'server.crt');
|
||||
|
||||
config.renderer.server.https = {
|
||||
key: readFileSync(keyPath),
|
||||
cert: readFileSync(certPath),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
export { config as default };
|
||||
|
||||
function manualChunks(id: string) {
|
||||
for (const dep of externalizeDeps) {
|
||||
if (id.includes(dep)) {
|
||||
return dep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/ui/boot.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@gravitational/teleterm",
|
||||
"version": "1.0.0-dev",
|
||||
"description": "Teleport Connect",
|
||||
"main": "build/app/dist/main/main.js",
|
||||
"main": "build/app/main/index.js",
|
||||
"author": {
|
||||
"name": "Gravitational, Inc.",
|
||||
"email": "[email protected]",
|
||||
@@ -10,15 +10,13 @@
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"start": "yarn build-native-deps && webpack serve --config webpack.renderer.dev.config.js --progress",
|
||||
"start-main": "webpack build --config webpack.main.config.js --mode=development --progress --watch",
|
||||
"start": "yarn build-native-deps && yarn start-skip-native-deps",
|
||||
"start-skip-native-deps": "electron-vite dev",
|
||||
"start-electron": "electron build/app/dist/main/main.js",
|
||||
"build": "yarn build-main && yarn build-renderer",
|
||||
"build-main": "webpack build --config webpack.main.config.js --progress --mode=production",
|
||||
"build-renderer": "webpack build --config webpack.renderer.prod.config.js --progress",
|
||||
"build": "electron-vite build",
|
||||
"build-native-deps": "electron-builder install-app-deps",
|
||||
"package": "electron-builder build --config electron-builder-config.js --publish never -c.extraMetadata.name=teleport-connect",
|
||||
"generate-grpc-shared": "npx -y --target_arch=x64 --package=[email protected] [email protected] -- grpc_tools_node_protoc -I=src/sharedProcess/api/proto --ts_out=service=grpc-node,mode=grpc-js:src/sharedProcess/api/protogen --grpc_out=grpc_js:src/sharedProcess/api/protogen --js_out=import_style=commonjs,binary:src/sharedProcess/api/protogen src/sharedProcess/api/proto/*.proto"
|
||||
"generate-grpc-shared": "npx -y --target_arch=x64 --package=@protobuf-ts/[email protected] -- protoc -I=src/sharedProcess/api/proto --ts_opt long_type_number,eslint_disable,add_pb_suffix,client_grpc1,server_grpc1,ts_nocheck --ts_out=src/sharedProcess/api/protogen src/sharedProcess/api/proto/*.proto"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -28,35 +26,38 @@
|
||||
"private": true,
|
||||
"homepage": "https://goteleport.com",
|
||||
"dependencies": {
|
||||
"@types/tar-fs": "^2.0.1",
|
||||
"@grpc/grpc-js": "1.8.8",
|
||||
"node-forge": "^1.3.1",
|
||||
"node-pty": "1.1.0-beta5",
|
||||
"split2": "4.1.0",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"tar-fs": "^3.0.3"
|
||||
"tar-fs": "^3.0.3",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gravitational/build": "^1.0.0",
|
||||
"@gravitational/design": "1.0.0",
|
||||
"@gravitational/shared": "1.0.0",
|
||||
"@grpc/grpc-js": "1.8.8",
|
||||
"@protobuf-ts/runtime": "^2.9.3",
|
||||
"@protobuf-ts/runtime-rpc": "^2.9.3",
|
||||
"@types/google-protobuf": "^3.10.0",
|
||||
"@types/node-forge": "^1.0.4",
|
||||
"@types/tar-fs": "^2.0.1",
|
||||
"@types/whatwg-url": "^11.0.1",
|
||||
"clean-webpack-plugin": "4.0.0",
|
||||
"cross-env": "5.0.5",
|
||||
"electron": "28.1.1",
|
||||
"electron-notarize": "^1.2.1",
|
||||
"electron-vite": "^2.0.0",
|
||||
"eslint-import-resolver-webpack": "0.13.2",
|
||||
"eslint-loader": "3.0.3",
|
||||
"google-protobuf": "^3.20.1",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"immer": "^9.0.7",
|
||||
"jest-canvas-mock": "^2.3.1",
|
||||
"node-forge": "^1.3.1",
|
||||
"react-dnd": "^14.0.4",
|
||||
"react-dnd-html5-backend": "^14.0.2",
|
||||
"split2": "4.1.0",
|
||||
"ts-loader": "^9.4.2",
|
||||
"vite-plugin-commonjs": "^0.10.1",
|
||||
"whatwg-url": "^13.0.0",
|
||||
"winston": "^3.3.3",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0",
|
||||
"zod": "^3.22.3",
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ExcludesFalse is a method that can be used instead of [].filter(Boolean)
|
||||
// this removes the false values from the array type
|
||||
import { PaginatedResource } from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
import { Server } from 'gen-proto-ts/teleport/lib/teleterm/v1/server_pb';
|
||||
import { Database } from 'gen-proto-ts/teleport/lib/teleterm/v1/database_pb';
|
||||
import { App } from 'gen-proto-ts/teleport/lib/teleterm/v1/app_pb';
|
||||
import { Kube } from 'gen-proto-ts/teleport/lib/teleterm/v1/kube_pb';
|
||||
|
||||
import * as prehog from 'gen-proto-ts/prehog/v1alpha/connect_pb';
|
||||
|
||||
import {
|
||||
PtyClientEvent,
|
||||
PtyEventData,
|
||||
PtyEventExit,
|
||||
PtyEventResize,
|
||||
PtyEventStart,
|
||||
PtyEventStartError,
|
||||
PtyServerEvent,
|
||||
} from 'teleterm/sharedProcess/api/protogen/ptyHostService_pb';
|
||||
|
||||
export function resourceOneOfIsServer(
|
||||
resource: PaginatedResource['resource']
|
||||
): resource is {
|
||||
oneofKind: 'server';
|
||||
server: Server;
|
||||
} {
|
||||
return resource.oneofKind === 'server';
|
||||
}
|
||||
|
||||
export function resourceOneOfIsDatabase(
|
||||
resource: PaginatedResource['resource']
|
||||
): resource is {
|
||||
oneofKind: 'database';
|
||||
database: Database;
|
||||
} {
|
||||
return resource.oneofKind === 'database';
|
||||
}
|
||||
|
||||
export function resourceOneOfIsApp(
|
||||
resource: PaginatedResource['resource']
|
||||
): resource is {
|
||||
oneofKind: 'app';
|
||||
app: App;
|
||||
} {
|
||||
return resource.oneofKind === 'app';
|
||||
}
|
||||
|
||||
export function resourceOneOfIsKube(
|
||||
resource: PaginatedResource['resource']
|
||||
): resource is {
|
||||
oneofKind: 'kube';
|
||||
kube: Kube;
|
||||
} {
|
||||
return resource.oneofKind === 'kube';
|
||||
}
|
||||
|
||||
export function ptyEventOneOfIsStart(
|
||||
event: PtyClientEvent['event'] | PtyServerEvent['event']
|
||||
): event is {
|
||||
oneofKind: 'start';
|
||||
start: PtyEventStart;
|
||||
} {
|
||||
return event.oneofKind === 'start';
|
||||
}
|
||||
|
||||
export function ptyEventOneOfIsData(
|
||||
event: PtyClientEvent['event'] | PtyServerEvent['event']
|
||||
): event is {
|
||||
oneofKind: 'data';
|
||||
data: PtyEventData;
|
||||
} {
|
||||
return event.oneofKind === 'data';
|
||||
}
|
||||
|
||||
export function ptyEventOneOfIsResize(
|
||||
event: PtyClientEvent['event'] | PtyServerEvent['event']
|
||||
): event is {
|
||||
oneofKind: 'resize';
|
||||
resize: PtyEventResize;
|
||||
} {
|
||||
return event.oneofKind === 'resize';
|
||||
}
|
||||
|
||||
export function ptyEventOneOfIsExit(
|
||||
event: PtyClientEvent['event'] | PtyServerEvent['event']
|
||||
): event is {
|
||||
oneofKind: 'exit';
|
||||
exit: PtyEventExit;
|
||||
} {
|
||||
return event.oneofKind === 'exit';
|
||||
}
|
||||
export function ptyEventOneOfIsStartError(
|
||||
event: PtyClientEvent['event'] | PtyServerEvent['event']
|
||||
): event is {
|
||||
oneofKind: 'startError';
|
||||
startError: PtyEventStartError;
|
||||
} {
|
||||
return event.oneofKind === 'startError';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsClusterLogin(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'clusterLogin';
|
||||
clusterLogin: prehog.ConnectClusterLoginEvent;
|
||||
} {
|
||||
return event.oneofKind === 'clusterLogin';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsProtocolUse(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'protocolUse';
|
||||
protocolUse: prehog.ConnectProtocolUseEvent;
|
||||
} {
|
||||
return event.oneofKind === 'protocolUse';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsAccessRequestCreate(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'accessRequestCreate';
|
||||
accessRequestCreate: prehog.ConnectAccessRequestCreateEvent;
|
||||
} {
|
||||
return event.oneofKind === 'accessRequestCreate';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsAccessRequestReview(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'accessRequestReview';
|
||||
accessRequestReview: prehog.ConnectAccessRequestReviewEvent;
|
||||
} {
|
||||
return event.oneofKind === 'accessRequestReview';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsAccessRequestAssumeRole(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'accessRequestAssumeRole';
|
||||
accessRequestAssumeRole: prehog.ConnectAccessRequestAssumeRoleEvent;
|
||||
} {
|
||||
return event.oneofKind === 'accessRequestAssumeRole';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsFileTransferRun(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'fileTransferRun';
|
||||
fileTransferRun: prehog.ConnectFileTransferRunEvent;
|
||||
} {
|
||||
return event.oneofKind === 'fileTransferRun';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsUserJobRoleUpdate(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'userJobRoleUpdate';
|
||||
userJobRoleUpdate: prehog.ConnectUserJobRoleUpdateEvent;
|
||||
} {
|
||||
return event.oneofKind === 'userJobRoleUpdate';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsConnectMyComputerSetup(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'connectMyComputerSetup';
|
||||
connectMyComputerSetup: prehog.ConnectConnectMyComputerSetup;
|
||||
} {
|
||||
return event.oneofKind === 'connectMyComputerSetup';
|
||||
}
|
||||
|
||||
export function connectEventOneOfIsConnectMyComputerAgentStart(
|
||||
event: prehog.SubmitConnectEventRequest['event']
|
||||
): event is {
|
||||
oneofKind: 'connectMyComputerAgentStart';
|
||||
connectMyComputerAgentStart: prehog.ConnectConnectMyComputerAgentStart;
|
||||
} {
|
||||
return event.oneofKind === 'connectMyComputerAgentStart';
|
||||
}
|
||||
@@ -91,6 +91,7 @@ function initializeApp(): void {
|
||||
windowsManager,
|
||||
});
|
||||
|
||||
//TODO(gzdunek): Make sure this is not needed after migrating to Vite.
|
||||
app.on(
|
||||
'certificate-error',
|
||||
(event, webContents, url, error, certificate, callback) => {
|
||||
@@ -201,6 +202,10 @@ function initializeApp(): void {
|
||||
// https://github.com/electron/electron/blob/v17.2.0/docs/tutorial/security.md#12-verify-webview-options-before-creation
|
||||
app.on('web-contents-created', (_, contents) => {
|
||||
contents.on('will-navigate', (event, navigationUrl) => {
|
||||
// Allow reloading the renderer app in dev mode.
|
||||
if (settings.dev && new URL(navigationUrl).host === 'localhost:8080') {
|
||||
return;
|
||||
}
|
||||
logger.warn(`Navigation to ${navigationUrl} blocked by 'will-navigate'`);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
@@ -36,13 +36,13 @@ const RESOURCES_PATH = app.isPackaged
|
||||
: path.join(__dirname, '../../../../');
|
||||
|
||||
const TSH_BIN_ENV_VAR = 'CONNECT_TSH_BIN_PATH';
|
||||
// __dirname of this file in dev mode is webapps/packages/teleterm/build/app/dist/main
|
||||
// We default to webapps/../teleport/build/tsh.
|
||||
// __dirname of this file in dev mode is teleport/web/packages/teleterm/build/app/main
|
||||
// We default to teleport/build/tsh.
|
||||
// prettier-ignore
|
||||
const TSH_BIN_DEFAULT_PATH_FOR_DEV = path.resolve(
|
||||
__dirname,
|
||||
'..', '..', '..', '..', '..', '..', '..', '..',
|
||||
'teleport', 'build', 'tsh',
|
||||
'..', '..', '..', '..', '..', '..',
|
||||
'build', 'tsh',
|
||||
);
|
||||
|
||||
// Refer to the docs of RuntimeSettings type for an explanation behind dev, debug and insecure.
|
||||
|
||||
@@ -121,7 +121,7 @@ export class WindowsManager {
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: false,
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
preload: path.join(__dirname, '../preload/index.js'),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@ import {
|
||||
PtyEventStart,
|
||||
PtyServerEvent,
|
||||
} from 'teleterm/sharedProcess/ptyHost';
|
||||
import {
|
||||
ptyEventOneOfIsData,
|
||||
ptyEventOneOfIsExit,
|
||||
ptyEventOneOfIsStartError,
|
||||
} from 'teleterm/helpers';
|
||||
|
||||
export class PtyEventsStreamHandler {
|
||||
private logger: Logger;
|
||||
@@ -46,23 +51,34 @@ export class PtyEventsStreamHandler {
|
||||
this.logger.info('Start');
|
||||
|
||||
this.writeOrThrow(
|
||||
new PtyClientEvent().setStart(
|
||||
new PtyEventStart().setColumns(columns).setRows(rows)
|
||||
)
|
||||
PtyClientEvent.create({
|
||||
event: {
|
||||
oneofKind: 'start',
|
||||
start: PtyEventStart.create({ columns, rows }),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
write(data: string): void {
|
||||
this.writeOrThrow(
|
||||
new PtyClientEvent().setData(new PtyEventData().setMessage(data))
|
||||
PtyClientEvent.create({
|
||||
event: {
|
||||
oneofKind: 'data',
|
||||
data: PtyEventData.create({ message: data }),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
resize(columns: number, rows: number): void {
|
||||
this.writeOrThrow(
|
||||
new PtyClientEvent().setResize(
|
||||
new PtyEventResize().setColumns(columns).setRows(rows)
|
||||
)
|
||||
PtyClientEvent.create({
|
||||
event: {
|
||||
oneofKind: 'resize',
|
||||
resize: PtyEventResize.create({ columns, rows }),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -80,7 +96,7 @@ export class PtyEventsStreamHandler {
|
||||
onOpen(callback: () => void): RemoveListenerFunction {
|
||||
return this.addDataListenerAndReturnRemovalFunction(
|
||||
(event: PtyServerEvent) => {
|
||||
if (event.hasOpen()) {
|
||||
if (event.event.oneofKind === 'open') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
@@ -90,8 +106,8 @@ export class PtyEventsStreamHandler {
|
||||
onData(callback: (data: string) => void): RemoveListenerFunction {
|
||||
return this.addDataListenerAndReturnRemovalFunction(
|
||||
(event: PtyServerEvent) => {
|
||||
if (event.hasData()) {
|
||||
callback(event.getData().getMessage());
|
||||
if (ptyEventOneOfIsData(event.event)) {
|
||||
callback(event.event.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -102,9 +118,9 @@ export class PtyEventsStreamHandler {
|
||||
): RemoveListenerFunction {
|
||||
return this.addDataListenerAndReturnRemovalFunction(
|
||||
(event: PtyServerEvent) => {
|
||||
if (event.hasExit()) {
|
||||
this.logger.info('On exit', event.getExit().toObject());
|
||||
callback(event.getExit().toObject());
|
||||
if (ptyEventOneOfIsExit(event.event)) {
|
||||
this.logger.info('On exit', event.event.exit);
|
||||
callback(event.event.exit);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -113,12 +129,9 @@ export class PtyEventsStreamHandler {
|
||||
onStartError(callback: (message: string) => void): RemoveListenerFunction {
|
||||
return this.addDataListenerAndReturnRemovalFunction(
|
||||
(event: PtyServerEvent) => {
|
||||
if (event.hasStartError()) {
|
||||
this.logger.info(
|
||||
'On start error',
|
||||
event.getStartError().toObject().message
|
||||
);
|
||||
callback(event.getStartError().toObject().message);
|
||||
if (ptyEventOneOfIsStartError(event.event)) {
|
||||
this.logger.info('On start error', event.event.startError.message);
|
||||
callback(event.event.startError.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
|
||||
import { ChannelCredentials, Metadata } from '@grpc/grpc-js';
|
||||
import { Struct } from 'google-protobuf/google/protobuf/struct_pb';
|
||||
|
||||
import {
|
||||
PtyHostClient as GrpcClient,
|
||||
@@ -25,6 +24,8 @@ import {
|
||||
PtyId,
|
||||
} from 'teleterm/sharedProcess/ptyHost';
|
||||
|
||||
import { Struct } from 'teleterm/sharedProcess/api/protogen/google/protobuf/struct_pb';
|
||||
|
||||
import { PtyHostClient } from '../types';
|
||||
|
||||
import { PtyEventsStreamHandler } from './ptyEventsStreamHandler';
|
||||
@@ -36,16 +37,17 @@ export function createPtyHostClient(
|
||||
const client = new GrpcClient(address, credentials);
|
||||
return {
|
||||
createPtyProcess(ptyOptions) {
|
||||
const request = new PtyCreate()
|
||||
.setArgsList(ptyOptions.args)
|
||||
.setPath(ptyOptions.path)
|
||||
.setEnv(Struct.fromJavaScript(ptyOptions.env));
|
||||
const request = PtyCreate.create({
|
||||
args: ptyOptions.args,
|
||||
path: ptyOptions.path,
|
||||
env: Struct.fromJson(ptyOptions.env),
|
||||
});
|
||||
|
||||
if (ptyOptions.cwd) {
|
||||
request.setCwd(ptyOptions.cwd);
|
||||
request.cwd = ptyOptions.cwd;
|
||||
}
|
||||
if (ptyOptions.initMessage) {
|
||||
request.setInitMessage(ptyOptions.initMessage);
|
||||
request.initMessage = ptyOptions.initMessage;
|
||||
}
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
@@ -53,18 +55,18 @@ export function createPtyHostClient(
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response.toObject().id);
|
||||
resolve(response.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getCwd(ptyId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
client.getCwd(new PtyId().setId(ptyId), (error, response) => {
|
||||
client.getCwd(PtyId.create({ id: ptyId }), (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response.toObject().cwd);
|
||||
resolve(response.cwd);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,8 @@
|
||||
|
||||
import { ClientReadableStream } from '@grpc/grpc-js';
|
||||
import { FileTransferListeners } from 'shared/components/FileTransfer';
|
||||
import { FileTransferProgress } from 'gen-proto-js/teleport/lib/teleterm/v1/service_pb';
|
||||
import * as api from 'gen-proto-js/teleport/lib/teleterm/v1/service_pb';
|
||||
import { FileTransferProgress } from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
import * as api from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
|
||||
import { TshAbortSignal } from './types';
|
||||
|
||||
@@ -32,7 +32,7 @@ export function createFileTransferStream(
|
||||
return {
|
||||
onProgress(callback: (progress: number) => void) {
|
||||
stream.on('data', (data: api.FileTransferProgress) =>
|
||||
callback(data.getPercentage())
|
||||
callback(data.percentage)
|
||||
);
|
||||
},
|
||||
onComplete(callback: () => void) {
|
||||
|
||||
@@ -20,12 +20,12 @@ import { getCliCommandArgs, getCliCommandEnv } from './gateway';
|
||||
import { GatewayCLICommand } from './types';
|
||||
|
||||
describe('getCliCommandArgs', () => {
|
||||
it("extracts Node.js-style args from cliCommand's argsList", () => {
|
||||
it("extracts Node.js-style args from cliCommand's args", () => {
|
||||
const cliCommand = makeCliCommand();
|
||||
|
||||
const args = getCliCommandArgs(cliCommand);
|
||||
|
||||
expect(args).toEqual([cliCommand.argsList[1]]);
|
||||
expect(args).toEqual([cliCommand.args[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,8 +43,8 @@ describe('getCliCommandEnv', () => {
|
||||
const makeCliCommand = (): GatewayCLICommand => {
|
||||
return {
|
||||
path: '/Users/foo/Applications/psql.app/MacOS/psql',
|
||||
argsList: ['psql', 'localhost:1337'],
|
||||
envList: ['foo=bar', 'baz=quux'],
|
||||
args: ['psql', 'localhost:1337'],
|
||||
env: ['foo=bar', 'baz=quux'],
|
||||
preview: 'foo=bar baz=quux psql localhost:1337',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ import { GatewayCLICommand } from './types';
|
||||
* include just the args.
|
||||
*/
|
||||
export function getCliCommandArgs(cliCommand: GatewayCLICommand): string[] {
|
||||
const [, ...args] = cliCommand.argsList;
|
||||
const [, ...args] = cliCommand.args;
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export function getCliCommandArgs(cliCommand: GatewayCLICommand): string[] {
|
||||
* We are safe to use this as the presentational command name.
|
||||
*/
|
||||
export function getCliCommandArgv0(cliCommand: GatewayCLICommand): string {
|
||||
return cliCommand.argsList[0];
|
||||
return cliCommand.args[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ export function getCliCommandEnv(
|
||||
cliCommand: GatewayCLICommand
|
||||
): Record<string, string> {
|
||||
return Object.fromEntries(
|
||||
cliCommand.envList.map(nameEqualsValue => nameEqualsValue.split('='))
|
||||
cliCommand.env.map(nameEqualsValue => nameEqualsValue.split('='))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,19 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import * as api from 'gen-proto-js/teleport/lib/teleterm/v1/usage_events_pb';
|
||||
import * as prehogApi from 'gen-proto-js/prehog/v1alpha/connect_pb';
|
||||
import * as api from 'gen-proto-ts/teleport/lib/teleterm/v1/usage_events_pb';
|
||||
import * as prehogApi from 'gen-proto-ts/prehog/v1alpha/connect_pb';
|
||||
|
||||
import {
|
||||
connectEventOneOfIsAccessRequestAssumeRole,
|
||||
connectEventOneOfIsAccessRequestCreate,
|
||||
connectEventOneOfIsAccessRequestReview,
|
||||
connectEventOneOfIsClusterLogin,
|
||||
connectEventOneOfIsConnectMyComputerAgentStart,
|
||||
connectEventOneOfIsConnectMyComputerSetup,
|
||||
connectEventOneOfIsFileTransferRun,
|
||||
connectEventOneOfIsProtocolUse,
|
||||
} from 'teleterm/helpers';
|
||||
|
||||
import * as types from './types';
|
||||
|
||||
@@ -26,103 +36,162 @@ import * as types from './types';
|
||||
* Maps a plain JS object into a gRPC request object.
|
||||
*/
|
||||
export function mapUsageEvent(event: types.ReportUsageEventRequest) {
|
||||
return new api.ReportUsageEventRequest()
|
||||
.setAuthClusterId(event.authClusterId)
|
||||
.setPrehogReq(mapPrehogBody(event.prehogReq));
|
||||
return api.ReportUsageEventRequest.create({
|
||||
authClusterId: event.authClusterId,
|
||||
prehogReq: mapPrehogBody(event.prehogReq),
|
||||
});
|
||||
}
|
||||
|
||||
function mapPrehogBody(
|
||||
plainReq: types.ReportUsageEventRequest['prehogReq']
|
||||
): prehogApi.SubmitConnectEventRequest {
|
||||
const req = new prehogApi.SubmitConnectEventRequest()
|
||||
.setTimestamp(Timestamp.fromDate(plainReq.timestamp))
|
||||
.setDistinctId(plainReq.distinctId);
|
||||
if (!plainReq) {
|
||||
throw new Error(`Unrecognized event: ${JSON.stringify(plainReq)}`);
|
||||
}
|
||||
|
||||
const req = prehogApi.SubmitConnectEventRequest.create({
|
||||
timestamp: plainReq.timestamp,
|
||||
distinctId: plainReq.distinctId,
|
||||
});
|
||||
|
||||
// Non-anonymized events.
|
||||
if (plainReq.userJobRoleUpdate) {
|
||||
const event = plainReq.userJobRoleUpdate;
|
||||
const reqEvent = new prehogApi.ConnectUserJobRoleUpdateEvent().setJobRole(
|
||||
event.jobRole
|
||||
);
|
||||
if (plainReq.event.oneofKind === 'userJobRoleUpdate') {
|
||||
const event = plainReq.event.userJobRoleUpdate;
|
||||
const reqEvent = prehogApi.ConnectUserJobRoleUpdateEvent.create({
|
||||
jobRole: event.jobRole,
|
||||
});
|
||||
|
||||
return req.setUserJobRoleUpdate(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'userJobRoleUpdate',
|
||||
userJobRoleUpdate: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
// Anonymized events.
|
||||
if (plainReq.clusterLogin) {
|
||||
const event = plainReq.clusterLogin;
|
||||
const reqEvent = new prehogApi.ConnectClusterLoginEvent()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName)
|
||||
.setConnectorType(event.connectorType)
|
||||
.setOs(event.os)
|
||||
.setArch(event.arch)
|
||||
.setOsVersion(event.osVersion)
|
||||
.setAppVersion(event.appVersion);
|
||||
if (connectEventOneOfIsClusterLogin(plainReq.event)) {
|
||||
const event = plainReq.event.clusterLogin;
|
||||
const reqEvent = prehogApi.ConnectClusterLoginEvent.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
connectorType: event.connectorType,
|
||||
os: event.os,
|
||||
arch: event.arch,
|
||||
osVersion: event.osVersion,
|
||||
appVersion: event.appVersion,
|
||||
});
|
||||
|
||||
return req.setClusterLogin(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'clusterLogin',
|
||||
clusterLogin: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.protocolUse) {
|
||||
const event = plainReq.protocolUse;
|
||||
const reqEvent = new prehogApi.ConnectProtocolUseEvent()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName)
|
||||
.setProtocol(event.protocol)
|
||||
.setOrigin(event.origin);
|
||||
if (connectEventOneOfIsProtocolUse(plainReq.event)) {
|
||||
const event = plainReq.event.protocolUse;
|
||||
const reqEvent = prehogApi.ConnectProtocolUseEvent.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
protocol: event.protocol,
|
||||
origin: event.origin,
|
||||
});
|
||||
|
||||
return req.setProtocolUse(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'protocolUse',
|
||||
protocolUse: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.accessRequestCreate) {
|
||||
const event = plainReq.accessRequestCreate;
|
||||
const reqEvent = new prehogApi.ConnectAccessRequestCreateEvent()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName)
|
||||
.setKind(event.kind);
|
||||
if (connectEventOneOfIsAccessRequestCreate(plainReq.event)) {
|
||||
const event = plainReq.event.accessRequestCreate;
|
||||
const reqEvent = prehogApi.ConnectAccessRequestCreateEvent.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
kind: event.kind,
|
||||
});
|
||||
|
||||
return req.setAccessRequestCreate(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'accessRequestCreate',
|
||||
accessRequestCreate: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.accessRequestReview) {
|
||||
const event = plainReq.accessRequestReview;
|
||||
const reqEvent = new prehogApi.ConnectAccessRequestReviewEvent()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName);
|
||||
if (connectEventOneOfIsAccessRequestReview(plainReq.event)) {
|
||||
const event = plainReq.event.accessRequestReview;
|
||||
const reqEvent = prehogApi.ConnectAccessRequestReviewEvent.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
});
|
||||
|
||||
return req.setAccessRequestReview(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'accessRequestReview',
|
||||
accessRequestReview: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.accessRequestAssumeRole) {
|
||||
const event = plainReq.accessRequestAssumeRole;
|
||||
const reqEvent = new prehogApi.ConnectAccessRequestAssumeRoleEvent()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName);
|
||||
if (connectEventOneOfIsAccessRequestAssumeRole(plainReq.event)) {
|
||||
const event = plainReq.event.accessRequestAssumeRole;
|
||||
const reqEvent = prehogApi.ConnectAccessRequestAssumeRoleEvent.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
});
|
||||
|
||||
return req.setAccessRequestAssumeRole(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'accessRequestAssumeRole',
|
||||
accessRequestAssumeRole: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.fileTransferRun) {
|
||||
const event = plainReq.fileTransferRun;
|
||||
const reqEvent = new prehogApi.ConnectFileTransferRunEvent()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName)
|
||||
.setIsUpload(event.isUpload);
|
||||
if (connectEventOneOfIsFileTransferRun(plainReq.event)) {
|
||||
const event = plainReq.event.fileTransferRun;
|
||||
const reqEvent = prehogApi.ConnectFileTransferRunEvent.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
isUpload: event.isUpload,
|
||||
});
|
||||
|
||||
return req.setFileTransferRun(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'fileTransferRun',
|
||||
fileTransferRun: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.connectMyComputerSetup) {
|
||||
const event = plainReq.connectMyComputerSetup;
|
||||
const reqEvent = new prehogApi.ConnectConnectMyComputerSetup()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName)
|
||||
.setSuccess(event.success)
|
||||
.setFailedStep(event.failedStep);
|
||||
if (connectEventOneOfIsConnectMyComputerSetup(plainReq.event)) {
|
||||
const event = plainReq.event.connectMyComputerSetup;
|
||||
const reqEvent = prehogApi.ConnectConnectMyComputerSetup.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
success: event.success,
|
||||
failedStep: event.failedStep,
|
||||
});
|
||||
|
||||
return req.setConnectMyComputerSetup(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'connectMyComputerSetup',
|
||||
connectMyComputerSetup: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
if (plainReq.connectMyComputerAgentStart) {
|
||||
const event = plainReq.connectMyComputerAgentStart;
|
||||
const reqEvent = new prehogApi.ConnectConnectMyComputerAgentStart()
|
||||
.setClusterName(event.clusterName)
|
||||
.setUserName(event.userName);
|
||||
if (connectEventOneOfIsConnectMyComputerAgentStart(plainReq.event)) {
|
||||
const event = plainReq.event.connectMyComputerAgentStart;
|
||||
const reqEvent = prehogApi.ConnectConnectMyComputerAgentStart.create({
|
||||
clusterName: event.clusterName,
|
||||
userName: event.userName,
|
||||
});
|
||||
|
||||
return req.setConnectMyComputerAgentStart(reqEvent);
|
||||
req.event = {
|
||||
oneofKind: 'connectMyComputerAgentStart',
|
||||
connectMyComputerAgentStart: reqEvent,
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
throw new Error(`Unrecognized event: ${JSON.stringify(plainReq)}`);
|
||||
|
||||
@@ -26,7 +26,7 @@ export const makeServer = (props: Partial<tsh.Server> = {}): tsh.Server => ({
|
||||
name: '1234abcd-1234-abcd-1234-abcd1234abcd',
|
||||
hostname: 'foo',
|
||||
addr: '127.0.0.1:3022',
|
||||
labelsList: [],
|
||||
labels: [],
|
||||
subKind: 'teleport',
|
||||
...props,
|
||||
});
|
||||
@@ -44,20 +44,20 @@ export const makeDatabase = (
|
||||
desc: '',
|
||||
hostname: '',
|
||||
addr: '',
|
||||
labelsList: [],
|
||||
labels: [],
|
||||
...props,
|
||||
});
|
||||
|
||||
export const makeKube = (props: Partial<tsh.Kube> = {}): tsh.Kube => ({
|
||||
name: 'foo',
|
||||
labelsList: [],
|
||||
labels: [],
|
||||
uri: '/clusters/bar/kubes/foo',
|
||||
...props,
|
||||
});
|
||||
|
||||
export const makeApp = (props: Partial<tsh.App> = {}): App => ({
|
||||
name: 'foo',
|
||||
labelsList: [],
|
||||
labels: [],
|
||||
endpointUri: 'tcp://localhost:3000',
|
||||
friendlyName: '',
|
||||
desc: '',
|
||||
@@ -104,7 +104,7 @@ export const makeLeafCluster = (
|
||||
export const makeLoggedInUser = (
|
||||
props: Partial<tsh.LoggedInUser> = {}
|
||||
): tsh.LoggedInUser => ({
|
||||
activeRequestsList: [],
|
||||
activeRequests: [],
|
||||
assumedRequests: {},
|
||||
name: 'alice',
|
||||
acl: {
|
||||
@@ -113,7 +113,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
activeSessions: {
|
||||
@@ -121,7 +121,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
authConnectors: {
|
||||
@@ -129,7 +129,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
roles: {
|
||||
@@ -137,7 +137,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
users: {
|
||||
@@ -145,7 +145,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
trustedClusters: {
|
||||
@@ -153,7 +153,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
events: {
|
||||
@@ -161,7 +161,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
tokens: {
|
||||
@@ -169,7 +169,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
servers: {
|
||||
@@ -177,7 +177,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
apps: {
|
||||
@@ -185,7 +185,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
dbs: {
|
||||
@@ -193,7 +193,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
kubeservers: {
|
||||
@@ -201,7 +201,7 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
accessRequests: {
|
||||
@@ -209,15 +209,15 @@ export const makeLoggedInUser = (
|
||||
read: true,
|
||||
edit: true,
|
||||
create: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
},
|
||||
sshLoginsList: [],
|
||||
rolesList: [],
|
||||
requestableRolesList: [],
|
||||
suggestedReviewersList: [],
|
||||
userType: tsh.UserType.USER_TYPE_LOCAL,
|
||||
sshLogins: [],
|
||||
roles: [],
|
||||
requestableRoles: [],
|
||||
suggestedReviewers: [],
|
||||
userType: tsh.UserType.LOCAL,
|
||||
...props,
|
||||
});
|
||||
|
||||
@@ -233,8 +233,8 @@ export const makeDatabaseGateway = (
|
||||
protocol: 'postgres',
|
||||
gatewayCliCommand: {
|
||||
path: '/foo/psql',
|
||||
argsList: ['psql', 'localhost:1337'],
|
||||
envList: [],
|
||||
args: ['psql', 'localhost:1337'],
|
||||
env: [],
|
||||
preview: 'psql localhost:1337',
|
||||
},
|
||||
targetSubresourceName: 'bar',
|
||||
@@ -253,8 +253,8 @@ export const makeKubeGateway = (
|
||||
protocol: '',
|
||||
gatewayCliCommand: {
|
||||
path: '/bin/kubectl',
|
||||
argsList: ['version'],
|
||||
envList: ['KUBECONFIG=/path/to/kubeconfig'],
|
||||
args: ['version'],
|
||||
env: ['KUBECONFIG=/path/to/kubeconfig'],
|
||||
preview: 'KUBECONFIG=/path/to/kubeconfig /bin/kubectl version',
|
||||
},
|
||||
targetSubresourceName: '',
|
||||
@@ -273,8 +273,8 @@ export const makeAppGateway = (
|
||||
gatewayCliCommand: {
|
||||
path: '',
|
||||
preview: 'curl http://localhost:1337',
|
||||
envList: [],
|
||||
argsList: [],
|
||||
env: [],
|
||||
args: [],
|
||||
},
|
||||
targetUser: '',
|
||||
protocol: 'HTTP',
|
||||
|
||||
@@ -24,40 +24,38 @@ import { RequestState } from 'e-teleport/services/workflow';
|
||||
import { SortType } from 'design/DataTable/types';
|
||||
import { FileTransferListeners } from 'shared/components/FileTransfer';
|
||||
import { NodeSubKind } from 'shared/services';
|
||||
import apiCluster from 'gen-proto-js/teleport/lib/teleterm/v1/cluster_pb';
|
||||
import apiDb from 'gen-proto-js/teleport/lib/teleterm/v1/database_pb';
|
||||
import apiGateway from 'gen-proto-js/teleport/lib/teleterm/v1/gateway_pb';
|
||||
import apiServer from 'gen-proto-js/teleport/lib/teleterm/v1/server_pb';
|
||||
import apiKube from 'gen-proto-js/teleport/lib/teleterm/v1/kube_pb';
|
||||
import apiApp from 'gen-proto-js/teleport/lib/teleterm/v1/app_pb';
|
||||
import apiLabel from 'gen-proto-js/teleport/lib/teleterm/v1/label_pb';
|
||||
import apiService, {
|
||||
FileTransferDirection,
|
||||
HeadlessAuthenticationState,
|
||||
} from 'gen-proto-js/teleport/lib/teleterm/v1/service_pb';
|
||||
import apiAuthSettings from 'gen-proto-js/teleport/lib/teleterm/v1/auth_settings_pb';
|
||||
import apiAccessRequest from 'gen-proto-js/teleport/lib/teleterm/v1/access_request_pb';
|
||||
import apiUsageEvents from 'gen-proto-js/teleport/lib/teleterm/v1/usage_events_pb';
|
||||
import apiAccessList from 'gen-proto-js/teleport/accesslist/v1/accesslist_pb';
|
||||
import * as apiCluster from 'gen-proto-ts/teleport/lib/teleterm/v1/cluster_pb';
|
||||
import * as apiDb from 'gen-proto-ts/teleport/lib/teleterm/v1/database_pb';
|
||||
import * as apiGateway from 'gen-proto-ts/teleport/lib/teleterm/v1/gateway_pb';
|
||||
import * as apiServer from 'gen-proto-ts/teleport/lib/teleterm/v1/server_pb';
|
||||
import * as apiKube from 'gen-proto-ts/teleport/lib/teleterm/v1/kube_pb';
|
||||
import * as apiApp from 'gen-proto-ts/teleport/lib/teleterm/v1/app_pb';
|
||||
import * as apiLabel from 'gen-proto-ts/teleport/lib/teleterm/v1/label_pb';
|
||||
import * as apiService from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
import * as apiAuthSettings from 'gen-proto-ts/teleport/lib/teleterm/v1/auth_settings_pb';
|
||||
import * as apiAccessRequest from 'gen-proto-ts/teleport/lib/teleterm/v1/access_request_pb';
|
||||
import * as apiUsageEvents from 'gen-proto-ts/teleport/lib/teleterm/v1/usage_events_pb';
|
||||
import * as apiAccessList from 'gen-proto-ts/teleport/accesslist/v1/accesslist_pb';
|
||||
|
||||
import * as uri from 'teleterm/ui/uri';
|
||||
|
||||
// We want to reexport both the type and the value of UserType. Because it's in a namespace, we have
|
||||
// to alias it first to do the reexport.
|
||||
// https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases
|
||||
import UserType = apiCluster.LoggedInUser.UserType;
|
||||
import UserType = apiCluster.LoggedInUser_UserType;
|
||||
|
||||
export { UserType };
|
||||
|
||||
export interface Kube extends apiKube.Kube.AsObject {
|
||||
export interface Kube extends apiKube.Kube {
|
||||
uri: uri.KubeUri;
|
||||
}
|
||||
|
||||
export interface Server extends apiServer.Server.AsObject {
|
||||
export interface Server extends apiServer.Server {
|
||||
uri: uri.ServerUri;
|
||||
subKind: NodeSubKind;
|
||||
}
|
||||
|
||||
export interface App extends apiApp.App.AsObject {
|
||||
export interface App extends apiApp.App {
|
||||
uri: uri.AppUri;
|
||||
/** Name of the application. */
|
||||
name: string;
|
||||
@@ -86,7 +84,7 @@ export interface App extends apiApp.App.AsObject {
|
||||
samlApp: boolean;
|
||||
}
|
||||
|
||||
export interface Gateway extends apiGateway.Gateway.AsObject {
|
||||
export interface Gateway extends apiGateway.Gateway {
|
||||
uri: uri.GatewayUri;
|
||||
targetUri: uri.GatewayTargetUri;
|
||||
// The type of gatewayCliCommand was repeated here just to refer to the type with the JSDoc.
|
||||
@@ -107,43 +105,33 @@ export interface Gateway extends apiGateway.Gateway.AsObject {
|
||||
* if the user was to invoke it manually from the terminal. Should not be actually used to execute
|
||||
* anything in the shell.
|
||||
*/
|
||||
export type GatewayCLICommand = apiGateway.GatewayCLICommand.AsObject;
|
||||
export type GatewayCLICommand = apiGateway.GatewayCLICommand;
|
||||
|
||||
export type AccessRequest = apiAccessRequest.AccessRequest.AsObject;
|
||||
export type ResourceId = apiAccessRequest.ResourceID.AsObject;
|
||||
export type AccessRequestReview = apiAccessRequest.AccessRequestReview.AsObject;
|
||||
export type AccessList = apiAccessList.AccessList.AsObject;
|
||||
export type AccessRequest = apiAccessRequest.AccessRequest;
|
||||
export type ResourceId = apiAccessRequest.ResourceID;
|
||||
export type AccessRequestReview = apiAccessRequest.AccessRequestReview;
|
||||
export type AccessList = apiAccessList.AccessList;
|
||||
|
||||
export interface GetServersResponse
|
||||
extends apiService.GetServersResponse.AsObject {
|
||||
agentsList: Server[];
|
||||
export interface GetServersResponse extends apiService.GetServersResponse {
|
||||
agents: Server[];
|
||||
}
|
||||
|
||||
export interface GetDatabasesResponse
|
||||
extends apiService.GetDatabasesResponse.AsObject {
|
||||
agentsList: Database[];
|
||||
export interface GetDatabasesResponse extends apiService.GetDatabasesResponse {
|
||||
agents: Database[];
|
||||
}
|
||||
|
||||
export interface GetKubesResponse extends apiService.GetKubesResponse.AsObject {
|
||||
agentsList: Kube[];
|
||||
export interface GetKubesResponse extends apiService.GetKubesResponse {
|
||||
agents: Kube[];
|
||||
}
|
||||
|
||||
export interface GetAppsResponse extends apiService.GetAppsResponse.AsObject {
|
||||
agentsList: App[];
|
||||
export interface GetAppsResponse extends apiService.GetAppsResponse {
|
||||
agents: App[];
|
||||
}
|
||||
|
||||
export type GetRequestableRolesResponse =
|
||||
apiService.GetRequestableRolesResponse.AsObject;
|
||||
apiService.GetRequestableRolesResponse;
|
||||
|
||||
export type ReportUsageEventRequest = Modify<
|
||||
apiUsageEvents.ReportUsageEventRequest.AsObject,
|
||||
{
|
||||
prehogReq: Modify<
|
||||
apiUsageEvents.ReportUsageEventRequest.AsObject['prehogReq'],
|
||||
{ timestamp: Date }
|
||||
>;
|
||||
}
|
||||
>;
|
||||
export type ReportUsageEventRequest = apiUsageEvents.ReportUsageEventRequest;
|
||||
|
||||
// Available types are listed here:
|
||||
// https://github.com/gravitational/teleport/blob/v9.0.3/lib/defaults/defaults.go#L513-L530
|
||||
@@ -157,11 +145,11 @@ export type GatewayProtocol =
|
||||
| 'redis'
|
||||
| 'sqlserver';
|
||||
|
||||
export interface Database extends apiDb.Database.AsObject {
|
||||
export interface Database extends apiDb.Database {
|
||||
uri: uri.DatabaseUri;
|
||||
}
|
||||
|
||||
export interface Cluster extends apiCluster.Cluster.AsObject {
|
||||
export interface Cluster extends apiCluster.Cluster {
|
||||
/**
|
||||
* The URI of the cluster.
|
||||
*
|
||||
@@ -196,22 +184,21 @@ export interface Cluster extends apiCluster.Cluster.AsObject {
|
||||
* includes a situation in which the cert has expired. If the cluster was added to the app but the
|
||||
* user is yet to log in, loggedInUser is not present.
|
||||
*/
|
||||
export type LoggedInUser = apiCluster.LoggedInUser.AsObject & {
|
||||
export type LoggedInUser = apiCluster.LoggedInUser & {
|
||||
assumedRequests?: Record<string, AssumedRequest>;
|
||||
/**
|
||||
* acl is available only after the cluster details are fetched, as acl is not stored on disk.
|
||||
*/
|
||||
acl?: apiCluster.ACL.AsObject;
|
||||
acl?: apiCluster.ACL;
|
||||
};
|
||||
export type AuthProvider = apiAuthSettings.AuthProvider.AsObject;
|
||||
export type AuthSettings = apiAuthSettings.AuthSettings.AsObject;
|
||||
export type AuthProvider = apiAuthSettings.AuthProvider;
|
||||
export type AuthSettings = apiAuthSettings.AuthSettings;
|
||||
|
||||
export interface FileTransferRequest
|
||||
extends apiService.FileTransferRequest.AsObject {
|
||||
export interface FileTransferRequest extends apiService.FileTransferRequest {
|
||||
serverUri: uri.ServerUri;
|
||||
}
|
||||
|
||||
export type WebauthnCredentialInfo = apiService.CredentialInfo.AsObject;
|
||||
export type WebauthnCredentialInfo = apiService.CredentialInfo;
|
||||
export type WebauthnLoginPrompt =
|
||||
| WebauthnLoginTapPrompt
|
||||
| WebauthnLoginRetapPrompt
|
||||
@@ -229,7 +216,7 @@ export type WebauthnLoginCredentialPrompt = {
|
||||
onUserResponse(index: number): void;
|
||||
};
|
||||
export type LoginPasswordlessRequest =
|
||||
Partial<apiService.LoginPasswordlessRequest.AsObject>;
|
||||
Partial<apiService.LoginPasswordlessRequest>;
|
||||
|
||||
export type TshdClient = {
|
||||
listRootClusters: (abortSignal?: TshAbortSignal) => Promise<Cluster[]>;
|
||||
@@ -327,20 +314,20 @@ export type TshdClient = {
|
||||
) => Promise<void>;
|
||||
|
||||
listUnifiedResources: (
|
||||
params: apiService.ListUnifiedResourcesRequest.AsObject,
|
||||
params: apiService.ListUnifiedResourcesRequest,
|
||||
abortSignal?: TshAbortSignal
|
||||
) => Promise<ListUnifiedResourcesResponse>;
|
||||
|
||||
getUserPreferences: (
|
||||
params: apiService.GetUserPreferencesRequest.AsObject,
|
||||
params: apiService.GetUserPreferencesRequest,
|
||||
abortSignal?: TshAbortSignal
|
||||
) => Promise<UserPreferences>;
|
||||
updateUserPreferences: (
|
||||
params: apiService.UpdateUserPreferencesRequest.AsObject,
|
||||
params: apiService.UpdateUserPreferencesRequest,
|
||||
abortSignal?: TshAbortSignal
|
||||
) => Promise<UserPreferences>;
|
||||
getSuggestedAccessLists: (
|
||||
params: apiService.GetSuggestedAccessListsRequest.AsObject,
|
||||
params: apiService.GetSuggestedAccessListsRequest,
|
||||
abortSignal?: TshAbortSignal
|
||||
) => Promise<AccessList[]>;
|
||||
promoteAccessRequest: (
|
||||
@@ -433,21 +420,19 @@ export type AssumedRequest = {
|
||||
roles: string[];
|
||||
};
|
||||
|
||||
export { FileTransferDirection };
|
||||
|
||||
export type Label = apiLabel.Label.AsObject;
|
||||
export type Label = apiLabel.Label;
|
||||
|
||||
export type CreateConnectMyComputerRoleResponse =
|
||||
apiService.CreateConnectMyComputerRoleResponse.AsObject;
|
||||
apiService.CreateConnectMyComputerRoleResponse;
|
||||
export type CreateConnectMyComputerNodeTokenResponse =
|
||||
apiService.CreateConnectMyComputerNodeTokenResponse.AsObject;
|
||||
apiService.CreateConnectMyComputerNodeTokenResponse;
|
||||
export type WaitForConnectMyComputerNodeJoinResponse =
|
||||
apiService.WaitForConnectMyComputerNodeJoinResponse.AsObject & {
|
||||
apiService.WaitForConnectMyComputerNodeJoinResponse & {
|
||||
server: Server;
|
||||
};
|
||||
|
||||
export type ListUnifiedResourcesRequest =
|
||||
apiService.ListUnifiedResourcesRequest.AsObject;
|
||||
apiService.ListUnifiedResourcesRequest;
|
||||
export type ListUnifiedResourcesResponse = {
|
||||
resources: UnifiedResourceResponse[];
|
||||
nextKey: string;
|
||||
@@ -461,19 +446,14 @@ export type UnifiedResourceResponse =
|
||||
| { kind: 'kube'; resource: Kube }
|
||||
| { kind: 'app'; resource: App };
|
||||
|
||||
export type UserPreferences = apiService.UserPreferences.AsObject;
|
||||
export type UserPreferences = apiService.UserPreferences;
|
||||
export type PromoteAccessRequestParams =
|
||||
apiService.PromoteAccessRequestRequest.AsObject & {
|
||||
apiService.PromoteAccessRequestRequest & {
|
||||
rootClusterUri: uri.RootClusterUri;
|
||||
};
|
||||
|
||||
// Replaces object property with a new type
|
||||
type Modify<T, R> = Omit<T, keyof R> & R;
|
||||
|
||||
export type UpdateHeadlessAuthenticationStateParams = {
|
||||
rootClusterUri: uri.RootClusterUri;
|
||||
headlessAuthenticationId: string;
|
||||
state: apiService.HeadlessAuthenticationState;
|
||||
};
|
||||
|
||||
export { HeadlessAuthenticationState };
|
||||
|
||||
@@ -17,40 +17,42 @@
|
||||
*/
|
||||
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import * as api from 'gen-proto-js/teleport/lib/teleterm/v1/tshd_events_service_pb';
|
||||
import * as apiService from 'gen-proto-js/teleport/lib/teleterm/v1/tshd_events_service_grpc_pb';
|
||||
import * as protobuf from 'google-protobuf';
|
||||
import * as api from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb';
|
||||
import * as apiService from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb.grpc-server';
|
||||
|
||||
import * as uri from 'teleterm/ui/uri';
|
||||
import Logger from 'teleterm/logger';
|
||||
import { TshdEventContextBridgeService } from 'teleterm/types';
|
||||
import {
|
||||
ExtractRequestType,
|
||||
ExtractResponseType,
|
||||
TshdEventContextBridgeService,
|
||||
} from 'teleterm/types';
|
||||
import { filterSensitiveProperties } from 'teleterm/services/tshd/middleware';
|
||||
|
||||
export interface ReloginRequest extends api.ReloginRequest.AsObject {
|
||||
export interface ReloginRequest extends api.ReloginRequest {
|
||||
rootClusterUri: uri.RootClusterUri;
|
||||
gatewayCertExpired?: GatewayCertExpired;
|
||||
}
|
||||
export interface GatewayCertExpired extends api.GatewayCertExpired.AsObject {
|
||||
export interface GatewayCertExpired extends api.GatewayCertExpired {
|
||||
gatewayUri: uri.GatewayUri;
|
||||
targetUri: uri.DatabaseUri;
|
||||
}
|
||||
|
||||
export interface SendNotificationRequest
|
||||
extends api.SendNotificationRequest.AsObject {
|
||||
export interface SendNotificationRequest extends api.SendNotificationRequest {
|
||||
cannotProxyGatewayConnection?: CannotProxyGatewayConnection;
|
||||
}
|
||||
export interface CannotProxyGatewayConnection
|
||||
extends api.CannotProxyGatewayConnection.AsObject {
|
||||
extends api.CannotProxyGatewayConnection {
|
||||
gatewayUri: uri.GatewayUri;
|
||||
targetUri: uri.DatabaseUri;
|
||||
}
|
||||
|
||||
export type PromptMfaRequest = api.PromptMFARequest.AsObject & {
|
||||
export type PromptMfaRequest = api.PromptMFARequest & {
|
||||
rootClusterUri: uri.RootClusterUri;
|
||||
};
|
||||
|
||||
export interface SendPendingHeadlessAuthenticationRequest
|
||||
extends api.SendPendingHeadlessAuthenticationRequest.AsObject {
|
||||
extends api.SendPendingHeadlessAuthenticationRequest {
|
||||
rootClusterUri: uri.RootClusterUri;
|
||||
}
|
||||
|
||||
@@ -77,17 +79,7 @@ export async function createTshdEventsServer(
|
||||
);
|
||||
const { service, setupTshdEventContextBridgeService } = createService(logger);
|
||||
|
||||
server.addService(
|
||||
apiService.TshdEventsServiceService,
|
||||
// Whatever we use for generating protobufs generated wrong types. The types say that
|
||||
// server.addService expects an UntypedServiceImplementation as the second argument.
|
||||
// ITshdEventsServiceService does implement UntypedServiceImplementation.
|
||||
//
|
||||
// However, what we actually need to pass as the second argument needs to have the shape of
|
||||
// ITshdEventsServiceServer. That's why we ignore the error below.
|
||||
// @ts-expect-error The generated protobuf types seem to be wrong.
|
||||
service
|
||||
);
|
||||
server.addService(apiService.tshdEventsServiceDefinition, service);
|
||||
|
||||
return { resolvedAddress, setupTshdEventContextBridgeService };
|
||||
}
|
||||
@@ -134,7 +126,7 @@ async function createServer(
|
||||
* See the JSDoc for TshdEventContextBridgeService for more details.
|
||||
*/
|
||||
function createService(logger: Logger): {
|
||||
service: apiService.ITshdEventsServiceServer;
|
||||
service: apiService.ITshdEventsService;
|
||||
setupTshdEventContextBridgeService: (
|
||||
listener: TshdEventContextBridgeService
|
||||
) => void;
|
||||
@@ -155,18 +147,20 @@ function createService(logger: Logger): {
|
||||
* through the context bridge) to a class instance (as expected by grpc-js).
|
||||
*/
|
||||
function processEvent<
|
||||
RpcName extends keyof apiService.ITshdEventsServiceServer,
|
||||
Request extends protobuf.Message,
|
||||
Response extends protobuf.Message
|
||||
RpcName extends keyof apiService.ITshdEventsService,
|
||||
Request extends ExtractRequestType<
|
||||
Parameters<apiService.ITshdEventsService[RpcName]>[0]
|
||||
>,
|
||||
Response extends ExtractResponseType<
|
||||
Parameters<apiService.ITshdEventsService[RpcName]>[1]
|
||||
>
|
||||
>(
|
||||
rpcName: RpcName,
|
||||
call: grpc.ServerUnaryCall<Request, Response>,
|
||||
callback: (error: Error, response: Response) => void,
|
||||
mapResponseObjectToResponseInstance: (
|
||||
responseObject: ReturnType<Response['toObject']>
|
||||
) => Response
|
||||
callback: (error: Error | null, response: Response | null) => void,
|
||||
mapResponseObjectToResponseInstance: (responseObject: Response) => Response
|
||||
) {
|
||||
const request = call.request.toObject();
|
||||
const request = call.request;
|
||||
|
||||
logger.info(`got ${rpcName}`, filterSensitiveProperties(request));
|
||||
|
||||
@@ -190,12 +184,7 @@ function createService(logger: Logger): {
|
||||
throw new Error(`No context bridge handler for ${rpcName}`);
|
||||
}
|
||||
|
||||
contextBridgeHandler({
|
||||
// `as` is a workaround. We'd have to tell TypeScript somehow that `Request` is the same
|
||||
// between `contextBridgeService` and `processEvent`, but it's not clear how to achieve that.
|
||||
request: request as ReturnType<Request['toObject']>,
|
||||
onRequestCancelled,
|
||||
}).then(
|
||||
contextBridgeHandler({ request, onRequestCancelled }).then(
|
||||
response => {
|
||||
if (call.cancelled) {
|
||||
return;
|
||||
@@ -232,29 +221,25 @@ function createService(logger: Logger): {
|
||||
);
|
||||
}
|
||||
|
||||
const service: apiService.ITshdEventsServiceServer = {
|
||||
const service: apiService.ITshdEventsService = {
|
||||
relogin: (call, callback) =>
|
||||
processEvent('relogin', call, callback, () => new api.ReloginResponse()),
|
||||
processEvent('relogin', call, callback, () =>
|
||||
api.ReloginResponse.create()
|
||||
),
|
||||
|
||||
sendNotification: (call, callback) =>
|
||||
processEvent(
|
||||
'sendNotification',
|
||||
call,
|
||||
callback,
|
||||
() => new api.SendNotificationResponse()
|
||||
processEvent('sendNotification', call, callback, () =>
|
||||
api.SendNotificationResponse.create()
|
||||
),
|
||||
|
||||
sendPendingHeadlessAuthentication: (call, callback) =>
|
||||
processEvent(
|
||||
'sendPendingHeadlessAuthentication',
|
||||
call,
|
||||
callback,
|
||||
() => new api.SendPendingHeadlessAuthenticationResponse()
|
||||
processEvent('sendPendingHeadlessAuthentication', call, callback, () =>
|
||||
api.SendPendingHeadlessAuthenticationResponse.create()
|
||||
),
|
||||
|
||||
promptMFA: (call, callback) => {
|
||||
processEvent('promptMFA', call, callback, response =>
|
||||
new api.PromptMFAResponse().setTotpCode(response.totpCode)
|
||||
api.PromptMFAResponse.create({ totpCode: response?.totpCode })
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
+484
@@ -0,0 +1,484 @@
|
||||
/* eslint-disable */
|
||||
// @generated by protobuf-ts 2.9.3 with parameter long_type_number,eslint_disable,add_pb_suffix,client_grpc1,server_grpc1,ts_nocheck
|
||||
// @generated from protobuf file "google/protobuf/struct.proto" (package "google.protobuf", syntax proto3)
|
||||
// tslint:disable
|
||||
// @ts-nocheck
|
||||
//
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
|
||||
import type { IBinaryWriter } from "@protobuf-ts/runtime";
|
||||
import { WireType } from "@protobuf-ts/runtime";
|
||||
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
|
||||
import type { IBinaryReader } from "@protobuf-ts/runtime";
|
||||
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
||||
import type { PartialMessage } from "@protobuf-ts/runtime";
|
||||
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
||||
import { isJsonObject } from "@protobuf-ts/runtime";
|
||||
import { typeofJsonValue } from "@protobuf-ts/runtime";
|
||||
import type { JsonValue } from "@protobuf-ts/runtime";
|
||||
import type { JsonReadOptions } from "@protobuf-ts/runtime";
|
||||
import type { JsonWriteOptions } from "@protobuf-ts/runtime";
|
||||
import type { JsonObject } from "@protobuf-ts/runtime";
|
||||
import { MessageType } from "@protobuf-ts/runtime";
|
||||
/**
|
||||
* `Struct` represents a structured data value, consisting of fields
|
||||
* which map to dynamically typed values. In some languages, `Struct`
|
||||
* might be supported by a native representation. For example, in
|
||||
* scripting languages like JS a struct is represented as an
|
||||
* object. The details of that representation are described together
|
||||
* with the proto support for the language.
|
||||
*
|
||||
* The JSON representation for `Struct` is JSON object.
|
||||
*
|
||||
* @generated from protobuf message google.protobuf.Struct
|
||||
*/
|
||||
export interface Struct {
|
||||
/**
|
||||
* Unordered map of dynamically typed values.
|
||||
*
|
||||
* @generated from protobuf field: map<string, google.protobuf.Value> fields = 1;
|
||||
*/
|
||||
fields: {
|
||||
[key: string]: Value;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* `Value` represents a dynamically typed value which can be either
|
||||
* null, a number, a string, a boolean, a recursive struct value, or a
|
||||
* list of values. A producer of value is expected to set one of these
|
||||
* variants. Absence of any variant indicates an error.
|
||||
*
|
||||
* The JSON representation for `Value` is JSON value.
|
||||
*
|
||||
* @generated from protobuf message google.protobuf.Value
|
||||
*/
|
||||
export interface Value {
|
||||
/**
|
||||
* @generated from protobuf oneof: kind
|
||||
*/
|
||||
kind: {
|
||||
oneofKind: "nullValue";
|
||||
/**
|
||||
* Represents a null value.
|
||||
*
|
||||
* @generated from protobuf field: google.protobuf.NullValue null_value = 1;
|
||||
*/
|
||||
nullValue: NullValue;
|
||||
} | {
|
||||
oneofKind: "numberValue";
|
||||
/**
|
||||
* Represents a double value.
|
||||
*
|
||||
* @generated from protobuf field: double number_value = 2;
|
||||
*/
|
||||
numberValue: number;
|
||||
} | {
|
||||
oneofKind: "stringValue";
|
||||
/**
|
||||
* Represents a string value.
|
||||
*
|
||||
* @generated from protobuf field: string string_value = 3;
|
||||
*/
|
||||
stringValue: string;
|
||||
} | {
|
||||
oneofKind: "boolValue";
|
||||
/**
|
||||
* Represents a boolean value.
|
||||
*
|
||||
* @generated from protobuf field: bool bool_value = 4;
|
||||
*/
|
||||
boolValue: boolean;
|
||||
} | {
|
||||
oneofKind: "structValue";
|
||||
/**
|
||||
* Represents a structured value.
|
||||
*
|
||||
* @generated from protobuf field: google.protobuf.Struct struct_value = 5;
|
||||
*/
|
||||
structValue: Struct;
|
||||
} | {
|
||||
oneofKind: "listValue";
|
||||
/**
|
||||
* Represents a repeated `Value`.
|
||||
*
|
||||
* @generated from protobuf field: google.protobuf.ListValue list_value = 6;
|
||||
*/
|
||||
listValue: ListValue;
|
||||
} | {
|
||||
oneofKind: undefined;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* `ListValue` is a wrapper around a repeated field of values.
|
||||
*
|
||||
* The JSON representation for `ListValue` is JSON array.
|
||||
*
|
||||
* @generated from protobuf message google.protobuf.ListValue
|
||||
*/
|
||||
export interface ListValue {
|
||||
/**
|
||||
* Repeated field of dynamically typed values.
|
||||
*
|
||||
* @generated from protobuf field: repeated google.protobuf.Value values = 1;
|
||||
*/
|
||||
values: Value[];
|
||||
}
|
||||
/**
|
||||
* `NullValue` is a singleton enumeration to represent the null value for the
|
||||
* `Value` type union.
|
||||
*
|
||||
* The JSON representation for `NullValue` is JSON `null`.
|
||||
*
|
||||
* @generated from protobuf enum google.protobuf.NullValue
|
||||
*/
|
||||
export enum NullValue {
|
||||
/**
|
||||
* Null value.
|
||||
*
|
||||
* @generated from protobuf enum value: NULL_VALUE = 0;
|
||||
*/
|
||||
NULL_VALUE = 0
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class Struct$Type extends MessageType<Struct> {
|
||||
constructor() {
|
||||
super("google.protobuf.Struct", [
|
||||
{ no: 1, name: "fields", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "message", T: () => Value } }
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Encode `Struct` to JSON object.
|
||||
*/
|
||||
internalJsonWrite(message: Struct, options: JsonWriteOptions): JsonValue {
|
||||
let json: JsonObject = {};
|
||||
for (let [k, v] of Object.entries(message.fields)) {
|
||||
json[k] = Value.toJson(v);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
/**
|
||||
* Decode `Struct` from JSON object.
|
||||
*/
|
||||
internalJsonRead(json: JsonValue, options: JsonReadOptions, target?: Struct): Struct {
|
||||
if (!isJsonObject(json))
|
||||
throw new globalThis.Error("Unable to parse message " + this.typeName + " from JSON " + typeofJsonValue(json) + ".");
|
||||
if (!target)
|
||||
target = this.create();
|
||||
for (let [k, v] of globalThis.Object.entries(json)) {
|
||||
target.fields[k] = Value.fromJson(v);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
create(value?: PartialMessage<Struct>): Struct {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.fields = {};
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<Struct>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Struct): Struct {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* map<string, google.protobuf.Value> fields */ 1:
|
||||
this.binaryReadMap1(message.fields, reader, options);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
private binaryReadMap1(map: Struct["fields"], reader: IBinaryReader, options: BinaryReadOptions): void {
|
||||
let len = reader.uint32(), end = reader.pos + len, key: keyof Struct["fields"] | undefined, val: Struct["fields"][any] | undefined;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case 1:
|
||||
key = reader.string();
|
||||
break;
|
||||
case 2:
|
||||
val = Value.internalBinaryRead(reader, reader.uint32(), options);
|
||||
break;
|
||||
default: throw new globalThis.Error("unknown map entry field for field google.protobuf.Struct.fields");
|
||||
}
|
||||
}
|
||||
map[key ?? ""] = val ?? Value.create();
|
||||
}
|
||||
internalBinaryWrite(message: Struct, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* map<string, google.protobuf.Value> fields = 1; */
|
||||
for (let k of globalThis.Object.keys(message.fields)) {
|
||||
writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k);
|
||||
writer.tag(2, WireType.LengthDelimited).fork();
|
||||
Value.internalBinaryWrite(message.fields[k], writer, options);
|
||||
writer.join().join();
|
||||
}
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message google.protobuf.Struct
|
||||
*/
|
||||
export const Struct = new Struct$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class Value$Type extends MessageType<Value> {
|
||||
constructor() {
|
||||
super("google.protobuf.Value", [
|
||||
{ no: 1, name: "null_value", kind: "enum", oneof: "kind", T: () => ["google.protobuf.NullValue", NullValue] },
|
||||
{ no: 2, name: "number_value", kind: "scalar", oneof: "kind", T: 1 /*ScalarType.DOUBLE*/ },
|
||||
{ no: 3, name: "string_value", kind: "scalar", oneof: "kind", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "bool_value", kind: "scalar", oneof: "kind", T: 8 /*ScalarType.BOOL*/ },
|
||||
{ no: 5, name: "struct_value", kind: "message", oneof: "kind", T: () => Struct },
|
||||
{ no: 6, name: "list_value", kind: "message", oneof: "kind", T: () => ListValue }
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Encode `Value` to JSON value.
|
||||
*/
|
||||
internalJsonWrite(message: Value, options: JsonWriteOptions): JsonValue {
|
||||
if (message.kind.oneofKind === undefined)
|
||||
throw new globalThis.Error();
|
||||
switch (message.kind.oneofKind) {
|
||||
case undefined: throw new globalThis.Error();
|
||||
case "boolValue": return message.kind.boolValue;
|
||||
case "nullValue": return null;
|
||||
case "numberValue":
|
||||
let numberValue = message.kind.numberValue;
|
||||
if (typeof numberValue == "number" && !Number.isFinite(numberValue))
|
||||
throw new globalThis.Error();
|
||||
return numberValue;
|
||||
case "stringValue": return message.kind.stringValue;
|
||||
case "listValue":
|
||||
let listValueField = this.fields.find(f => f.no === 6);
|
||||
if (listValueField?.kind !== "message")
|
||||
throw new globalThis.Error();
|
||||
return listValueField.T().toJson(message.kind.listValue);
|
||||
case "structValue":
|
||||
let structValueField = this.fields.find(f => f.no === 5);
|
||||
if (structValueField?.kind !== "message")
|
||||
throw new globalThis.Error();
|
||||
return structValueField.T().toJson(message.kind.structValue);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Decode `Value` from JSON value.
|
||||
*/
|
||||
internalJsonRead(json: JsonValue, options: JsonReadOptions, target?: Value): Value {
|
||||
if (!target)
|
||||
target = this.create();
|
||||
switch (typeof json) {
|
||||
case "number":
|
||||
target.kind = { oneofKind: "numberValue", numberValue: json };
|
||||
break;
|
||||
case "string":
|
||||
target.kind = { oneofKind: "stringValue", stringValue: json };
|
||||
break;
|
||||
case "boolean":
|
||||
target.kind = { oneofKind: "boolValue", boolValue: json };
|
||||
break;
|
||||
case "object":
|
||||
if (json === null) {
|
||||
target.kind = { oneofKind: "nullValue", nullValue: NullValue.NULL_VALUE };
|
||||
}
|
||||
else if (globalThis.Array.isArray(json)) {
|
||||
target.kind = { oneofKind: "listValue", listValue: ListValue.fromJson(json) };
|
||||
}
|
||||
else {
|
||||
target.kind = { oneofKind: "structValue", structValue: Struct.fromJson(json) };
|
||||
}
|
||||
break;
|
||||
default: throw new globalThis.Error("Unable to parse " + this.typeName + " from JSON " + typeofJsonValue(json));
|
||||
}
|
||||
return target;
|
||||
}
|
||||
create(value?: PartialMessage<Value>): Value {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.kind = { oneofKind: undefined };
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<Value>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Value): Value {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* google.protobuf.NullValue null_value */ 1:
|
||||
message.kind = {
|
||||
oneofKind: "nullValue",
|
||||
nullValue: reader.int32()
|
||||
};
|
||||
break;
|
||||
case /* double number_value */ 2:
|
||||
message.kind = {
|
||||
oneofKind: "numberValue",
|
||||
numberValue: reader.double()
|
||||
};
|
||||
break;
|
||||
case /* string string_value */ 3:
|
||||
message.kind = {
|
||||
oneofKind: "stringValue",
|
||||
stringValue: reader.string()
|
||||
};
|
||||
break;
|
||||
case /* bool bool_value */ 4:
|
||||
message.kind = {
|
||||
oneofKind: "boolValue",
|
||||
boolValue: reader.bool()
|
||||
};
|
||||
break;
|
||||
case /* google.protobuf.Struct struct_value */ 5:
|
||||
message.kind = {
|
||||
oneofKind: "structValue",
|
||||
structValue: Struct.internalBinaryRead(reader, reader.uint32(), options, (message.kind as any).structValue)
|
||||
};
|
||||
break;
|
||||
case /* google.protobuf.ListValue list_value */ 6:
|
||||
message.kind = {
|
||||
oneofKind: "listValue",
|
||||
listValue: ListValue.internalBinaryRead(reader, reader.uint32(), options, (message.kind as any).listValue)
|
||||
};
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: Value, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* google.protobuf.NullValue null_value = 1; */
|
||||
if (message.kind.oneofKind === "nullValue")
|
||||
writer.tag(1, WireType.Varint).int32(message.kind.nullValue);
|
||||
/* double number_value = 2; */
|
||||
if (message.kind.oneofKind === "numberValue")
|
||||
writer.tag(2, WireType.Bit64).double(message.kind.numberValue);
|
||||
/* string string_value = 3; */
|
||||
if (message.kind.oneofKind === "stringValue")
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.kind.stringValue);
|
||||
/* bool bool_value = 4; */
|
||||
if (message.kind.oneofKind === "boolValue")
|
||||
writer.tag(4, WireType.Varint).bool(message.kind.boolValue);
|
||||
/* google.protobuf.Struct struct_value = 5; */
|
||||
if (message.kind.oneofKind === "structValue")
|
||||
Struct.internalBinaryWrite(message.kind.structValue, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
|
||||
/* google.protobuf.ListValue list_value = 6; */
|
||||
if (message.kind.oneofKind === "listValue")
|
||||
ListValue.internalBinaryWrite(message.kind.listValue, writer.tag(6, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message google.protobuf.Value
|
||||
*/
|
||||
export const Value = new Value$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ListValue$Type extends MessageType<ListValue> {
|
||||
constructor() {
|
||||
super("google.protobuf.ListValue", [
|
||||
{ no: 1, name: "values", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Value }
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Encode `ListValue` to JSON array.
|
||||
*/
|
||||
internalJsonWrite(message: ListValue, options: JsonWriteOptions): JsonValue {
|
||||
return message.values.map(v => Value.toJson(v));
|
||||
}
|
||||
/**
|
||||
* Decode `ListValue` from JSON array.
|
||||
*/
|
||||
internalJsonRead(json: JsonValue, options: JsonReadOptions, target?: ListValue): ListValue {
|
||||
if (!globalThis.Array.isArray(json))
|
||||
throw new globalThis.Error("Unable to parse " + this.typeName + " from JSON " + typeofJsonValue(json));
|
||||
if (!target)
|
||||
target = this.create();
|
||||
let values = json.map(v => Value.fromJson(v));
|
||||
target.values.push(...values);
|
||||
return target;
|
||||
}
|
||||
create(value?: PartialMessage<ListValue>): ListValue {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.values = [];
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<ListValue>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListValue): ListValue {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* repeated google.protobuf.Value values */ 1:
|
||||
message.values.push(Value.internalBinaryRead(reader, reader.uint32(), options));
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: ListValue, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* repeated google.protobuf.Value values = 1; */
|
||||
for (let i = 0; i < message.values.length; i++)
|
||||
Value.internalBinaryWrite(message.values[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message google.protobuf.ListValue
|
||||
*/
|
||||
export const ListValue = new ListValue$Type();
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// package:
|
||||
// file: ptyHostService.proto
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import * as grpc from "grpc";
|
||||
import * as ptyHostService_pb from "./ptyHostService_pb";
|
||||
import * as google_protobuf_struct_pb from "google-protobuf/google/protobuf/struct_pb";
|
||||
|
||||
interface IPtyHostService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {
|
||||
createPtyProcess: IPtyHostService_ICreatePtyProcess;
|
||||
exchangeEvents: IPtyHostService_IExchangeEvents;
|
||||
getCwd: IPtyHostService_IGetCwd;
|
||||
}
|
||||
|
||||
interface IPtyHostService_ICreatePtyProcess extends grpc.MethodDefinition<ptyHostService_pb.PtyCreate, ptyHostService_pb.PtyId> {
|
||||
path: "/PtyHost/CreatePtyProcess";
|
||||
requestStream: false;
|
||||
responseStream: false;
|
||||
requestSerialize: grpc.serialize<ptyHostService_pb.PtyCreate>;
|
||||
requestDeserialize: grpc.deserialize<ptyHostService_pb.PtyCreate>;
|
||||
responseSerialize: grpc.serialize<ptyHostService_pb.PtyId>;
|
||||
responseDeserialize: grpc.deserialize<ptyHostService_pb.PtyId>;
|
||||
}
|
||||
interface IPtyHostService_IExchangeEvents extends grpc.MethodDefinition<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent> {
|
||||
path: "/PtyHost/ExchangeEvents";
|
||||
requestStream: true;
|
||||
responseStream: true;
|
||||
requestSerialize: grpc.serialize<ptyHostService_pb.PtyClientEvent>;
|
||||
requestDeserialize: grpc.deserialize<ptyHostService_pb.PtyClientEvent>;
|
||||
responseSerialize: grpc.serialize<ptyHostService_pb.PtyServerEvent>;
|
||||
responseDeserialize: grpc.deserialize<ptyHostService_pb.PtyServerEvent>;
|
||||
}
|
||||
interface IPtyHostService_IGetCwd extends grpc.MethodDefinition<ptyHostService_pb.PtyId, ptyHostService_pb.PtyCwd> {
|
||||
path: "/PtyHost/GetCwd";
|
||||
requestStream: false;
|
||||
responseStream: false;
|
||||
requestSerialize: grpc.serialize<ptyHostService_pb.PtyId>;
|
||||
requestDeserialize: grpc.deserialize<ptyHostService_pb.PtyId>;
|
||||
responseSerialize: grpc.serialize<ptyHostService_pb.PtyCwd>;
|
||||
responseDeserialize: grpc.deserialize<ptyHostService_pb.PtyCwd>;
|
||||
}
|
||||
|
||||
export const PtyHostService: IPtyHostService;
|
||||
|
||||
export interface IPtyHostServer {
|
||||
createPtyProcess: grpc.handleUnaryCall<ptyHostService_pb.PtyCreate, ptyHostService_pb.PtyId>;
|
||||
exchangeEvents: grpc.handleBidiStreamingCall<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent>;
|
||||
getCwd: grpc.handleUnaryCall<ptyHostService_pb.PtyId, ptyHostService_pb.PtyCwd>;
|
||||
}
|
||||
|
||||
export interface IPtyHostClient {
|
||||
createPtyProcess(request: ptyHostService_pb.PtyCreate, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyId) => void): grpc.ClientUnaryCall;
|
||||
createPtyProcess(request: ptyHostService_pb.PtyCreate, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyId) => void): grpc.ClientUnaryCall;
|
||||
createPtyProcess(request: ptyHostService_pb.PtyCreate, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyId) => void): grpc.ClientUnaryCall;
|
||||
exchangeEvents(): grpc.ClientDuplexStream<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent>;
|
||||
exchangeEvents(options: Partial<grpc.CallOptions>): grpc.ClientDuplexStream<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent>;
|
||||
exchangeEvents(metadata: grpc.Metadata, options?: Partial<grpc.CallOptions>): grpc.ClientDuplexStream<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent>;
|
||||
getCwd(request: ptyHostService_pb.PtyId, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
getCwd(request: ptyHostService_pb.PtyId, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
getCwd(request: ptyHostService_pb.PtyId, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
}
|
||||
|
||||
export class PtyHostClient extends grpc.Client implements IPtyHostClient {
|
||||
constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);
|
||||
public createPtyProcess(request: ptyHostService_pb.PtyCreate, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyId) => void): grpc.ClientUnaryCall;
|
||||
public createPtyProcess(request: ptyHostService_pb.PtyCreate, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyId) => void): grpc.ClientUnaryCall;
|
||||
public createPtyProcess(request: ptyHostService_pb.PtyCreate, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyId) => void): grpc.ClientUnaryCall;
|
||||
public exchangeEvents(options?: Partial<grpc.CallOptions>): grpc.ClientDuplexStream<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent>;
|
||||
public exchangeEvents(metadata?: grpc.Metadata, options?: Partial<grpc.CallOptions>): grpc.ClientDuplexStream<ptyHostService_pb.PtyClientEvent, ptyHostService_pb.PtyServerEvent>;
|
||||
public getCwd(request: ptyHostService_pb.PtyId, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
public getCwd(request: ptyHostService_pb.PtyId, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
public getCwd(request: ptyHostService_pb.PtyId, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: ptyHostService_pb.PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
// GENERATED CODE -- DO NOT EDIT!
|
||||
|
||||
// Original file comments:
|
||||
/*
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// TODO(ravicious): Before introducing any changes, move this file to the /proto dir and
|
||||
// remove the generate-grpc-shared script.
|
||||
//
|
||||
'use strict';
|
||||
var grpc = require('@grpc/grpc-js');
|
||||
var ptyHostService_pb = require('./ptyHostService_pb.js');
|
||||
var google_protobuf_struct_pb = require('google-protobuf/google/protobuf/struct_pb.js');
|
||||
|
||||
function serialize_PtyClientEvent(arg) {
|
||||
if (!(arg instanceof ptyHostService_pb.PtyClientEvent)) {
|
||||
throw new Error('Expected argument of type PtyClientEvent');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_PtyClientEvent(buffer_arg) {
|
||||
return ptyHostService_pb.PtyClientEvent.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_PtyCreate(arg) {
|
||||
if (!(arg instanceof ptyHostService_pb.PtyCreate)) {
|
||||
throw new Error('Expected argument of type PtyCreate');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_PtyCreate(buffer_arg) {
|
||||
return ptyHostService_pb.PtyCreate.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_PtyCwd(arg) {
|
||||
if (!(arg instanceof ptyHostService_pb.PtyCwd)) {
|
||||
throw new Error('Expected argument of type PtyCwd');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_PtyCwd(buffer_arg) {
|
||||
return ptyHostService_pb.PtyCwd.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_PtyId(arg) {
|
||||
if (!(arg instanceof ptyHostService_pb.PtyId)) {
|
||||
throw new Error('Expected argument of type PtyId');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_PtyId(buffer_arg) {
|
||||
return ptyHostService_pb.PtyId.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
function serialize_PtyServerEvent(arg) {
|
||||
if (!(arg instanceof ptyHostService_pb.PtyServerEvent)) {
|
||||
throw new Error('Expected argument of type PtyServerEvent');
|
||||
}
|
||||
return Buffer.from(arg.serializeBinary());
|
||||
}
|
||||
|
||||
function deserialize_PtyServerEvent(buffer_arg) {
|
||||
return ptyHostService_pb.PtyServerEvent.deserializeBinary(new Uint8Array(buffer_arg));
|
||||
}
|
||||
|
||||
|
||||
var PtyHostService = exports.PtyHostService = {
|
||||
createPtyProcess: {
|
||||
path: '/PtyHost/CreatePtyProcess',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: ptyHostService_pb.PtyCreate,
|
||||
responseType: ptyHostService_pb.PtyId,
|
||||
requestSerialize: serialize_PtyCreate,
|
||||
requestDeserialize: deserialize_PtyCreate,
|
||||
responseSerialize: serialize_PtyId,
|
||||
responseDeserialize: deserialize_PtyId,
|
||||
},
|
||||
exchangeEvents: {
|
||||
path: '/PtyHost/ExchangeEvents',
|
||||
requestStream: true,
|
||||
responseStream: true,
|
||||
requestType: ptyHostService_pb.PtyClientEvent,
|
||||
responseType: ptyHostService_pb.PtyServerEvent,
|
||||
requestSerialize: serialize_PtyClientEvent,
|
||||
requestDeserialize: deserialize_PtyClientEvent,
|
||||
responseSerialize: serialize_PtyServerEvent,
|
||||
responseDeserialize: deserialize_PtyServerEvent,
|
||||
},
|
||||
getCwd: {
|
||||
path: '/PtyHost/GetCwd',
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestType: ptyHostService_pb.PtyId,
|
||||
responseType: ptyHostService_pb.PtyCwd,
|
||||
requestSerialize: serialize_PtyId,
|
||||
requestDeserialize: deserialize_PtyId,
|
||||
responseSerialize: serialize_PtyCwd,
|
||||
responseDeserialize: deserialize_PtyCwd,
|
||||
},
|
||||
};
|
||||
|
||||
exports.PtyHostClient = grpc.makeGenericClientConstructor(PtyHostService);
|
||||
-336
@@ -1,336 +0,0 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2023 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// package:
|
||||
// file: ptyHostService.proto
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import * as jspb from "google-protobuf";
|
||||
import * as google_protobuf_struct_pb from "google-protobuf/google/protobuf/struct_pb";
|
||||
|
||||
export class PtyId extends jspb.Message {
|
||||
getId(): string;
|
||||
setId(value: string): PtyId;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyId.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyId): PtyId.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyId, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyId;
|
||||
static deserializeBinaryFromReader(message: PtyId, reader: jspb.BinaryReader): PtyId;
|
||||
}
|
||||
|
||||
export namespace PtyId {
|
||||
export type AsObject = {
|
||||
id: string,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyCreate extends jspb.Message {
|
||||
getPath(): string;
|
||||
setPath(value: string): PtyCreate;
|
||||
clearArgsList(): void;
|
||||
getArgsList(): Array<string>;
|
||||
setArgsList(value: Array<string>): PtyCreate;
|
||||
addArgs(value: string, index?: number): string;
|
||||
getCwd(): string;
|
||||
setCwd(value: string): PtyCreate;
|
||||
|
||||
hasEnv(): boolean;
|
||||
clearEnv(): void;
|
||||
getEnv(): google_protobuf_struct_pb.Struct | undefined;
|
||||
setEnv(value?: google_protobuf_struct_pb.Struct): PtyCreate;
|
||||
getInitMessage(): string;
|
||||
setInitMessage(value: string): PtyCreate;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyCreate.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyCreate): PtyCreate.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyCreate, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyCreate;
|
||||
static deserializeBinaryFromReader(message: PtyCreate, reader: jspb.BinaryReader): PtyCreate;
|
||||
}
|
||||
|
||||
export namespace PtyCreate {
|
||||
export type AsObject = {
|
||||
path: string,
|
||||
argsList: Array<string>,
|
||||
cwd: string,
|
||||
env?: google_protobuf_struct_pb.Struct.AsObject,
|
||||
initMessage: string,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyClientEvent extends jspb.Message {
|
||||
|
||||
hasStart(): boolean;
|
||||
clearStart(): void;
|
||||
getStart(): PtyEventStart | undefined;
|
||||
setStart(value?: PtyEventStart): PtyClientEvent;
|
||||
|
||||
hasResize(): boolean;
|
||||
clearResize(): void;
|
||||
getResize(): PtyEventResize | undefined;
|
||||
setResize(value?: PtyEventResize): PtyClientEvent;
|
||||
|
||||
hasData(): boolean;
|
||||
clearData(): void;
|
||||
getData(): PtyEventData | undefined;
|
||||
setData(value?: PtyEventData): PtyClientEvent;
|
||||
|
||||
getEventCase(): PtyClientEvent.EventCase;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyClientEvent.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyClientEvent): PtyClientEvent.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyClientEvent, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyClientEvent;
|
||||
static deserializeBinaryFromReader(message: PtyClientEvent, reader: jspb.BinaryReader): PtyClientEvent;
|
||||
}
|
||||
|
||||
export namespace PtyClientEvent {
|
||||
export type AsObject = {
|
||||
start?: PtyEventStart.AsObject,
|
||||
resize?: PtyEventResize.AsObject,
|
||||
data?: PtyEventData.AsObject,
|
||||
}
|
||||
|
||||
export enum EventCase {
|
||||
EVENT_NOT_SET = 0,
|
||||
START = 2,
|
||||
RESIZE = 3,
|
||||
DATA = 4,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class PtyServerEvent extends jspb.Message {
|
||||
|
||||
hasResize(): boolean;
|
||||
clearResize(): void;
|
||||
getResize(): PtyEventResize | undefined;
|
||||
setResize(value?: PtyEventResize): PtyServerEvent;
|
||||
|
||||
hasData(): boolean;
|
||||
clearData(): void;
|
||||
getData(): PtyEventData | undefined;
|
||||
setData(value?: PtyEventData): PtyServerEvent;
|
||||
|
||||
hasOpen(): boolean;
|
||||
clearOpen(): void;
|
||||
getOpen(): PtyEventOpen | undefined;
|
||||
setOpen(value?: PtyEventOpen): PtyServerEvent;
|
||||
|
||||
hasExit(): boolean;
|
||||
clearExit(): void;
|
||||
getExit(): PtyEventExit | undefined;
|
||||
setExit(value?: PtyEventExit): PtyServerEvent;
|
||||
|
||||
hasStartError(): boolean;
|
||||
clearStartError(): void;
|
||||
getStartError(): PtyEventStartError | undefined;
|
||||
setStartError(value?: PtyEventStartError): PtyServerEvent;
|
||||
|
||||
getEventCase(): PtyServerEvent.EventCase;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyServerEvent.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyServerEvent): PtyServerEvent.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyServerEvent, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyServerEvent;
|
||||
static deserializeBinaryFromReader(message: PtyServerEvent, reader: jspb.BinaryReader): PtyServerEvent;
|
||||
}
|
||||
|
||||
export namespace PtyServerEvent {
|
||||
export type AsObject = {
|
||||
resize?: PtyEventResize.AsObject,
|
||||
data?: PtyEventData.AsObject,
|
||||
open?: PtyEventOpen.AsObject,
|
||||
exit?: PtyEventExit.AsObject,
|
||||
startError?: PtyEventStartError.AsObject,
|
||||
}
|
||||
|
||||
export enum EventCase {
|
||||
EVENT_NOT_SET = 0,
|
||||
RESIZE = 1,
|
||||
DATA = 2,
|
||||
OPEN = 3,
|
||||
EXIT = 4,
|
||||
START_ERROR = 5,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class PtyEventStart extends jspb.Message {
|
||||
getColumns(): number;
|
||||
setColumns(value: number): PtyEventStart;
|
||||
getRows(): number;
|
||||
setRows(value: number): PtyEventStart;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyEventStart.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyEventStart): PtyEventStart.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyEventStart, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyEventStart;
|
||||
static deserializeBinaryFromReader(message: PtyEventStart, reader: jspb.BinaryReader): PtyEventStart;
|
||||
}
|
||||
|
||||
export namespace PtyEventStart {
|
||||
export type AsObject = {
|
||||
columns: number,
|
||||
rows: number,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyEventData extends jspb.Message {
|
||||
getMessage(): string;
|
||||
setMessage(value: string): PtyEventData;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyEventData.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyEventData): PtyEventData.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyEventData, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyEventData;
|
||||
static deserializeBinaryFromReader(message: PtyEventData, reader: jspb.BinaryReader): PtyEventData;
|
||||
}
|
||||
|
||||
export namespace PtyEventData {
|
||||
export type AsObject = {
|
||||
message: string,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyEventResize extends jspb.Message {
|
||||
getColumns(): number;
|
||||
setColumns(value: number): PtyEventResize;
|
||||
getRows(): number;
|
||||
setRows(value: number): PtyEventResize;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyEventResize.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyEventResize): PtyEventResize.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyEventResize, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyEventResize;
|
||||
static deserializeBinaryFromReader(message: PtyEventResize, reader: jspb.BinaryReader): PtyEventResize;
|
||||
}
|
||||
|
||||
export namespace PtyEventResize {
|
||||
export type AsObject = {
|
||||
columns: number,
|
||||
rows: number,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyEventOpen extends jspb.Message {
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyEventOpen.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyEventOpen): PtyEventOpen.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyEventOpen, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyEventOpen;
|
||||
static deserializeBinaryFromReader(message: PtyEventOpen, reader: jspb.BinaryReader): PtyEventOpen;
|
||||
}
|
||||
|
||||
export namespace PtyEventOpen {
|
||||
export type AsObject = {
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyEventExit extends jspb.Message {
|
||||
getExitCode(): number;
|
||||
setExitCode(value: number): PtyEventExit;
|
||||
|
||||
hasSignal(): boolean;
|
||||
clearSignal(): void;
|
||||
getSignal(): number | undefined;
|
||||
setSignal(value: number): PtyEventExit;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyEventExit.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyEventExit): PtyEventExit.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyEventExit, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyEventExit;
|
||||
static deserializeBinaryFromReader(message: PtyEventExit, reader: jspb.BinaryReader): PtyEventExit;
|
||||
}
|
||||
|
||||
export namespace PtyEventExit {
|
||||
export type AsObject = {
|
||||
exitCode: number,
|
||||
signal?: number,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyEventStartError extends jspb.Message {
|
||||
getMessage(): string;
|
||||
setMessage(value: string): PtyEventStartError;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyEventStartError.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyEventStartError): PtyEventStartError.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyEventStartError, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyEventStartError;
|
||||
static deserializeBinaryFromReader(message: PtyEventStartError, reader: jspb.BinaryReader): PtyEventStartError;
|
||||
}
|
||||
|
||||
export namespace PtyEventStartError {
|
||||
export type AsObject = {
|
||||
message: string,
|
||||
}
|
||||
}
|
||||
|
||||
export class PtyCwd extends jspb.Message {
|
||||
getCwd(): string;
|
||||
setCwd(value: string): PtyCwd;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): PtyCwd.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: PtyCwd): PtyCwd.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: PtyCwd, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): PtyCwd;
|
||||
static deserializeBinaryFromReader(message: PtyCwd, reader: jspb.BinaryReader): PtyCwd;
|
||||
}
|
||||
|
||||
export namespace PtyCwd {
|
||||
export type AsObject = {
|
||||
cwd: string,
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/* eslint-disable */
|
||||
// @generated by protobuf-ts 2.9.3 with parameter long_type_number,eslint_disable,add_pb_suffix,client_grpc1,server_grpc1,ts_nocheck
|
||||
// @generated from protobuf file "ptyHostService.proto" (syntax proto3)
|
||||
// tslint:disable
|
||||
// @ts-nocheck
|
||||
//
|
||||
//
|
||||
// Teleport
|
||||
// Copyright (C) 2023 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
// TODO(ravicious): Before introducing any changes, move this file to the /proto dir and
|
||||
// remove the generate-grpc-shared script.
|
||||
//
|
||||
import { PtyHost } from "./ptyHostService_pb";
|
||||
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
|
||||
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
|
||||
import type { PtyCwd } from "./ptyHostService_pb";
|
||||
import type { PtyServerEvent } from "./ptyHostService_pb";
|
||||
import type { PtyClientEvent } from "./ptyHostService_pb";
|
||||
import type { PtyId } from "./ptyHostService_pb";
|
||||
import type { PtyCreate } from "./ptyHostService_pb";
|
||||
import * as grpc from "@grpc/grpc-js";
|
||||
/**
|
||||
* @generated from protobuf service PtyHost
|
||||
*/
|
||||
export interface IPtyHostClient {
|
||||
/**
|
||||
* @generated from protobuf rpc: CreatePtyProcess(PtyCreate) returns (PtyId);
|
||||
*/
|
||||
createPtyProcess(input: PtyCreate, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (err: grpc.ServiceError | null, value?: PtyId) => void): grpc.ClientUnaryCall;
|
||||
createPtyProcess(input: PtyCreate, metadata: grpc.Metadata, callback: (err: grpc.ServiceError | null, value?: PtyId) => void): grpc.ClientUnaryCall;
|
||||
createPtyProcess(input: PtyCreate, options: grpc.CallOptions, callback: (err: grpc.ServiceError | null, value?: PtyId) => void): grpc.ClientUnaryCall;
|
||||
createPtyProcess(input: PtyCreate, callback: (err: grpc.ServiceError | null, value?: PtyId) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* @generated from protobuf rpc: ExchangeEvents(stream PtyClientEvent) returns (stream PtyServerEvent);
|
||||
*/
|
||||
exchangeEvents(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<PtyClientEvent, PtyServerEvent>;
|
||||
exchangeEvents(options?: grpc.CallOptions): grpc.ClientDuplexStream<PtyClientEvent, PtyServerEvent>;
|
||||
/**
|
||||
* @generated from protobuf rpc: GetCwd(PtyId) returns (PtyCwd);
|
||||
*/
|
||||
getCwd(input: PtyId, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (err: grpc.ServiceError | null, value?: PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
getCwd(input: PtyId, metadata: grpc.Metadata, callback: (err: grpc.ServiceError | null, value?: PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
getCwd(input: PtyId, options: grpc.CallOptions, callback: (err: grpc.ServiceError | null, value?: PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
getCwd(input: PtyId, callback: (err: grpc.ServiceError | null, value?: PtyCwd) => void): grpc.ClientUnaryCall;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf service PtyHost
|
||||
*/
|
||||
export class PtyHostClient extends grpc.Client implements IPtyHostClient {
|
||||
private readonly _binaryOptions: Partial<BinaryReadOptions & BinaryWriteOptions>;
|
||||
constructor(address: string, credentials: grpc.ChannelCredentials, options: grpc.ClientOptions = {}, binaryOptions: Partial<BinaryReadOptions & BinaryWriteOptions> = {}) {
|
||||
super(address, credentials, options);
|
||||
this._binaryOptions = binaryOptions;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf rpc: CreatePtyProcess(PtyCreate) returns (PtyId);
|
||||
*/
|
||||
createPtyProcess(input: PtyCreate, metadata: grpc.Metadata | grpc.CallOptions | ((err: grpc.ServiceError | null, value?: PtyId) => void), options?: grpc.CallOptions | ((err: grpc.ServiceError | null, value?: PtyId) => void), callback?: ((err: grpc.ServiceError | null, value?: PtyId) => void)): grpc.ClientUnaryCall {
|
||||
const method = PtyHost.methods[0];
|
||||
return this.makeUnaryRequest<PtyCreate, PtyId>(`/${PtyHost.typeName}/${method.name}`, (value: PtyCreate): Buffer => Buffer.from(method.I.toBinary(value, this._binaryOptions)), (value: Buffer): PtyId => method.O.fromBinary(value, this._binaryOptions), input, (metadata as any), (options as any), (callback as any));
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf rpc: ExchangeEvents(stream PtyClientEvent) returns (stream PtyServerEvent);
|
||||
*/
|
||||
exchangeEvents(metadata?: grpc.Metadata | grpc.CallOptions, options?: grpc.CallOptions): grpc.ClientDuplexStream<PtyClientEvent, PtyServerEvent> {
|
||||
const method = PtyHost.methods[1];
|
||||
return this.makeBidiStreamRequest<PtyClientEvent, PtyServerEvent>(`/${PtyHost.typeName}/${method.name}`, (value: PtyClientEvent): Buffer => Buffer.from(method.I.toBinary(value, this._binaryOptions)), (value: Buffer): PtyServerEvent => method.O.fromBinary(value, this._binaryOptions), (metadata as any), options);
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf rpc: GetCwd(PtyId) returns (PtyCwd);
|
||||
*/
|
||||
getCwd(input: PtyId, metadata: grpc.Metadata | grpc.CallOptions | ((err: grpc.ServiceError | null, value?: PtyCwd) => void), options?: grpc.CallOptions | ((err: grpc.ServiceError | null, value?: PtyCwd) => void), callback?: ((err: grpc.ServiceError | null, value?: PtyCwd) => void)): grpc.ClientUnaryCall {
|
||||
const method = PtyHost.methods[2];
|
||||
return this.makeUnaryRequest<PtyId, PtyCwd>(`/${PtyHost.typeName}/${method.name}`, (value: PtyId): Buffer => Buffer.from(method.I.toBinary(value, this._binaryOptions)), (value: Buffer): PtyCwd => method.O.fromBinary(value, this._binaryOptions), input, (metadata as any), (options as any), (callback as any));
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/* eslint-disable */
|
||||
// @generated by protobuf-ts 2.9.3 with parameter long_type_number,eslint_disable,add_pb_suffix,client_grpc1,server_grpc1,ts_nocheck
|
||||
// @generated from protobuf file "ptyHostService.proto" (syntax proto3)
|
||||
// tslint:disable
|
||||
// @ts-nocheck
|
||||
//
|
||||
//
|
||||
// Teleport
|
||||
// Copyright (C) 2023 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
// TODO(ravicious): Before introducing any changes, move this file to the /proto dir and
|
||||
// remove the generate-grpc-shared script.
|
||||
//
|
||||
import { PtyCwd } from "./ptyHostService_pb";
|
||||
import { PtyServerEvent } from "./ptyHostService_pb";
|
||||
import { PtyClientEvent } from "./ptyHostService_pb";
|
||||
import { PtyId } from "./ptyHostService_pb";
|
||||
import { PtyCreate } from "./ptyHostService_pb";
|
||||
import type * as grpc from "@grpc/grpc-js";
|
||||
/**
|
||||
* @generated from protobuf service PtyHost
|
||||
*/
|
||||
export interface IPtyHost extends grpc.UntypedServiceImplementation {
|
||||
/**
|
||||
* @generated from protobuf rpc: CreatePtyProcess(PtyCreate) returns (PtyId);
|
||||
*/
|
||||
createPtyProcess: grpc.handleUnaryCall<PtyCreate, PtyId>;
|
||||
/**
|
||||
* @generated from protobuf rpc: ExchangeEvents(stream PtyClientEvent) returns (stream PtyServerEvent);
|
||||
*/
|
||||
exchangeEvents: grpc.handleBidiStreamingCall<PtyClientEvent, PtyServerEvent>;
|
||||
/**
|
||||
* @generated from protobuf rpc: GetCwd(PtyId) returns (PtyCwd);
|
||||
*/
|
||||
getCwd: grpc.handleUnaryCall<PtyId, PtyCwd>;
|
||||
}
|
||||
/**
|
||||
* @grpc/grpc-js definition for the protobuf service PtyHost.
|
||||
*
|
||||
* Usage: Implement the interface IPtyHost and add to a grpc server.
|
||||
*
|
||||
* ```typescript
|
||||
* const server = new grpc.Server();
|
||||
* const service: IPtyHost = ...
|
||||
* server.addService(ptyHostDefinition, service);
|
||||
* ```
|
||||
*/
|
||||
export const ptyHostDefinition: grpc.ServiceDefinition<IPtyHost> = {
|
||||
createPtyProcess: {
|
||||
path: "/PtyHost/CreatePtyProcess",
|
||||
originalName: "CreatePtyProcess",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
responseDeserialize: bytes => PtyId.fromBinary(bytes),
|
||||
requestDeserialize: bytes => PtyCreate.fromBinary(bytes),
|
||||
responseSerialize: value => Buffer.from(PtyId.toBinary(value)),
|
||||
requestSerialize: value => Buffer.from(PtyCreate.toBinary(value))
|
||||
},
|
||||
exchangeEvents: {
|
||||
path: "/PtyHost/ExchangeEvents",
|
||||
originalName: "ExchangeEvents",
|
||||
requestStream: true,
|
||||
responseStream: true,
|
||||
responseDeserialize: bytes => PtyServerEvent.fromBinary(bytes),
|
||||
requestDeserialize: bytes => PtyClientEvent.fromBinary(bytes),
|
||||
responseSerialize: value => Buffer.from(PtyServerEvent.toBinary(value)),
|
||||
requestSerialize: value => Buffer.from(PtyClientEvent.toBinary(value))
|
||||
},
|
||||
getCwd: {
|
||||
path: "/PtyHost/GetCwd",
|
||||
originalName: "GetCwd",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
responseDeserialize: bytes => PtyCwd.fromBinary(bytes),
|
||||
requestDeserialize: bytes => PtyId.fromBinary(bytes),
|
||||
responseSerialize: value => Buffer.from(PtyCwd.toBinary(value)),
|
||||
requestSerialize: value => Buffer.from(PtyId.toBinary(value))
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,836 @@
|
||||
/* eslint-disable */
|
||||
// @generated by protobuf-ts 2.9.3 with parameter long_type_number,eslint_disable,add_pb_suffix,client_grpc1,server_grpc1,ts_nocheck
|
||||
// @generated from protobuf file "ptyHostService.proto" (syntax proto3)
|
||||
// tslint:disable
|
||||
// @ts-nocheck
|
||||
//
|
||||
//
|
||||
// Teleport
|
||||
// Copyright (C) 2023 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
// TODO(ravicious): Before introducing any changes, move this file to the /proto dir and
|
||||
// remove the generate-grpc-shared script.
|
||||
//
|
||||
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
||||
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
|
||||
import type { IBinaryWriter } from "@protobuf-ts/runtime";
|
||||
import { WireType } from "@protobuf-ts/runtime";
|
||||
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
|
||||
import type { IBinaryReader } from "@protobuf-ts/runtime";
|
||||
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
|
||||
import type { PartialMessage } from "@protobuf-ts/runtime";
|
||||
import { reflectionMergePartial } from "@protobuf-ts/runtime";
|
||||
import { MessageType } from "@protobuf-ts/runtime";
|
||||
import { Struct } from "./google/protobuf/struct_pb";
|
||||
/**
|
||||
* @generated from protobuf message PtyId
|
||||
*/
|
||||
export interface PtyId {
|
||||
/**
|
||||
* @generated from protobuf field: string id = 1;
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyCreate
|
||||
*/
|
||||
export interface PtyCreate {
|
||||
/**
|
||||
* @generated from protobuf field: string path = 3;
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* @generated from protobuf field: repeated string args = 4;
|
||||
*/
|
||||
args: string[];
|
||||
/**
|
||||
* @generated from protobuf field: string cwd = 5;
|
||||
*/
|
||||
cwd: string;
|
||||
/**
|
||||
* @generated from protobuf field: google.protobuf.Struct env = 7;
|
||||
*/
|
||||
env?: Struct;
|
||||
/**
|
||||
* @generated from protobuf field: string init_message = 8;
|
||||
*/
|
||||
initMessage: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyClientEvent
|
||||
*/
|
||||
export interface PtyClientEvent {
|
||||
/**
|
||||
* @generated from protobuf oneof: event
|
||||
*/
|
||||
event: {
|
||||
oneofKind: "start";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventStart start = 2;
|
||||
*/
|
||||
start: PtyEventStart;
|
||||
} | {
|
||||
oneofKind: "resize";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventResize resize = 3;
|
||||
*/
|
||||
resize: PtyEventResize;
|
||||
} | {
|
||||
oneofKind: "data";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventData data = 4;
|
||||
*/
|
||||
data: PtyEventData;
|
||||
} | {
|
||||
oneofKind: undefined;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyServerEvent
|
||||
*/
|
||||
export interface PtyServerEvent {
|
||||
/**
|
||||
* @generated from protobuf oneof: event
|
||||
*/
|
||||
event: {
|
||||
oneofKind: "resize";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventResize resize = 1;
|
||||
*/
|
||||
resize: PtyEventResize;
|
||||
} | {
|
||||
oneofKind: "data";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventData data = 2;
|
||||
*/
|
||||
data: PtyEventData;
|
||||
} | {
|
||||
oneofKind: "open";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventOpen open = 3;
|
||||
*/
|
||||
open: PtyEventOpen;
|
||||
} | {
|
||||
oneofKind: "exit";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventExit exit = 4;
|
||||
*/
|
||||
exit: PtyEventExit;
|
||||
} | {
|
||||
oneofKind: "startError";
|
||||
/**
|
||||
* @generated from protobuf field: PtyEventStartError start_error = 5;
|
||||
*/
|
||||
startError: PtyEventStartError;
|
||||
} | {
|
||||
oneofKind: undefined;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyEventStart
|
||||
*/
|
||||
export interface PtyEventStart {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 columns = 2;
|
||||
*/
|
||||
columns: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 rows = 3;
|
||||
*/
|
||||
rows: number;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyEventData
|
||||
*/
|
||||
export interface PtyEventData {
|
||||
/**
|
||||
* @generated from protobuf field: string message = 2;
|
||||
*/
|
||||
message: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyEventResize
|
||||
*/
|
||||
export interface PtyEventResize {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 columns = 2;
|
||||
*/
|
||||
columns: number;
|
||||
/**
|
||||
* @generated from protobuf field: uint32 rows = 3;
|
||||
*/
|
||||
rows: number;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyEventOpen
|
||||
*/
|
||||
export interface PtyEventOpen {
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyEventExit
|
||||
*/
|
||||
export interface PtyEventExit {
|
||||
/**
|
||||
* @generated from protobuf field: uint32 exit_code = 1;
|
||||
*/
|
||||
exitCode: number;
|
||||
/**
|
||||
* @generated from protobuf field: optional uint32 signal = 2;
|
||||
*/
|
||||
signal?: number;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyEventStartError
|
||||
*/
|
||||
export interface PtyEventStartError {
|
||||
/**
|
||||
* @generated from protobuf field: string message = 1;
|
||||
*/
|
||||
message: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message PtyCwd
|
||||
*/
|
||||
export interface PtyCwd {
|
||||
/**
|
||||
* @generated from protobuf field: string cwd = 1;
|
||||
*/
|
||||
cwd: string;
|
||||
}
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyId$Type extends MessageType<PtyId> {
|
||||
constructor() {
|
||||
super("PtyId", [
|
||||
{ no: 1, name: "id", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyId>): PtyId {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.id = "";
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyId>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyId): PtyId {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string id */ 1:
|
||||
message.id = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyId, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string id = 1; */
|
||||
if (message.id !== "")
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.id);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyId
|
||||
*/
|
||||
export const PtyId = new PtyId$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyCreate$Type extends MessageType<PtyCreate> {
|
||||
constructor() {
|
||||
super("PtyCreate", [
|
||||
{ no: 3, name: "path", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "args", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "cwd", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 7, name: "env", kind: "message", T: () => Struct },
|
||||
{ no: 8, name: "init_message", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyCreate>): PtyCreate {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.path = "";
|
||||
message.args = [];
|
||||
message.cwd = "";
|
||||
message.initMessage = "";
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyCreate>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyCreate): PtyCreate {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string path */ 3:
|
||||
message.path = reader.string();
|
||||
break;
|
||||
case /* repeated string args */ 4:
|
||||
message.args.push(reader.string());
|
||||
break;
|
||||
case /* string cwd */ 5:
|
||||
message.cwd = reader.string();
|
||||
break;
|
||||
case /* google.protobuf.Struct env */ 7:
|
||||
message.env = Struct.internalBinaryRead(reader, reader.uint32(), options, message.env);
|
||||
break;
|
||||
case /* string init_message */ 8:
|
||||
message.initMessage = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyCreate, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string path = 3; */
|
||||
if (message.path !== "")
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.path);
|
||||
/* repeated string args = 4; */
|
||||
for (let i = 0; i < message.args.length; i++)
|
||||
writer.tag(4, WireType.LengthDelimited).string(message.args[i]);
|
||||
/* string cwd = 5; */
|
||||
if (message.cwd !== "")
|
||||
writer.tag(5, WireType.LengthDelimited).string(message.cwd);
|
||||
/* google.protobuf.Struct env = 7; */
|
||||
if (message.env)
|
||||
Struct.internalBinaryWrite(message.env, writer.tag(7, WireType.LengthDelimited).fork(), options).join();
|
||||
/* string init_message = 8; */
|
||||
if (message.initMessage !== "")
|
||||
writer.tag(8, WireType.LengthDelimited).string(message.initMessage);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyCreate
|
||||
*/
|
||||
export const PtyCreate = new PtyCreate$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyClientEvent$Type extends MessageType<PtyClientEvent> {
|
||||
constructor() {
|
||||
super("PtyClientEvent", [
|
||||
{ no: 2, name: "start", kind: "message", oneof: "event", T: () => PtyEventStart },
|
||||
{ no: 3, name: "resize", kind: "message", oneof: "event", T: () => PtyEventResize },
|
||||
{ no: 4, name: "data", kind: "message", oneof: "event", T: () => PtyEventData }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyClientEvent>): PtyClientEvent {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.event = { oneofKind: undefined };
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyClientEvent>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyClientEvent): PtyClientEvent {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* PtyEventStart start */ 2:
|
||||
message.event = {
|
||||
oneofKind: "start",
|
||||
start: PtyEventStart.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).start)
|
||||
};
|
||||
break;
|
||||
case /* PtyEventResize resize */ 3:
|
||||
message.event = {
|
||||
oneofKind: "resize",
|
||||
resize: PtyEventResize.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).resize)
|
||||
};
|
||||
break;
|
||||
case /* PtyEventData data */ 4:
|
||||
message.event = {
|
||||
oneofKind: "data",
|
||||
data: PtyEventData.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).data)
|
||||
};
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyClientEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* PtyEventStart start = 2; */
|
||||
if (message.event.oneofKind === "start")
|
||||
PtyEventStart.internalBinaryWrite(message.event.start, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
||||
/* PtyEventResize resize = 3; */
|
||||
if (message.event.oneofKind === "resize")
|
||||
PtyEventResize.internalBinaryWrite(message.event.resize, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
/* PtyEventData data = 4; */
|
||||
if (message.event.oneofKind === "data")
|
||||
PtyEventData.internalBinaryWrite(message.event.data, writer.tag(4, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyClientEvent
|
||||
*/
|
||||
export const PtyClientEvent = new PtyClientEvent$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyServerEvent$Type extends MessageType<PtyServerEvent> {
|
||||
constructor() {
|
||||
super("PtyServerEvent", [
|
||||
{ no: 1, name: "resize", kind: "message", oneof: "event", T: () => PtyEventResize },
|
||||
{ no: 2, name: "data", kind: "message", oneof: "event", T: () => PtyEventData },
|
||||
{ no: 3, name: "open", kind: "message", oneof: "event", T: () => PtyEventOpen },
|
||||
{ no: 4, name: "exit", kind: "message", oneof: "event", T: () => PtyEventExit },
|
||||
{ no: 5, name: "start_error", kind: "message", oneof: "event", T: () => PtyEventStartError }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyServerEvent>): PtyServerEvent {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.event = { oneofKind: undefined };
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyServerEvent>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyServerEvent): PtyServerEvent {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* PtyEventResize resize */ 1:
|
||||
message.event = {
|
||||
oneofKind: "resize",
|
||||
resize: PtyEventResize.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).resize)
|
||||
};
|
||||
break;
|
||||
case /* PtyEventData data */ 2:
|
||||
message.event = {
|
||||
oneofKind: "data",
|
||||
data: PtyEventData.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).data)
|
||||
};
|
||||
break;
|
||||
case /* PtyEventOpen open */ 3:
|
||||
message.event = {
|
||||
oneofKind: "open",
|
||||
open: PtyEventOpen.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).open)
|
||||
};
|
||||
break;
|
||||
case /* PtyEventExit exit */ 4:
|
||||
message.event = {
|
||||
oneofKind: "exit",
|
||||
exit: PtyEventExit.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).exit)
|
||||
};
|
||||
break;
|
||||
case /* PtyEventStartError start_error */ 5:
|
||||
message.event = {
|
||||
oneofKind: "startError",
|
||||
startError: PtyEventStartError.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).startError)
|
||||
};
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyServerEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* PtyEventResize resize = 1; */
|
||||
if (message.event.oneofKind === "resize")
|
||||
PtyEventResize.internalBinaryWrite(message.event.resize, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
||||
/* PtyEventData data = 2; */
|
||||
if (message.event.oneofKind === "data")
|
||||
PtyEventData.internalBinaryWrite(message.event.data, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
|
||||
/* PtyEventOpen open = 3; */
|
||||
if (message.event.oneofKind === "open")
|
||||
PtyEventOpen.internalBinaryWrite(message.event.open, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
||||
/* PtyEventExit exit = 4; */
|
||||
if (message.event.oneofKind === "exit")
|
||||
PtyEventExit.internalBinaryWrite(message.event.exit, writer.tag(4, WireType.LengthDelimited).fork(), options).join();
|
||||
/* PtyEventStartError start_error = 5; */
|
||||
if (message.event.oneofKind === "startError")
|
||||
PtyEventStartError.internalBinaryWrite(message.event.startError, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyServerEvent
|
||||
*/
|
||||
export const PtyServerEvent = new PtyServerEvent$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyEventStart$Type extends MessageType<PtyEventStart> {
|
||||
constructor() {
|
||||
super("PtyEventStart", [
|
||||
{ no: 2, name: "columns", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 3, name: "rows", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyEventStart>): PtyEventStart {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.columns = 0;
|
||||
message.rows = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyEventStart>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyEventStart): PtyEventStart {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 columns */ 2:
|
||||
message.columns = reader.uint32();
|
||||
break;
|
||||
case /* uint32 rows */ 3:
|
||||
message.rows = reader.uint32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyEventStart, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 columns = 2; */
|
||||
if (message.columns !== 0)
|
||||
writer.tag(2, WireType.Varint).uint32(message.columns);
|
||||
/* uint32 rows = 3; */
|
||||
if (message.rows !== 0)
|
||||
writer.tag(3, WireType.Varint).uint32(message.rows);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyEventStart
|
||||
*/
|
||||
export const PtyEventStart = new PtyEventStart$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyEventData$Type extends MessageType<PtyEventData> {
|
||||
constructor() {
|
||||
super("PtyEventData", [
|
||||
{ no: 2, name: "message", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyEventData>): PtyEventData {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.message = "";
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyEventData>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyEventData): PtyEventData {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string message */ 2:
|
||||
message.message = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyEventData, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string message = 2; */
|
||||
if (message.message !== "")
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.message);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyEventData
|
||||
*/
|
||||
export const PtyEventData = new PtyEventData$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyEventResize$Type extends MessageType<PtyEventResize> {
|
||||
constructor() {
|
||||
super("PtyEventResize", [
|
||||
{ no: 2, name: "columns", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 3, name: "rows", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyEventResize>): PtyEventResize {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.columns = 0;
|
||||
message.rows = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyEventResize>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyEventResize): PtyEventResize {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 columns */ 2:
|
||||
message.columns = reader.uint32();
|
||||
break;
|
||||
case /* uint32 rows */ 3:
|
||||
message.rows = reader.uint32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyEventResize, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 columns = 2; */
|
||||
if (message.columns !== 0)
|
||||
writer.tag(2, WireType.Varint).uint32(message.columns);
|
||||
/* uint32 rows = 3; */
|
||||
if (message.rows !== 0)
|
||||
writer.tag(3, WireType.Varint).uint32(message.rows);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyEventResize
|
||||
*/
|
||||
export const PtyEventResize = new PtyEventResize$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyEventOpen$Type extends MessageType<PtyEventOpen> {
|
||||
constructor() {
|
||||
super("PtyEventOpen", []);
|
||||
}
|
||||
create(value?: PartialMessage<PtyEventOpen>): PtyEventOpen {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyEventOpen>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyEventOpen): PtyEventOpen {
|
||||
return target ?? this.create();
|
||||
}
|
||||
internalBinaryWrite(message: PtyEventOpen, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyEventOpen
|
||||
*/
|
||||
export const PtyEventOpen = new PtyEventOpen$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyEventExit$Type extends MessageType<PtyEventExit> {
|
||||
constructor() {
|
||||
super("PtyEventExit", [
|
||||
{ no: 1, name: "exit_code", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
|
||||
{ no: 2, name: "signal", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyEventExit>): PtyEventExit {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.exitCode = 0;
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyEventExit>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyEventExit): PtyEventExit {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* uint32 exit_code */ 1:
|
||||
message.exitCode = reader.uint32();
|
||||
break;
|
||||
case /* optional uint32 signal */ 2:
|
||||
message.signal = reader.uint32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyEventExit, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* uint32 exit_code = 1; */
|
||||
if (message.exitCode !== 0)
|
||||
writer.tag(1, WireType.Varint).uint32(message.exitCode);
|
||||
/* optional uint32 signal = 2; */
|
||||
if (message.signal !== undefined)
|
||||
writer.tag(2, WireType.Varint).uint32(message.signal);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyEventExit
|
||||
*/
|
||||
export const PtyEventExit = new PtyEventExit$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyEventStartError$Type extends MessageType<PtyEventStartError> {
|
||||
constructor() {
|
||||
super("PtyEventStartError", [
|
||||
{ no: 1, name: "message", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyEventStartError>): PtyEventStartError {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.message = "";
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyEventStartError>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyEventStartError): PtyEventStartError {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string message */ 1:
|
||||
message.message = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyEventStartError, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string message = 1; */
|
||||
if (message.message !== "")
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.message);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyEventStartError
|
||||
*/
|
||||
export const PtyEventStartError = new PtyEventStartError$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class PtyCwd$Type extends MessageType<PtyCwd> {
|
||||
constructor() {
|
||||
super("PtyCwd", [
|
||||
{ no: 1, name: "cwd", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<PtyCwd>): PtyCwd {
|
||||
const message = globalThis.Object.create((this.messagePrototype!));
|
||||
message.cwd = "";
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<PtyCwd>(this, message, value);
|
||||
return message;
|
||||
}
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PtyCwd): PtyCwd {
|
||||
let message = target ?? this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string cwd */ 1:
|
||||
message.cwd = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message: PtyCwd, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
|
||||
/* string cwd = 1; */
|
||||
if (message.cwd !== "")
|
||||
writer.tag(1, WireType.LengthDelimited).string(message.cwd);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message PtyCwd
|
||||
*/
|
||||
export const PtyCwd = new PtyCwd$Type();
|
||||
/**
|
||||
* @generated ServiceType for protobuf service PtyHost
|
||||
*/
|
||||
export const PtyHost = new ServiceType("PtyHost", [
|
||||
{ name: "CreatePtyProcess", options: {}, I: PtyCreate, O: PtyId },
|
||||
{ name: "ExchangeEvents", serverStreaming: true, clientStreaming: true, options: {}, I: PtyClientEvent, O: PtyServerEvent },
|
||||
{ name: "GetCwd", options: {}, I: PtyId, O: PtyCwd }
|
||||
]);
|
||||
@@ -17,5 +17,6 @@
|
||||
*/
|
||||
|
||||
export * from './types';
|
||||
export * from '../api/protogen/ptyHostService_grpc_pb';
|
||||
export * from '../api/protogen/ptyHostService_pb.grpc-server';
|
||||
export * from '../api/protogen/ptyHostService_pb.grpc-client';
|
||||
export * from '../api/protogen/ptyHostService_pb';
|
||||
|
||||
@@ -20,6 +20,12 @@ import { ServerDuplexStream } from '@grpc/grpc-js';
|
||||
|
||||
import Logger from 'teleterm/logger';
|
||||
|
||||
import {
|
||||
ptyEventOneOfIsData,
|
||||
ptyEventOneOfIsResize,
|
||||
ptyEventOneOfIsStart,
|
||||
} from 'teleterm/helpers';
|
||||
|
||||
import {
|
||||
PtyClientEvent,
|
||||
PtyEventData,
|
||||
@@ -43,7 +49,7 @@ export class PtyEventsStreamHandler {
|
||||
private readonly ptyProcesses: Map<string, PtyProcess>
|
||||
) {
|
||||
this.ptyId = stream.metadata.get('ptyId')[0].toString();
|
||||
this.ptyProcess = ptyProcesses.get(this.ptyId);
|
||||
this.ptyProcess = ptyProcesses.get(this.ptyId)!;
|
||||
this.logger = new Logger(`PtyEventsStreamHandler (id: ${this.ptyId})`);
|
||||
|
||||
stream.addListener('data', event => this.handleStreamData(event));
|
||||
@@ -52,49 +58,70 @@ export class PtyEventsStreamHandler {
|
||||
}
|
||||
|
||||
private handleStreamData(event: PtyClientEvent): void {
|
||||
switch (event.getEventCase()) {
|
||||
case PtyClientEvent.EventCase.START:
|
||||
return this.handleStartEvent(event.getStart());
|
||||
case PtyClientEvent.EventCase.DATA:
|
||||
return this.handleDataEvent(event.getData());
|
||||
case PtyClientEvent.EventCase.RESIZE:
|
||||
return this.handleResizeEvent(event.getResize());
|
||||
if (ptyEventOneOfIsStart(event.event)) {
|
||||
return this.handleStartEvent(event.event.start);
|
||||
}
|
||||
|
||||
if (ptyEventOneOfIsData(event.event)) {
|
||||
return this.handleDataEvent(event.event.data);
|
||||
}
|
||||
|
||||
if (ptyEventOneOfIsResize(event.event)) {
|
||||
return this.handleResizeEvent(event.event.resize);
|
||||
}
|
||||
}
|
||||
|
||||
private handleStartEvent(event: PtyEventStart): void {
|
||||
this.ptyProcess.onData(data =>
|
||||
this.stream.write(
|
||||
new PtyServerEvent().setData(new PtyEventData().setMessage(data))
|
||||
PtyServerEvent.create({
|
||||
event: {
|
||||
oneofKind: 'data',
|
||||
data: PtyEventData.create({ message: data }),
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
this.ptyProcess.onOpen(() =>
|
||||
this.stream.write(new PtyServerEvent().setOpen(new PtyEventOpen()))
|
||||
this.stream.write(
|
||||
PtyServerEvent.create({
|
||||
event: {
|
||||
oneofKind: 'open',
|
||||
open: PtyEventOpen.create(),
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
this.ptyProcess.onExit(({ exitCode, signal }) =>
|
||||
this.stream.write(
|
||||
new PtyServerEvent().setExit(
|
||||
new PtyEventExit().setExitCode(exitCode).setSignal(signal)
|
||||
)
|
||||
PtyServerEvent.create({
|
||||
event: {
|
||||
oneofKind: 'exit',
|
||||
exit: PtyEventExit.create({ exitCode, signal }),
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
this.ptyProcess.onStartError(message => {
|
||||
this.stream.write(
|
||||
new PtyServerEvent().setStartError(
|
||||
new PtyEventStartError().setMessage(message)
|
||||
)
|
||||
PtyServerEvent.create({
|
||||
event: {
|
||||
oneofKind: 'startError',
|
||||
startError: PtyEventStartError.create({ message }),
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
this.ptyProcess.start(event.getColumns(), event.getRows());
|
||||
this.ptyProcess.start(event.columns, event.rows);
|
||||
this.logger.info(`stream has started`);
|
||||
}
|
||||
|
||||
private handleDataEvent(event: PtyEventData): void {
|
||||
this.ptyProcess.write(event.getMessage());
|
||||
this.ptyProcess.write(event.message);
|
||||
}
|
||||
|
||||
private handleResizeEvent(event: PtyEventResize): void {
|
||||
this.ptyProcess.resize(event.getColumns(), event.getRows());
|
||||
this.ptyProcess.resize(event.columns, event.rows);
|
||||
}
|
||||
|
||||
private handleStreamError(error: Error): void {
|
||||
|
||||
@@ -20,26 +20,28 @@ import { unique } from 'teleterm/ui/utils';
|
||||
|
||||
import Logger from 'teleterm/logger';
|
||||
|
||||
import { Struct } from 'teleterm/sharedProcess/api/protogen/google/protobuf/struct_pb';
|
||||
|
||||
import { PtyProcess } from './ptyProcess';
|
||||
import { IPtyHostServer } from './../api/protogen/ptyHostService_grpc_pb';
|
||||
import { IPtyHost } from './../api/protogen/ptyHostService_pb.grpc-server';
|
||||
import { PtyCwd, PtyId } from './../api/protogen/ptyHostService_pb';
|
||||
import { PtyEventsStreamHandler } from './ptyEventsStreamHandler';
|
||||
|
||||
export function createPtyHostService(): IPtyHostServer {
|
||||
export function createPtyHostService(): IPtyHost {
|
||||
const logger = new Logger('PtyHostService');
|
||||
const ptyProcesses = new Map<string, PtyProcess>();
|
||||
|
||||
return {
|
||||
createPtyProcess: (call, callback) => {
|
||||
const ptyOptions = call.request.toObject();
|
||||
const ptyOptions = call.request;
|
||||
const ptyId = unique();
|
||||
try {
|
||||
const ptyProcess = new PtyProcess({
|
||||
path: ptyOptions.path,
|
||||
args: ptyOptions.argsList,
|
||||
args: ptyOptions.args,
|
||||
cwd: ptyOptions.cwd,
|
||||
ptyId,
|
||||
env: call.request.getEnv()?.toJavaScript() as Record<string, string>,
|
||||
env: Struct.toJson(call.request.env!) as Record<string, string>,
|
||||
initMessage: ptyOptions.initMessage,
|
||||
});
|
||||
ptyProcesses.set(ptyId, ptyProcess);
|
||||
@@ -48,11 +50,11 @@ export function createPtyHostService(): IPtyHostServer {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
callback(null, new PtyId().setId(ptyId));
|
||||
callback(null, PtyId.create({ id: ptyId }));
|
||||
logger.info(`created PTY process for id ${ptyId}`);
|
||||
},
|
||||
getCwd: (call, callback) => {
|
||||
const id = call.request.getId();
|
||||
const id = call.request.id;
|
||||
const ptyProcess = ptyProcesses.get(id);
|
||||
if (!ptyProcess) {
|
||||
const message = `PTY process with id: ${id} does not exist`;
|
||||
@@ -62,7 +64,7 @@ export function createPtyHostService(): IPtyHostServer {
|
||||
ptyProcess
|
||||
.getCwd()
|
||||
.then(cwd => {
|
||||
const response = new PtyCwd().setCwd(cwd);
|
||||
const response = PtyCwd.create({ cwd });
|
||||
callback(null, response);
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
@@ -31,7 +31,8 @@ import {
|
||||
import { RuntimeSettings } from 'teleterm/mainProcess/types';
|
||||
import Logger from 'teleterm/logger';
|
||||
|
||||
import { PtyHostService } from './api/protogen/ptyHostService_grpc_pb';
|
||||
import { ptyHostDefinition } from 'teleterm/sharedProcess/api/protogen/ptyHostService_pb.grpc-server';
|
||||
|
||||
import { createPtyHostService } from './ptyHost/ptyHostService';
|
||||
|
||||
const runtimeSettings = getRuntimeSettings();
|
||||
@@ -73,8 +74,7 @@ async function initializeServer(
|
||||
}
|
||||
|
||||
const server = new Server();
|
||||
// @ts-expect-error we have a typed service
|
||||
server.addService(PtyHostService, createPtyHostService());
|
||||
server.addService(ptyHostDefinition, createPtyHostService());
|
||||
|
||||
// grpc-js requires us to pass localhost:port for TCP connections,
|
||||
const grpcServerAddress = address.replace('tcp://', '');
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ITshdEventsServiceServer } from 'gen-proto-js/teleport/lib/teleterm/v1/tshd_events_service_grpc_pb';
|
||||
import { ITshdEventsService } from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb.grpc-server';
|
||||
|
||||
import { sendUnaryData, ServerUnaryCall } from 'grpc';
|
||||
|
||||
import { TshdClient } from 'teleterm/services/tshd/types';
|
||||
import { PtyServiceClient } from 'teleterm/services/pty';
|
||||
import { RuntimeSettings, MainProcessClient } from 'teleterm/mainProcess/types';
|
||||
import { FileStorage } from 'teleterm/services/fileStorage';
|
||||
import { Logger, LoggerService } from 'teleterm/services/logger/types';
|
||||
import { FileStorage } from 'teleterm/services/fileStorage';
|
||||
import { MainProcessClient, RuntimeSettings } from 'teleterm/mainProcess/types';
|
||||
import { PtyServiceClient } from 'teleterm/services/pty';
|
||||
import { TshdClient } from 'teleterm/services/tshd/types';
|
||||
|
||||
export type {
|
||||
Logger,
|
||||
@@ -78,13 +80,11 @@ export type {
|
||||
* actually uses the returned object.
|
||||
*/
|
||||
export type TshdEventContextBridgeService = {
|
||||
[RpcName in keyof ITshdEventsServiceServer]: (args: {
|
||||
[RpcName in keyof ITshdEventsService]: (args: {
|
||||
/**
|
||||
* request is the result of calling call.request.toObject() in a gRPC handler.
|
||||
*/
|
||||
request: ReturnType<
|
||||
Parameters<ITshdEventsServiceServer[RpcName]>[0]['request']['toObject']
|
||||
>;
|
||||
request: ExtractRequestType<Parameters<ITshdEventsService[RpcName]>[0]>;
|
||||
/**
|
||||
* onRequestCancelled sets up a callback that is called when the request gets canceled by the
|
||||
* client (tshd in this case).
|
||||
@@ -93,14 +93,18 @@ export type TshdEventContextBridgeService = {
|
||||
}) => Promise<
|
||||
// The following type maps to the object version of the response type expected as the second
|
||||
// argument to the callback function in a gRPC handler.
|
||||
ReturnType<
|
||||
Parameters<
|
||||
Parameters<ITshdEventsServiceServer[RpcName]>[1]
|
||||
>[1]['toObject']
|
||||
>
|
||||
ExtractResponseType<Parameters<ITshdEventsService[RpcName]>[1]>
|
||||
>;
|
||||
};
|
||||
|
||||
export type ExtractRequestType<T> = T extends ServerUnaryCall<infer Req, any>
|
||||
? Req
|
||||
: never;
|
||||
|
||||
export type ExtractResponseType<T> = T extends sendUnaryData<infer Res>
|
||||
? Res
|
||||
: never;
|
||||
|
||||
export type ElectronGlobals = {
|
||||
readonly mainProcessClient: MainProcessClient;
|
||||
readonly tshClient: TshdClient;
|
||||
|
||||
@@ -36,11 +36,8 @@ export const AppInitializer = () => {
|
||||
const initializeApp = useCallback(async () => {
|
||||
try {
|
||||
await appContext.pullInitialState();
|
||||
|
||||
setShouldShowUi(true);
|
||||
|
||||
await showStartupModalsAndNotifications(appContext);
|
||||
|
||||
appContext.mainProcessClient.signalUserInterfaceReadiness({
|
||||
success: true,
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ function makeProps(): ClusterLoginPresentationProps {
|
||||
data: {
|
||||
preferredMfa: 'webauthn',
|
||||
localAuthEnabled: true,
|
||||
authProvidersList: [],
|
||||
authProviders: [],
|
||||
type: '',
|
||||
secondFactor: 'optional',
|
||||
hasMessageOfTheDay: false,
|
||||
@@ -172,7 +172,7 @@ export const SsoOnly = () => {
|
||||
const props = makeProps();
|
||||
props.initAttempt.data.localAuthEnabled = false;
|
||||
props.initAttempt.data.authType = 'github';
|
||||
props.initAttempt.data.authProvidersList = [
|
||||
props.initAttempt.data.authProviders = [
|
||||
{ type: 'github', name: 'github', displayName: 'github' },
|
||||
{ type: 'saml', name: 'microsoft', displayName: 'microsoft' },
|
||||
];
|
||||
@@ -205,7 +205,7 @@ export const LocalLoggedInUserWithPasswordless = () => {
|
||||
|
||||
export const LocalWithSso = () => {
|
||||
const props = makeProps();
|
||||
props.initAttempt.data.authProvidersList = [
|
||||
props.initAttempt.data.authProviders = [
|
||||
{ type: 'github', name: 'github', displayName: 'github' },
|
||||
{ type: 'saml', name: 'microsoft', displayName: 'microsoft' },
|
||||
];
|
||||
@@ -243,7 +243,7 @@ export const PasswordlessWithLocalLoggedInUser = () => {
|
||||
export const SsoWithLocalAndPasswordless = () => {
|
||||
const props = makeProps();
|
||||
props.initAttempt.data.authType = 'github';
|
||||
props.initAttempt.data.authProvidersList = [
|
||||
props.initAttempt.data.authProviders = [
|
||||
{ type: 'github', name: 'github', displayName: 'github' },
|
||||
{ type: 'saml', name: 'microsoft', displayName: 'microsoft' },
|
||||
];
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function LoginForm(props: Props) {
|
||||
const {
|
||||
loginAttempt,
|
||||
onAbort,
|
||||
authProvidersList,
|
||||
authProviders,
|
||||
localAuthEnabled = true,
|
||||
shouldPromptSsoStatus,
|
||||
webauthnLogin,
|
||||
@@ -53,7 +53,7 @@ export default function LoginForm(props: Props) {
|
||||
return <PromptSsoStatus onCancel={onAbort} />;
|
||||
}
|
||||
|
||||
const ssoEnabled = authProvidersList?.length > 0;
|
||||
const ssoEnabled = authProviders?.length > 0;
|
||||
|
||||
// If local auth was not enabled, disregard any primary auth type config
|
||||
// and display sso providers if any.
|
||||
@@ -107,7 +107,7 @@ const Primary = ({
|
||||
hasTransitionEnded,
|
||||
...otherProps
|
||||
}: Props & StepComponentProps) => {
|
||||
const ssoEnabled = otherProps.authProvidersList?.length > 0;
|
||||
const ssoEnabled = otherProps.authProviders?.length > 0;
|
||||
let otherOptionsAvailable = true;
|
||||
let $primary;
|
||||
|
||||
@@ -161,7 +161,7 @@ const Secondary = ({
|
||||
refCallback,
|
||||
...otherProps
|
||||
}: Props & StepComponentProps) => {
|
||||
const ssoEnabled = otherProps.authProvidersList?.length > 0;
|
||||
const ssoEnabled = otherProps.authProviders?.length > 0;
|
||||
const { primaryAuthType, allowPasswordless } = otherProps;
|
||||
|
||||
let $secondary;
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ import type { Props } from '../FormLogin';
|
||||
|
||||
export const FormSso = ({
|
||||
loginAttempt,
|
||||
authProvidersList,
|
||||
authProviders,
|
||||
onLoginWithSso,
|
||||
autoFocus = false,
|
||||
}: Props) => {
|
||||
@@ -34,7 +34,7 @@ export const FormSso = ({
|
||||
<SSOButtonList
|
||||
prefixText="Login with"
|
||||
isDisabled={loginAttempt.status === 'processing'}
|
||||
providers={authProvidersList}
|
||||
providers={authProviders}
|
||||
onClick={onLoginWithSso}
|
||||
autoFocus={autoFocus}
|
||||
/>
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ export function NoAccess() {
|
||||
|
||||
export function AccessUnknown() {
|
||||
const cluster = makeRootCluster();
|
||||
cluster.loggedInUser.userType = UserType.USER_TYPE_UNSPECIFIED;
|
||||
cluster.loggedInUser.userType = UserType.UNSPECIFIED;
|
||||
const appContext = new MockAppContext({});
|
||||
|
||||
return (
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ function setupAppContext(): {
|
||||
list: true,
|
||||
read: true,
|
||||
edit: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
use: true,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export function Running() {
|
||||
Promise.resolve(
|
||||
makeServer({
|
||||
hostname: 'staging-mac-mini',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
hostname: 'staging-mac-mini',
|
||||
'teleport.dev/connect-my-computer/owner': '[email protected]',
|
||||
}),
|
||||
|
||||
@@ -227,7 +227,7 @@ export function Status(props: { closeDocument?: () => void }) {
|
||||
<LabelsContainer gap={1} className={state}>
|
||||
{/* Explicitly check for existence of agentNode because Transition doesn't seem to
|
||||
unmount immediately when `in` becomes falsy. */}
|
||||
{agentNode?.labelsList && renderLabels(agentNode.labelsList)}
|
||||
{agentNode?.labels && renderLabels(agentNode.labels)}
|
||||
</LabelsContainer>
|
||||
)}
|
||||
</Transition>
|
||||
|
||||
@@ -70,7 +70,7 @@ test.each(testCases)('$name', testCase => {
|
||||
list: false,
|
||||
use: false,
|
||||
read: false,
|
||||
pb_delete: false,
|
||||
delete: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -52,13 +52,13 @@ export function getConnectMyComputerAccess(
|
||||
|
||||
if (
|
||||
!loggedInUser ||
|
||||
loggedInUser.userType === tsh.UserType.USER_TYPE_UNSPECIFIED ||
|
||||
loggedInUser.userType === tsh.UserType.UNSPECIFIED ||
|
||||
!loggedInUser.acl
|
||||
) {
|
||||
return { status: 'unknown' };
|
||||
}
|
||||
|
||||
if (loggedInUser.userType === tsh.UserType.USER_TYPE_SSO) {
|
||||
if (loggedInUser.userType === tsh.UserType.SSO) {
|
||||
return { status: 'no-access', reason: 'sso-user' };
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ function getMocks() {
|
||||
list: false,
|
||||
use: false,
|
||||
read: false,
|
||||
pb_delete: false,
|
||||
delete: false,
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -114,7 +114,7 @@ function HttpApp() {
|
||||
function Server() {
|
||||
const appContext = new MockAppContext();
|
||||
const testCluster = makeRootCluster();
|
||||
testCluster.loggedInUser.sshLoginsList = ['ec2-user'];
|
||||
testCluster.loggedInUser.sshLogins = ['ec2-user'];
|
||||
appContext.workspacesService.setState(d => {
|
||||
d.rootClusterUri = testCluster.uri;
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ export function ConnectServerActionButton(props: {
|
||||
|
||||
function getSshLogins(): string[] {
|
||||
const cluster = ctx.clustersService.findClusterByResource(props.server.uri);
|
||||
return cluster?.loggedInUser?.sshLoginsList || [];
|
||||
return cluster?.loggedInUser?.sshLogins || [];
|
||||
}
|
||||
|
||||
function connect(login: string): void {
|
||||
|
||||
@@ -65,13 +65,13 @@ export const OnlineEmptyResourcesAndCanAddResourcesAndConnectComputer = () => {
|
||||
makeRootCluster({
|
||||
uri: rootClusterDoc.clusterUri,
|
||||
loggedInUser: makeLoggedInUser({
|
||||
userType: tsh.UserType.USER_TYPE_LOCAL,
|
||||
userType: tsh.UserType.LOCAL,
|
||||
acl: {
|
||||
tokens: {
|
||||
create: true,
|
||||
list: true,
|
||||
edit: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
read: true,
|
||||
use: true,
|
||||
},
|
||||
@@ -101,13 +101,13 @@ export const OnlineEmptyResourcesAndCanAddResourcesButCannotConnectComputer =
|
||||
makeRootCluster({
|
||||
uri: rootClusterDoc.clusterUri,
|
||||
loggedInUser: makeLoggedInUser({
|
||||
userType: tsh.UserType.USER_TYPE_SSO,
|
||||
userType: tsh.UserType.SSO,
|
||||
acl: {
|
||||
tokens: {
|
||||
create: true,
|
||||
list: true,
|
||||
edit: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
read: true,
|
||||
use: true,
|
||||
},
|
||||
@@ -141,7 +141,7 @@ export const OnlineEmptyResourcesAndCannotAddResources = () => {
|
||||
create: false,
|
||||
list: true,
|
||||
edit: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
read: true,
|
||||
use: true,
|
||||
},
|
||||
|
||||
@@ -48,13 +48,13 @@ it('displays a button for Connect My Computer in the empty state if the user can
|
||||
makeRootCluster({
|
||||
uri: doc.clusterUri,
|
||||
loggedInUser: makeLoggedInUser({
|
||||
userType: tsh.UserType.USER_TYPE_LOCAL,
|
||||
userType: tsh.UserType.LOCAL,
|
||||
acl: {
|
||||
tokens: {
|
||||
create: true,
|
||||
list: true,
|
||||
edit: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
read: true,
|
||||
use: true,
|
||||
},
|
||||
@@ -118,13 +118,13 @@ it('does not display a button for Connect My Computer in the empty state if the
|
||||
makeRootCluster({
|
||||
uri: doc.clusterUri,
|
||||
loggedInUser: makeLoggedInUser({
|
||||
userType: tsh.UserType.USER_TYPE_LOCAL,
|
||||
userType: tsh.UserType.LOCAL,
|
||||
acl: {
|
||||
tokens: {
|
||||
create: false,
|
||||
list: true,
|
||||
edit: true,
|
||||
pb_delete: true,
|
||||
delete: true,
|
||||
read: true,
|
||||
use: true,
|
||||
},
|
||||
|
||||
@@ -37,10 +37,10 @@ import * as icons from 'design/Icon';
|
||||
import Image from 'design/Image';
|
||||
import stack from 'design/assets/resources/stack.png';
|
||||
|
||||
import { DefaultTab } from 'shared/services/unifiedResourcePreferences';
|
||||
|
||||
import { Attempt } from 'shared/hooks/useAsync';
|
||||
|
||||
import { DefaultTab } from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import {
|
||||
UnifiedResourceResponse,
|
||||
UserPreferences,
|
||||
@@ -86,8 +86,7 @@ export function UnifiedResources(props: {
|
||||
() => ({
|
||||
kinds: props.queryParams.resourceKinds,
|
||||
sort: props.queryParams.sort,
|
||||
pinnedOnly:
|
||||
unifiedResourcePreferences.defaultTab === DefaultTab.DEFAULT_TAB_PINNED,
|
||||
pinnedOnly: unifiedResourcePreferences.defaultTab === DefaultTab.PINNED,
|
||||
search: props.queryParams.advancedSearchEnabled
|
||||
? ''
|
||||
: props.queryParams.search,
|
||||
@@ -190,7 +189,7 @@ const Resources = memo(
|
||||
field: props.queryParams.sort.fieldName,
|
||||
},
|
||||
search: props.queryParams.search,
|
||||
kindsList: props.queryParams.kinds,
|
||||
kinds: props.queryParams.kinds,
|
||||
query: props.queryParams.query,
|
||||
pinnedOnly: props.queryParams.pinnedOnly,
|
||||
startKey: paginationParams.startKey,
|
||||
@@ -228,24 +227,23 @@ const Resources = memo(
|
||||
return cleanup;
|
||||
}, [onResourcesRefreshRequest, fetch, clear]);
|
||||
|
||||
const resourceIdsList =
|
||||
props.userPreferences.clusterPreferences?.pinnedResources
|
||||
?.resourceIdsList;
|
||||
const resourceIds =
|
||||
props.userPreferences.clusterPreferences?.pinnedResources?.resourceIds;
|
||||
const { updateUserPreferences } = props;
|
||||
const pinning = useMemo<UnifiedResourcesPinning>(() => {
|
||||
return resourceIdsList
|
||||
return resourceIds
|
||||
? {
|
||||
kind: 'supported',
|
||||
getClusterPinnedResources: async () => resourceIdsList,
|
||||
getClusterPinnedResources: async () => resourceIds,
|
||||
updateClusterPinnedResources: pinnedIds =>
|
||||
updateUserPreferences({
|
||||
clusterPreferences: {
|
||||
pinnedResources: { resourceIdsList: pinnedIds },
|
||||
pinnedResources: { resourceIds: pinnedIds },
|
||||
},
|
||||
}),
|
||||
}
|
||||
: { kind: 'not-supported' };
|
||||
}, [updateUserPreferences, resourceIdsList]);
|
||||
}, [updateUserPreferences, resourceIds]);
|
||||
|
||||
return (
|
||||
<SharedUnifiedResources
|
||||
@@ -302,7 +300,7 @@ const mapToSharedResource = (
|
||||
return {
|
||||
resource: {
|
||||
kind: 'node' as const,
|
||||
labels: server.labelsList,
|
||||
labels: server.labels,
|
||||
id: server.name,
|
||||
hostname: server.hostname,
|
||||
addr: server.addr,
|
||||
@@ -319,7 +317,7 @@ const mapToSharedResource = (
|
||||
return {
|
||||
resource: {
|
||||
kind: 'db' as const,
|
||||
labels: database.labelsList,
|
||||
labels: database.labels,
|
||||
description: database.desc,
|
||||
name: database.name,
|
||||
type: formatDatabaseInfo(
|
||||
@@ -339,7 +337,7 @@ const mapToSharedResource = (
|
||||
return {
|
||||
resource: {
|
||||
kind: 'kube_cluster' as const,
|
||||
labels: kube.labelsList,
|
||||
labels: kube.labels,
|
||||
name: kube.name,
|
||||
},
|
||||
ui: {
|
||||
@@ -353,7 +351,7 @@ const mapToSharedResource = (
|
||||
return {
|
||||
resource: {
|
||||
kind: 'app' as const,
|
||||
labels: app.labelsList,
|
||||
labels: app.labels,
|
||||
name: app.name,
|
||||
id: app.name,
|
||||
addrWithProtocol: app.addrWithProtocol,
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
*/
|
||||
|
||||
import { renderHook, act } from '@testing-library/react';
|
||||
|
||||
import {
|
||||
ViewMode,
|
||||
DefaultTab,
|
||||
LabelsViewMode,
|
||||
} from 'shared/services/unifiedResourcePreferences';
|
||||
ViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import { makeRootCluster } from 'teleterm/services/tshd/testHelpers';
|
||||
import { MockAppContextProvider } from 'teleterm/ui/fixtures/MockAppContextProvider';
|
||||
@@ -33,11 +34,11 @@ import { useUserPreferences } from './useUserPreferences';
|
||||
|
||||
const cluster = makeRootCluster();
|
||||
const preferences: UserPreferences = {
|
||||
clusterPreferences: { pinnedResources: { resourceIdsList: ['abc'] } },
|
||||
clusterPreferences: { pinnedResources: { resourceIds: ['abc'] } },
|
||||
unifiedResourcePreferences: {
|
||||
viewMode: ViewMode.VIEW_MODE_CARD,
|
||||
defaultTab: DefaultTab.DEFAULT_TAB_ALL,
|
||||
labelsViewMode: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
viewMode: ViewMode.CARD,
|
||||
defaultTab: DefaultTab.ALL,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -140,9 +141,9 @@ describe('updating preferences', () => {
|
||||
const newPreferences: UserPreferences = {
|
||||
clusterPreferences: {},
|
||||
unifiedResourcePreferences: {
|
||||
viewMode: ViewMode.VIEW_MODE_LIST,
|
||||
defaultTab: DefaultTab.DEFAULT_TAB_PINNED,
|
||||
labelsViewMode: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
viewMode: ViewMode.LIST,
|
||||
defaultTab: DefaultTab.PINNED,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -201,9 +202,9 @@ describe('updating preferences', () => {
|
||||
const newPreferences: UserPreferences = {
|
||||
clusterPreferences: {},
|
||||
unifiedResourcePreferences: {
|
||||
viewMode: ViewMode.VIEW_MODE_LIST,
|
||||
defaultTab: DefaultTab.DEFAULT_TAB_PINNED,
|
||||
labelsViewMode: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
viewMode: ViewMode.LIST,
|
||||
defaultTab: DefaultTab.PINNED,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -232,11 +233,11 @@ describe('updating preferences', () => {
|
||||
// (e.g., because they were changed it in the browser in the meantime)
|
||||
act(() =>
|
||||
resolveUpdateUserPreferencesPromise({
|
||||
clusterPreferences: { pinnedResources: { resourceIdsList: ['abc'] } },
|
||||
clusterPreferences: { pinnedResources: { resourceIds: ['abc'] } },
|
||||
unifiedResourcePreferences: {
|
||||
viewMode: ViewMode.VIEW_MODE_CARD,
|
||||
defaultTab: DefaultTab.DEFAULT_TAB_PINNED,
|
||||
labelsViewMode: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
viewMode: ViewMode.CARD,
|
||||
defaultTab: DefaultTab.PINNED,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -248,7 +249,7 @@ describe('updating preferences', () => {
|
||||
);
|
||||
expect(
|
||||
result.current.userPreferences.clusterPreferences.pinnedResources
|
||||
.resourceIdsList
|
||||
.resourceIds
|
||||
).toEqual(['abc']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,10 +32,10 @@ import {
|
||||
|
||||
import {
|
||||
DefaultTab,
|
||||
ViewMode,
|
||||
UnifiedResourcePreferences,
|
||||
LabelsViewMode,
|
||||
} from 'shared/services/unifiedResourcePreferences';
|
||||
UnifiedResourcePreferences,
|
||||
ViewMode,
|
||||
} from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb';
|
||||
|
||||
import { useAppContext } from 'teleterm/ui/appContextProvider';
|
||||
|
||||
@@ -62,16 +62,16 @@ export function useUserPreferences(clusterUri: ClusterUri): {
|
||||
routing.ensureRootClusterUri(clusterUri)
|
||||
)
|
||||
) || {
|
||||
defaultTab: DefaultTab.DEFAULT_TAB_ALL,
|
||||
viewMode: ViewMode.VIEW_MODE_CARD,
|
||||
labelsViewMode: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
defaultTab: DefaultTab.ALL,
|
||||
viewMode: ViewMode.CARD,
|
||||
labelsViewMode: LabelsViewMode.COLLAPSED,
|
||||
}
|
||||
);
|
||||
const [clusterPreferences, setClusterPreferences] = useState<
|
||||
UserPreferences['clusterPreferences']
|
||||
>({
|
||||
// we pass an empty array, so pinning is enabled by default
|
||||
pinnedResources: { resourceIdsList: [] },
|
||||
pinnedResources: { resourceIds: [] },
|
||||
});
|
||||
|
||||
const [initialFetchAttempt, runInitialFetchAttempt] = useAsync(
|
||||
@@ -221,17 +221,16 @@ function mergeWithDefaultUnifiedResourcePreferences(
|
||||
return {
|
||||
defaultTab: unifiedResourcePreferences
|
||||
? unifiedResourcePreferences.defaultTab
|
||||
: DefaultTab.DEFAULT_TAB_ALL,
|
||||
: DefaultTab.ALL,
|
||||
viewMode:
|
||||
unifiedResourcePreferences &&
|
||||
unifiedResourcePreferences.viewMode !== ViewMode.VIEW_MODE_UNSPECIFIED
|
||||
unifiedResourcePreferences.viewMode !== ViewMode.UNSPECIFIED
|
||||
? unifiedResourcePreferences.viewMode
|
||||
: ViewMode.VIEW_MODE_CARD,
|
||||
: ViewMode.CARD,
|
||||
labelsViewMode:
|
||||
unifiedResourcePreferences &&
|
||||
unifiedResourcePreferences.labelsViewMode !==
|
||||
LabelsViewMode.LABELS_VIEW_MODE_UNSPECIFIED
|
||||
unifiedResourcePreferences.labelsViewMode !== LabelsViewMode.UNSPECIFIED
|
||||
? unifiedResourcePreferences.labelsViewMode
|
||||
: LabelsViewMode.LABELS_VIEW_MODE_COLLAPSED,
|
||||
: LabelsViewMode.COLLAPSED,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ import {
|
||||
createFileTransferEventsEmitter,
|
||||
} from 'shared/components/FileTransfer';
|
||||
|
||||
import { FileTransferDirection } from 'teleterm/services/tshd/types';
|
||||
import { FileTransferDirection } from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
|
||||
import { retryWithRelogin } from 'teleterm/ui/utils';
|
||||
import { useAppContext } from 'teleterm/ui/appContextProvider';
|
||||
import { IAppContext } from 'teleterm/ui/types';
|
||||
@@ -40,7 +41,7 @@ export function useTshFileTransferHandlers() {
|
||||
appContext,
|
||||
file,
|
||||
abortController,
|
||||
FileTransferDirection.FILE_TRANSFER_DIRECTION_UPLOAD
|
||||
FileTransferDirection.UPLOAD
|
||||
);
|
||||
},
|
||||
download(
|
||||
@@ -51,7 +52,7 @@ export function useTshFileTransferHandlers() {
|
||||
appContext,
|
||||
file,
|
||||
abortController,
|
||||
FileTransferDirection.FILE_TRANSFER_DIRECTION_DOWNLOAD
|
||||
FileTransferDirection.DOWNLOAD
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -20,11 +20,11 @@ import React, { useRef, useEffect } from 'react';
|
||||
|
||||
import { useAsync } from 'shared/hooks/useAsync';
|
||||
|
||||
import { HeadlessAuthenticationState } from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
|
||||
import { useAppContext } from 'teleterm/ui/appContextProvider';
|
||||
import { RootClusterUri } from 'teleterm/ui/uri';
|
||||
|
||||
import { HeadlessAuthenticationState } from 'teleterm/services/tshd/types';
|
||||
|
||||
import { HeadlessPrompt } from './HeadlessPrompt';
|
||||
|
||||
interface HeadlessAuthenticationProps {
|
||||
@@ -55,7 +55,7 @@ export function HeadlessAuthentication(props: HeadlessAuthenticationProps) {
|
||||
|
||||
async function handleHeadlessApprove(): Promise<void> {
|
||||
const [, error] = await updateHeadlessState(
|
||||
HeadlessAuthenticationState.HEADLESS_AUTHENTICATION_STATE_APPROVED
|
||||
HeadlessAuthenticationState.APPROVED
|
||||
);
|
||||
if (!error) {
|
||||
props.onSuccess();
|
||||
@@ -64,7 +64,7 @@ export function HeadlessAuthentication(props: HeadlessAuthenticationProps) {
|
||||
|
||||
async function handleHeadlessReject(): Promise<void> {
|
||||
const [, error] = await updateHeadlessState(
|
||||
HeadlessAuthenticationState.HEADLESS_AUTHENTICATION_STATE_DENIED
|
||||
HeadlessAuthenticationState.DENIED
|
||||
);
|
||||
if (!error) {
|
||||
props.onSuccess();
|
||||
|
||||
@@ -65,7 +65,7 @@ export function mapToAction(
|
||||
parameter: {
|
||||
getSuggestions: async () =>
|
||||
ctx.clustersService.findClusterByResource(result.resource.uri)
|
||||
?.loggedInUser?.sshLoginsList,
|
||||
?.loggedInUser?.sshLogins,
|
||||
placeholder: 'Provide login',
|
||||
},
|
||||
perform: login => {
|
||||
|
||||
@@ -966,7 +966,7 @@ function Labels(
|
||||
scoreMap.set(match.labelName, currentScore + match.score);
|
||||
});
|
||||
|
||||
const sortedLabelsList = [...searchResult.resource.labelsList];
|
||||
const sortedLabelsList = [...searchResult.resource.labels];
|
||||
sortedLabelsList.sort(
|
||||
(a, b) =>
|
||||
// Highest score first.
|
||||
|
||||
@@ -110,7 +110,7 @@ const SearchResultItems = () => {
|
||||
hostname: 'long-label-list',
|
||||
uri: `${clusterUri}/servers/2f96e498-88ec-442f-a25b-569fa915041c`,
|
||||
name: '2f96e498-88ec-442f-a25b-569fa915041c',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
arch: 'aarch64',
|
||||
external: '32.192.113.93',
|
||||
internal: '10.0.0.175',
|
||||
@@ -127,7 +127,7 @@ const SearchResultItems = () => {
|
||||
tunnel: true,
|
||||
uri: `${clusterUri}/servers/90a29595-aac7-42eb-a484-c6c0e23f1a21`,
|
||||
name: '90a29595-aac7-42eb-a484-c6c0e23f1a21',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
arch: 'aarch64',
|
||||
service: 'ansible',
|
||||
external: '32.192.113.93',
|
||||
@@ -144,7 +144,7 @@ const SearchResultItems = () => {
|
||||
tunnel: true,
|
||||
uri: `${clusterUri}/servers/bbaaceba-6bd1-4750-9d3d-1a80e0cc8a63`,
|
||||
name: 'bbaaceba-6bd1-4750-9d3d-1a80e0cc8a63',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
internal: '10.0.0.175',
|
||||
service: 'ansible',
|
||||
external: '32.192.113.93',
|
||||
@@ -158,7 +158,7 @@ const SearchResultItems = () => {
|
||||
hostname:
|
||||
'super-long-server-name-with-uuid-2f96e498-88ec-442f-a25b-569fa915041c',
|
||||
uri: `${longClusterUri}/servers/super-long-desc`,
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
internal: '10.0.0.175',
|
||||
service: 'ansible',
|
||||
external: '32.192.113.93',
|
||||
@@ -172,7 +172,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/apps/no-desc`,
|
||||
name: 'no-desc',
|
||||
desc: '',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
access: 'cloudwatch-metrics,ec2,s3,cloudtrail',
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Owner': 'foobar',
|
||||
@@ -187,7 +187,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/apps/short-desc`,
|
||||
name: 'short-desc',
|
||||
desc: 'Lorem ipsum',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
access: 'cloudwatch-metrics,ec2,s3,cloudtrail',
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Owner': 'foobar',
|
||||
@@ -202,7 +202,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/apps/long-desc`,
|
||||
name: 'long-desc',
|
||||
desc: 'Eget dignissim lectus nisi vitae nunc',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
access: 'cloudwatch-metrics,ec2,s3,cloudtrail',
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Owner': 'foobar',
|
||||
@@ -217,7 +217,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/apps/super-long-desc`,
|
||||
name: 'super-long-desc',
|
||||
desc: 'Duis id tortor at purus tincidunt finibus. Mauris eu semper orci, non commodo lacus. Praesent sollicitudin magna id laoreet porta. Nunc lobortis varius sem vel fringilla.',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
access: 'cloudwatch-metrics,ec2,s3,cloudtrail',
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Owner': 'foobar',
|
||||
@@ -232,7 +232,7 @@ const SearchResultItems = () => {
|
||||
name: 'super-long-app-with-uuid-1f96e498-88ec-442f-a25b-569fa915041c',
|
||||
desc: 'short-desc',
|
||||
uri: `${longClusterUri}/apps/super-long-desc`,
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
access: 'cloudwatch-metrics,ec2,s3,cloudtrail',
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Owner': 'foobar',
|
||||
@@ -248,7 +248,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/dbs/no-desc`,
|
||||
name: 'no-desc',
|
||||
desc: '',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'aws/Accounting': 'dev-ops',
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Name': 'db-bastion-4-13biz',
|
||||
@@ -266,7 +266,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/dbs/short-desc`,
|
||||
name: 'short-desc',
|
||||
desc: 'Lorem ipsum',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Name': 'db-bastion-4-13biz',
|
||||
'aws/Accounting': 'dev-ops',
|
||||
@@ -284,7 +284,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/dbs/long-desc`,
|
||||
name: 'long-desc',
|
||||
desc: 'Eget dignissim lectus nisi vitae nunc',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Name': 'db-bastion-4-13biz',
|
||||
'aws/Accounting': 'dev-ops',
|
||||
@@ -302,7 +302,7 @@ const SearchResultItems = () => {
|
||||
uri: `${clusterUri}/dbs/super-long-desc`,
|
||||
name: 'super-long-desc',
|
||||
desc: 'Duis id tortor at purus tincidunt finibus. Mauris eu semper orci, non commodo lacus. Praesent sollicitudin magna id laoreet porta. Nunc lobortis varius sem vel fringilla.',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Accounting': 'dev-ops',
|
||||
'aws/Name': 'db-bastion-4-13biz',
|
||||
@@ -319,7 +319,7 @@ const SearchResultItems = () => {
|
||||
resource: makeDatabase({
|
||||
name: 'super-long-server-db-with-uuid-2f96e498-88ec-442f-a25b-569fa915041c',
|
||||
uri: `${longClusterUri}/dbs/super-long-desc`,
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Accounting': 'dev-ops',
|
||||
'aws/Name': 'db-bastion-4-13biz',
|
||||
@@ -335,7 +335,7 @@ const SearchResultItems = () => {
|
||||
kind: 'kube',
|
||||
resource: makeKube({
|
||||
name: 'short-label-list',
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'im-just-a-smol': 'kube',
|
||||
kube: 'kubersson',
|
||||
with: 'little-to-no-labels',
|
||||
@@ -347,7 +347,7 @@ const SearchResultItems = () => {
|
||||
resource: makeKube({
|
||||
name: 'long-label-list',
|
||||
uri: `${clusterUri}/kubes/long-label-list`,
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'aws/Environment': 'demo-13-biz',
|
||||
'aws/Owner': 'foobar',
|
||||
'aws/Name': 'db-bastion-4-13biz',
|
||||
@@ -361,7 +361,7 @@ const SearchResultItems = () => {
|
||||
resource: makeKube({
|
||||
name: 'super-long-kube-name-with-uuid-2f96e498-88ec-442f-a25b-569fa915041c',
|
||||
uri: `/clusters/teleport-very-long-cluster-name-with-uuid-2f96e498-88ec-442f-a25b-569fa915041c/kubes/super-long-desc`,
|
||||
labelsList: makeLabelsList({
|
||||
labels: makeLabelsList({
|
||||
'im-just-a-smol': 'kube',
|
||||
kube: 'kubersson',
|
||||
with: 'little-to-no-labels',
|
||||
|
||||
@@ -109,10 +109,7 @@ export const mainResourceField: {
|
||||
// fields of string type.
|
||||
export const searchableFields: {
|
||||
[Kind in ResourceSearchResult['kind']]: ReadonlyArray<
|
||||
Exclude<
|
||||
keyof resourcesServiceTypes.SearchResultResource<Kind>,
|
||||
'labelsList'
|
||||
>
|
||||
Exclude<keyof resourcesServiceTypes.SearchResultResource<Kind>, 'labels'>
|
||||
>;
|
||||
} = {
|
||||
server: ['name', 'hostname', 'addr'],
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('rankResults', () => {
|
||||
const server = makeResourceResult({
|
||||
kind: 'server',
|
||||
resource: makeServer({
|
||||
labelsList: makeLabelsList({ quux: 'bar-baz', foo: 'bar' }),
|
||||
labels: makeLabelsList({ quux: 'bar-baz', foo: 'bar' }),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('rankResults', () => {
|
||||
makeResourceResult({
|
||||
kind: 'server',
|
||||
resource: makeServer({
|
||||
labelsList: makeLabelsList({ foo: 'bar1' }),
|
||||
labels: makeLabelsList({ foo: 'bar1' }),
|
||||
}),
|
||||
})
|
||||
);
|
||||
@@ -99,7 +99,7 @@ describe('rankResults', () => {
|
||||
kind: 'server',
|
||||
resource: makeServer({
|
||||
uri: lowestScoreServerUri,
|
||||
labelsList: makeLabelsList({ foo: 'bar123456' }),
|
||||
labels: makeLabelsList({ foo: 'bar123456' }),
|
||||
}),
|
||||
})
|
||||
);
|
||||
@@ -111,7 +111,7 @@ describe('rankResults', () => {
|
||||
kind: 'server',
|
||||
resource: makeServer({
|
||||
uri: highestScoreServerUri,
|
||||
labelsList: makeLabelsList({ foo: 'bar' }),
|
||||
labels: makeLabelsList({ foo: 'bar' }),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -277,7 +277,7 @@ function populateMatches(
|
||||
const resourceMatches: ResourceMatch<ResourceSearchResult['kind']>[] = [];
|
||||
|
||||
terms.forEach(term => {
|
||||
searchResult.resource.labelsList.forEach(label => {
|
||||
searchResult.resource.labels.forEach(label => {
|
||||
// indexOf is faster on Chrome than includes or regex.
|
||||
// https://jsbench.me/b7lf9kvrux/1
|
||||
const nameIndex = label.name.toLocaleLowerCase().indexOf(term);
|
||||
@@ -328,7 +328,7 @@ function calculateScore(
|
||||
let searchResultScore = 0;
|
||||
|
||||
const labelMatches = searchResult.labelMatches.map(match => {
|
||||
const label = searchResult.resource.labelsList.find(
|
||||
const label = searchResult.resource.labels.find(
|
||||
label => label.name === match.labelName
|
||||
);
|
||||
let matchedValue: string;
|
||||
|
||||
@@ -97,8 +97,8 @@ export function OneClusterWithActiveCluster() {
|
||||
proxyHost: 'localhost:3080',
|
||||
loggedInUser: makeLoggedInUser({
|
||||
name: 'alice',
|
||||
rolesList: ['access', 'editor'],
|
||||
sshLoginsList: ['root'],
|
||||
roles: ['access', 'editor'],
|
||||
sshLogins: ['root'],
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -183,8 +183,8 @@ export function ManyClustersWithActiveCluster() {
|
||||
proxyHost: 'localhost:3080',
|
||||
loggedInUser: makeLoggedInUser({
|
||||
name: activeIdentityRootCluster.userName,
|
||||
rolesList: ['access', 'editor'],
|
||||
sshLoginsList: ['root'],
|
||||
roles: ['access', 'editor'],
|
||||
sshLogins: ['root'],
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -234,7 +234,7 @@ export function LongNamesWithManyRoles() {
|
||||
proxyHost: 'localhost:3080',
|
||||
loggedInUser: makeLoggedInUser({
|
||||
name: activeIdentityRootCluster.userName,
|
||||
rolesList: [
|
||||
roles: [
|
||||
'circle-mark-app-access',
|
||||
'grafana-lite-app-access',
|
||||
'grafana-gold-app-access',
|
||||
@@ -245,7 +245,7 @@ export function LongNamesWithManyRoles() {
|
||||
'sales-center-shop-app-access',
|
||||
'sales-center-floor-db-access',
|
||||
],
|
||||
sshLoginsList: ['root'],
|
||||
sshLogins: ['root'],
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ export function IdentityList(props: IdentityListProps) {
|
||||
<Box>
|
||||
<Text bold>{props.loggedInUser.name}</Text>
|
||||
<Flex flexWrap="wrap" gap={1}>
|
||||
{props.loggedInUser.rolesList.map(role => (
|
||||
{props.loggedInUser.roles.map(role => (
|
||||
<Label key={role} kind="secondary">
|
||||
{role}
|
||||
</Label>
|
||||
|
||||
@@ -177,6 +177,7 @@ export class ClustersService extends ImmutableStore<types.ClustersServiceState>
|
||||
clusters.map(c => [c.uri, this.removeInternalLoginsFromCluster(c)])
|
||||
);
|
||||
});
|
||||
|
||||
clusters
|
||||
.filter(c => c.connected)
|
||||
.forEach(c => this.syncRootClusterAndCatchErrors(c.uri));
|
||||
@@ -520,7 +521,7 @@ export class ClustersService extends ImmutableStore<types.ClustersServiceState>
|
||||
// TODO: this information should eventually be gathered by getCluster
|
||||
const assumedRequests = cluster.loggedInUser
|
||||
? await this.fetchClusterAssumedRequests(
|
||||
cluster.loggedInUser.activeRequestsList,
|
||||
cluster.loggedInUser.activeRequests,
|
||||
clusterUri
|
||||
)
|
||||
: undefined;
|
||||
@@ -555,7 +556,7 @@ export class ClustersService extends ImmutableStore<types.ClustersServiceState>
|
||||
requestsMap[request.id] = {
|
||||
id: request.id,
|
||||
expires: new Date(request.expires.seconds * 1000),
|
||||
roles: request.rolesList,
|
||||
roles: request.roles,
|
||||
};
|
||||
return requestsMap;
|
||||
}, {});
|
||||
@@ -569,7 +570,7 @@ export class ClustersService extends ImmutableStore<types.ClustersServiceState>
|
||||
...cluster,
|
||||
loggedInUser: cluster.loggedInUser && {
|
||||
...cluster.loggedInUser,
|
||||
sshLoginsList: cluster.loggedInUser.sshLoginsList.filter(
|
||||
sshLogins: cluster.loggedInUser.sshLogins.filter(
|
||||
login => !login.startsWith('-')
|
||||
),
|
||||
},
|
||||
@@ -583,7 +584,7 @@ export function makeServer(source: tsh.Server) {
|
||||
id: source.name,
|
||||
clusterId: source.name,
|
||||
hostname: source.hostname,
|
||||
labels: source.labelsList,
|
||||
labels: source.labels,
|
||||
addr: source.addr,
|
||||
tunnel: source.tunnel,
|
||||
sshLogins: [],
|
||||
@@ -600,7 +601,7 @@ export function makeDatabase(source: tsh.Database) {
|
||||
source.protocol as DbProtocol
|
||||
).title,
|
||||
protocol: source.protocol,
|
||||
labels: source.labelsList,
|
||||
labels: source.labels,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -608,7 +609,7 @@ export function makeKube(source: tsh.Kube) {
|
||||
return {
|
||||
uri: source.uri,
|
||||
name: source.name,
|
||||
labels: source.labelsList,
|
||||
labels: source.labels,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,9 @@
|
||||
|
||||
import { FileTransferListeners } from 'shared/components/FileTransfer';
|
||||
|
||||
import {
|
||||
FileTransferDirection,
|
||||
FileTransferRequest,
|
||||
TshdClient,
|
||||
} from 'teleterm/services/tshd/types';
|
||||
import { FileTransferDirection } from 'gen-proto-ts/teleport/lib/teleterm/v1/service_pb';
|
||||
|
||||
import { FileTransferRequest, TshdClient } from 'teleterm/services/tshd/types';
|
||||
import { UsageService } from 'teleterm/ui/services/usage';
|
||||
|
||||
export class FileTransferService {
|
||||
@@ -52,17 +50,12 @@ export class FileTransferService {
|
||||
{ once: true }
|
||||
);
|
||||
const listeners = this.tshClient.transferFile(options, abortSignal);
|
||||
if (
|
||||
options.direction ===
|
||||
FileTransferDirection.FILE_TRANSFER_DIRECTION_DOWNLOAD
|
||||
) {
|
||||
if (options.direction === FileTransferDirection.DOWNLOAD) {
|
||||
this.usageService.captureFileTransferRun(options.serverUri, {
|
||||
isUpload: false,
|
||||
});
|
||||
}
|
||||
if (
|
||||
options.direction === FileTransferDirection.FILE_TRANSFER_DIRECTION_UPLOAD
|
||||
) {
|
||||
if (options.direction === FileTransferDirection.UPLOAD) {
|
||||
this.usageService.captureFileTransferRun(options.serverUri, {
|
||||
isUpload: true,
|
||||
});
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('getServerByHostname', () => {
|
||||
{
|
||||
name: 'returns a server when the hostname matches a single server',
|
||||
getServersMockedValue: {
|
||||
agentsList: [server],
|
||||
agents: [server],
|
||||
totalCount: 1,
|
||||
startKey: 'foo',
|
||||
},
|
||||
@@ -54,7 +54,7 @@ describe('getServerByHostname', () => {
|
||||
{
|
||||
name: 'throws an error when the hostname matches multiple servers',
|
||||
getServersMockedValue: {
|
||||
agentsList: [server, server],
|
||||
agents: [server, server],
|
||||
totalCount: 2,
|
||||
startKey: 'foo',
|
||||
},
|
||||
@@ -63,7 +63,7 @@ describe('getServerByHostname', () => {
|
||||
{
|
||||
name: 'returns nothing if the hostname does not match any servers',
|
||||
getServersMockedValue: {
|
||||
agentsList: [],
|
||||
agents: [],
|
||||
totalCount: 0,
|
||||
startKey: 'foo',
|
||||
},
|
||||
@@ -107,22 +107,22 @@ describe('searchResources', () => {
|
||||
|
||||
const tshClient: Partial<tsh.TshdClient> = {
|
||||
getServers: jest.fn().mockResolvedValueOnce({
|
||||
agentsList: [server],
|
||||
agents: [server],
|
||||
totalCount: 1,
|
||||
startKey: '',
|
||||
}),
|
||||
getDatabases: jest.fn().mockResolvedValueOnce({
|
||||
agentsList: [db],
|
||||
agents: [db],
|
||||
totalCount: 1,
|
||||
startKey: '',
|
||||
}),
|
||||
getKubes: jest.fn().mockResolvedValueOnce({
|
||||
agentsList: [kube],
|
||||
agents: [kube],
|
||||
totalCount: 1,
|
||||
startKey: '',
|
||||
}),
|
||||
getApps: jest.fn().mockResolvedValueOnce({
|
||||
agentsList: [app],
|
||||
agents: [app],
|
||||
totalCount: 1,
|
||||
startKey: '',
|
||||
}),
|
||||
@@ -161,7 +161,7 @@ describe('searchResources', () => {
|
||||
const server = makeServer();
|
||||
const tshClient: Partial<tsh.TshdClient> = {
|
||||
getServers: jest.fn().mockResolvedValueOnce({
|
||||
agentsList: [server],
|
||||
agents: [server],
|
||||
totalCount: 1,
|
||||
startKey: '',
|
||||
}),
|
||||
|
||||
@@ -38,7 +38,7 @@ export class ResourcesService {
|
||||
hostname: string
|
||||
): Promise<types.Server | undefined> {
|
||||
const query = `name == "${hostname}"`;
|
||||
const { agentsList: servers } = await this.fetchServers({
|
||||
const { agents: servers } = await this.fetchServers({
|
||||
clusterUri,
|
||||
query,
|
||||
limit: 2,
|
||||
@@ -94,7 +94,7 @@ export class ResourcesService {
|
||||
const getServers = () =>
|
||||
this.fetchServers(params).then(
|
||||
res =>
|
||||
res.agentsList.map(resource => ({
|
||||
res.agents.map(resource => ({
|
||||
kind: 'server' as const,
|
||||
resource,
|
||||
})),
|
||||
@@ -104,7 +104,7 @@ export class ResourcesService {
|
||||
const getApps = () =>
|
||||
this.fetchApps(params).then(
|
||||
res =>
|
||||
res.agentsList.map(resource => ({
|
||||
res.agents.map(resource => ({
|
||||
kind: 'app' as const,
|
||||
resource: makeApp(resource),
|
||||
})),
|
||||
@@ -113,7 +113,7 @@ export class ResourcesService {
|
||||
const getDatabases = () =>
|
||||
this.fetchDatabases(params).then(
|
||||
res =>
|
||||
res.agentsList.map(resource => ({
|
||||
res.agents.map(resource => ({
|
||||
kind: 'database' as const,
|
||||
resource,
|
||||
})),
|
||||
@@ -123,7 +123,7 @@ export class ResourcesService {
|
||||
const getKubes = () =>
|
||||
this.fetchKubes(params).then(
|
||||
res =>
|
||||
res.agentsList.map(resource => ({
|
||||
res.agents.map(resource => ({
|
||||
kind: 'kube' as const,
|
||||
resource,
|
||||
})),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user