Skip to content

Commit

Permalink
chore: Add NTLM Credentials support (#2710)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanfbrito authored Aug 3, 2023
1 parent 193e6e4 commit ec21350
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 5 deletions.
14 changes: 11 additions & 3 deletions src/app/PersistableValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ type PersistableValues_3_8_12 = PersistableValues_3_8_9 & {
hasHideOnTrayNotificationShown: boolean;
};

type PersistableValues_3_9_5 = PersistableValues_3_8_12 & {
type PersistableValues_3_9_6 = PersistableValues_3_8_12 & {
lastSelectedServerUrl: string;
allowedNTLMCredentialsDomains: string | null;
isNTLMCredentialsEnabled: boolean;
};

export type PersistableValues = Pick<
PersistableValues_3_9_5,
keyof PersistableValues_3_9_5
PersistableValues_3_9_6,
keyof PersistableValues_3_9_6
>;

export const migrations = {
Expand Down Expand Up @@ -113,4 +115,10 @@ export const migrations = {
...before,
hasHideOnTrayNotificationShown: false,
}),
'>=3.9.6': (before: PersistableValues_3_8_12): PersistableValues_3_9_6 => ({
...before,
isNTLMCredentialsEnabled: false,
allowedNTLMCredentialsDomains: null,
lastSelectedServerUrl: '',
}),
};
3 changes: 3 additions & 0 deletions src/app/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ export const APP_ERROR_THROWN = 'app/error-thrown';
export const APP_PATH_SET = 'app/path-set';
export const APP_VERSION_SET = 'app/version-set';
export const APP_SETTINGS_LOADED = 'app/settings-loaded';
export const APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET =
'app/allowed-ntlm-credentials-domains-set';

export type AppActionTypeToPayloadMap = {
[APP_ERROR_THROWN]: Error;
[APP_PATH_SET]: string;
[APP_VERSION_SET]: string;
[APP_SETTINGS_LOADED]: Partial<PersistableValues>;
[APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET]: string;
};
45 changes: 43 additions & 2 deletions src/app/main/app.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app } from 'electron';
import { app, session } from 'electron';
import rimraf from 'rimraf';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand All @@ -14,11 +14,16 @@ import { dispatch, listen } from '../../store';
import { readSetting } from '../../store/readSetting';
import {
SETTINGS_CLEAR_PERMITTED_SCREEN_CAPTURE_PERMISSIONS,
SETTINGS_NTLM_CREDENTIALS_CHANGED,
SETTINGS_SET_HARDWARE_ACCELERATION_OPT_IN_CHANGED,
} from '../../ui/actions';
import { askForClearScreenCapturePermission } from '../../ui/main/dialogs';
import { getRootWindow } from '../../ui/main/rootWindow';
import { APP_PATH_SET, APP_VERSION_SET } from '../actions';
import {
APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET,
APP_PATH_SET,
APP_VERSION_SET,
} from '../actions';

export const packageJsonInformation = {
productName: packageJson.productName,
Expand Down Expand Up @@ -94,6 +99,29 @@ export const setupApp = (): void => {
relaunchApp();
});

listen(APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET, (action) => {
if (action.payload.length > 0) {
session.defaultSession.allowNTLMCredentialsForDomains(action.payload);
}
});

listen(SETTINGS_NTLM_CREDENTIALS_CHANGED, (action) => {
if (action.payload === true) {
const allowedNTLMCredentialsDomains = readSetting(
'allowedNTLMCredentialsDomains'
);
if (allowedNTLMCredentialsDomains) {
console.log('Setting NTLM credentials', allowedNTLMCredentialsDomains);
session.defaultSession.allowNTLMCredentialsForDomains(
allowedNTLMCredentialsDomains
);
}
} else {
console.log('Clearing NTLM credentials');
session.defaultSession.allowNTLMCredentialsForDomains('');
}
});

listen(
SETTINGS_CLEAR_PERMITTED_SCREEN_CAPTURE_PERMISSIONS,
async (_action) => {
Expand All @@ -108,6 +136,19 @@ export const setupApp = (): void => {
}
);

const allowedNTLMCredentialsDomains = readSetting(
'allowedNTLMCredentialsDomains'
);

const isNTLMCredentialsEnabled = readSetting('isNTLMCredentialsEnabled');

if (isNTLMCredentialsEnabled && allowedNTLMCredentialsDomains.length > 0) {
console.log('Setting NTLM credentials', allowedNTLMCredentialsDomains);
session.defaultSession.allowNTLMCredentialsForDomains(
allowedNTLMCredentialsDomains
);
}

dispatch({ type: APP_PATH_SET, payload: app.getAppPath() });
dispatch({ type: APP_VERSION_SET, payload: app.getVersion() });
};
31 changes: 31 additions & 0 deletions src/app/reducers/allowedNTLMCredentialsDomains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Reducer } from 'redux';

import type { ActionOf } from '../../store/actions';
import {
APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET,
APP_SETTINGS_LOADED,
} from '../actions';

type allowedNTLMCredentialsDomainsAction =
| ActionOf<typeof APP_SETTINGS_LOADED>
| ActionOf<typeof APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET>;

export const allowedNTLMCredentialsDomains: Reducer<
string | null,
allowedNTLMCredentialsDomainsAction
> = (state = null, action) => {
switch (action.type) {
case APP_SETTINGS_LOADED: {
const { allowedNTLMCredentialsDomains = state } = action.payload;
return allowedNTLMCredentialsDomains;
}

case APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET: {
if (action.payload === null) return null;
return action.payload;
}

default:
return state;
}
};
4 changes: 4 additions & 0 deletions src/app/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ export const selectPersistableValues = createStructuredSelector<
hasHideOnTrayNotificationShown: ({ hasHideOnTrayNotificationShown }) =>
hasHideOnTrayNotificationShown,
lastSelectedServerUrl: ({ lastSelectedServerUrl }) => lastSelectedServerUrl,
allowedNTLMCredentialsDomains: ({ allowedNTLMCredentialsDomains }) =>
allowedNTLMCredentialsDomains,
isNTLMCredentialsEnabled: ({ isNTLMCredentialsEnabled }) =>
isNTLMCredentialsEnabled,
});
9 changes: 9 additions & 0 deletions src/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@
"clearPermittedScreenCaptureServers": {
"title": "Clear Screen Capture Permissions",
"description": "Clear the screen capture permissions that was selected to not ask again on video calls."
},
"allowScreenCaptureOnVideoCalls": {
"title": "Allow Screen Capture on Video Calls",
"description": "Allow screen capture on video calls. This will ask for permission on each video call."
},
"ntlmCredentials": {
"title": "NTLM Credentials",
"description": "Allow NTLM Credentials to be used when connecting to a server.",
"domains": "Domains that will use the credentials. Separated by comma. Use * to match all domains."
}
}
},
Expand Down
13 changes: 13 additions & 0 deletions src/i18n/pt-BR.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,19 @@
"trayIcon": {
"title": "Ícone da bandeja",
"description": "Mostra um ícone na bandeja do sistema para acessar rapidamente a aplicação. Se o ícone da bandeja estiver ativado, a aplicação será minimizada para a barra de tarefas ao ser fechada. Por outro lado se o ícone da bandeja estiver desativado, a aplicação será finalizada ao ser fechada."
},
"clearPermittedScreenCaptureServers": {
"title": "Limpar Permissões de Captura de Tela",
"description": "Limpar as permissões de captura de tela que foram selecionadas para não perguntar novamente em chamadas de vídeo."
},
"allowScreenCaptureOnVideoCalls": {
"title": "Permitir Captura de Tela em Chamadas de Vídeo",
"description": "Permitir captura de tela em chamadas de vídeo. Isso solicitará permissão em cada chamada de vídeo."
},
"ntlmCredentials": {
"title": "Credenciais NTLM",
"description": "Permitir o uso de credenciais NTLM ao conectar-se a um servidor.",
"domains": "Domínios que usarão as credenciais. Separados por vírgula. Use * para permitir todos os domínios."
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions src/store/rootReducer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { combineReducers } from 'redux';

import { allowedNTLMCredentialsDomains } from '../app/reducers/allowedNTLMCredentialsDomains';
import { appPath } from '../app/reducers/appPath';
import { appVersion } from '../app/reducers/appVersion';
import { downloads } from '../downloads/reducers/downloads';
Expand All @@ -20,6 +21,7 @@ import { isInternalVideoChatWindowEnabled } from '../ui/reducers/isInternalVideo
import { isMenuBarEnabled } from '../ui/reducers/isMenuBarEnabled';
import { isMessageBoxFocused } from '../ui/reducers/isMessageBoxFocused';
import { isMinimizeOnCloseEnabled } from '../ui/reducers/isMinimizeOnCloseEnabled';
import { isNTLMCredentialsEnabled } from '../ui/reducers/isNTLMCredentialsEnabled';
import { isReportEnabled } from '../ui/reducers/isReportEnabled';
import { isShowWindowOnUnreadChangedEnabled } from '../ui/reducers/isShowWindowOnUnreadChangedEnabled';
import { isSideBarEnabled } from '../ui/reducers/isSideBarEnabled';
Expand Down Expand Up @@ -74,6 +76,8 @@ export const rootReducer = combineReducers({
isAddNewServersEnabled,
hasHideOnTrayNotificationShown,
lastSelectedServerUrl,
allowedNTLMCredentialsDomains,
isNTLMCredentialsEnabled,
});

export type RootState = ReturnType<typeof rootReducer>;
3 changes: 3 additions & 0 deletions src/ui/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ export const SETTINGS_SET_IS_MENU_BAR_ENABLED_CHANGED =
'settings/set-is-menu-bar-enabled-changed';
export const SETTINGS_CLEAR_PERMITTED_SCREEN_CAPTURE_PERMISSIONS =
'settings/clear-permitted-screen-capture-permissions';
export const SETTINGS_NTLM_CREDENTIALS_CHANGED =
'settings/ntlm-credentials-changed';
export const SET_HAS_TRAY_MINIMIZE_NOTIFICATION_SHOWN =
'notifications/set-has-tray-minimize-notification-shown';
export const VIDEO_CALL_WINDOW_OPEN_URL = 'video-call-window/open-url';
Expand Down Expand Up @@ -163,6 +165,7 @@ export type UiActionTypeToPayloadMap = {
[SETTINGS_SET_IS_MENU_BAR_ENABLED_CHANGED]: boolean;
[SETTINGS_CLEAR_PERMITTED_SCREEN_CAPTURE_PERMISSIONS]: void;
[SET_HAS_TRAY_MINIMIZE_NOTIFICATION_SHOWN]: boolean;
[SETTINGS_NTLM_CREDENTIALS_CHANGED]: boolean;
[VIDEO_CALL_WINDOW_OPEN_URL]: { url: string };
[DOWNLOADS_BACK_BUTTON_CLICKED]: string;
};
2 changes: 2 additions & 0 deletions src/ui/components/SettingsView/GeneralTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HardwareAcceleration } from './features/HardwareAcceleration';
import { InternalVideoChatWindow } from './features/InternalVideoChatWindow';
import { MenuBar } from './features/MenuBar';
import { MinimizeOnClose } from './features/MinimizeOnClose';
import { NTLMCredentials } from './features/NTLMCredentials';
import { ReportErrors } from './features/ReportErrors';
import { SideBar } from './features/SideBar';
import { TrayIcon } from './features/TrayIcon';
Expand All @@ -23,6 +24,7 @@ export const GeneralTab: FC = () => (
{process.platform === 'win32' && <MinimizeOnClose />}
<SideBar />
{process.platform !== 'darwin' && <MenuBar />}
<NTLMCredentials />
{!process.mas && <ClearPermittedScreenCaptureServers />}
</FieldGroup>
</Box>
Expand Down
85 changes: 85 additions & 0 deletions src/ui/components/SettingsView/features/NTLMCredentials.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Field, InputBox, ToggleSwitch } from '@rocket.chat/fuselage';
import React, {
useCallback,
type ChangeEvent,
type Dispatch,
type FC,
} from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';

import { APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET } from '../../../../app/actions';
import type { RootAction } from '../../../../store/actions';
import type { RootState } from '../../../../store/rootReducer';
import { SETTINGS_NTLM_CREDENTIALS_CHANGED } from '../../../actions';

type Props = {
className?: string;
};

export const NTLMCredentials: FC<Props> = (props) => {
const isNTLMCredentialsEnabled = useSelector(
({ isNTLMCredentialsEnabled }: RootState) => isNTLMCredentialsEnabled
);
const allowedNTLMCredentialsDomains = useSelector(
({ allowedNTLMCredentialsDomains }: RootState) =>
allowedNTLMCredentialsDomains
);
const { t } = useTranslation();
const dispatch = useDispatch<Dispatch<RootAction>>();

const handleToggleChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
const isChecked = event.currentTarget.checked;
dispatch({
type: SETTINGS_NTLM_CREDENTIALS_CHANGED,
payload: isChecked,
});
},
[dispatch]
);

const handleDomainsChange = useCallback(
(event: React.FocusEvent<HTMLInputElement>) => {
const domains = event.target.value;
dispatch({
type: APP_ALLOWED_NTLM_CREDENTIALS_DOMAINS_SET,
payload: domains,
});
},
[dispatch]
);

return (
<Field className={props.className}>
<Field.Row>
<ToggleSwitch
onChange={handleToggleChange}
checked={isNTLMCredentialsEnabled}
/>
<Field.Label htmlFor='toggle-switch'>
{t('settings.options.ntlmCredentials.title')}
</Field.Label>
</Field.Row>
<Field.Row>
<Field.Hint>
{t('settings.options.ntlmCredentials.description')}
</Field.Hint>
</Field.Row>
<Field.Row>
<Field.Row size={'100%'}>
<InputBox
defaultValue={allowedNTLMCredentialsDomains as string}
onBlur={handleDomainsChange}
type={'text'}
disabled={!isNTLMCredentialsEnabled}
placeholder='*example.com, *foobar.com, *baz'
/>
</Field.Row>
</Field.Row>
<Field.Row>
<Field.Hint>{t('settings.options.ntlmCredentials.domains')}</Field.Hint>
</Field.Row>
</Field>
);
};
28 changes: 28 additions & 0 deletions src/ui/reducers/isNTLMCredentialsEnabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { Reducer } from 'redux';

import { APP_SETTINGS_LOADED } from '../../app/actions';
import type { ActionOf } from '../../store/actions';
import { SETTINGS_NTLM_CREDENTIALS_CHANGED } from '../actions';

type isNTLMCredentialsEnabledAction =
| ActionOf<typeof APP_SETTINGS_LOADED>
| ActionOf<typeof SETTINGS_NTLM_CREDENTIALS_CHANGED>;

export const isNTLMCredentialsEnabled: Reducer<
boolean,
isNTLMCredentialsEnabledAction
> = (state = false, action) => {
switch (action.type) {
case APP_SETTINGS_LOADED: {
const { isNTLMCredentialsEnabled = state } = action.payload;
return isNTLMCredentialsEnabled;
}

case SETTINGS_NTLM_CREDENTIALS_CHANGED: {
return action.payload;
}

default:
return state;
}
};

0 comments on commit ec21350

Please sign in to comment.