Skip to content

Commit

Permalink
Fixed opting out of frontdoor login or some actions
Browse files Browse the repository at this point in the history
Some datatable actions were not honoring the profile setting

Fixed issue where skipping frontdoor caused an extra `/` in the URL
  • Loading branch information
paustint committed Feb 10, 2024
1 parent 958e2a7 commit 7b81c77
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 43 deletions.
15 changes: 5 additions & 10 deletions apps/docs/docs/getting-started/_org-troubleshooting-table.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,8 @@ export const OAuthSettingsSolution = ({ children }) => (

If you have issues adding your org, here are some likely causes and solutions.

| Problem | Possible Causes | Solution |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| You are unable to login, your username and password is not accepted from Salesforce | Your org may have a login restriction to only allow access by logging in using the custom domain. | This setting can be found in Salesforce under `Setup``My Domain``Policies``Prevent login from https://login.salesforce.com`. <br /> <br /> If this is set to true, then you will want to use the **Custom Login URL** option and provide custom domain shown on the **Current My Domain URL** on the setup page. |
| You receive an error message after successfully logging in | <OAuthSettingsList /> | <OAuthSettingsSolution /> |

:::important

Jetstream uses a wide range of IP addresses, so you may need to relax IP address restrictions for the Jetstream Connected App.

:::
| Problem | Possible Causes | Solution |
| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| You are unable to login, your username and password is not accepted from Salesforce | Your org may have a login restriction to only allow access by logging in using the custom domain. | This setting can be found in Salesforce under `Setup``My Domain``Policies``Prevent login from https://login.salesforce.com`. <br /> <br /> If this is set to true, then you will want to use the **Custom Login URL** option and provide custom domain shown on the **Current My Domain URL** on the setup page. |
| You receive an error message after successfully logging in | <OAuthSettingsList /> | <OAuthSettingsSolution /> |
| When you click a Salesforce link, you are required to "Choose a Verification Method" to continue to Salesforce. | You may have very strict session settings in Salesforce, such as "High Assurance". | By default, Jetstream uses [Frontdoor](https://help.salesforce.com/s/articleView?id=sf.security_frontdoorjsp.htm&type=5) to login using your existing Jetstream session. <br /> <br /> This can be disabled by navigating to your settings and enabling the option to **Don't Auto-Login on Link Clicks**. <br /> <br /> <img src={require('./settings-dont-auto-login.png').default} alt="Disable Auto-Login" /> |
2 changes: 1 addition & 1 deletion apps/docs/docs/getting-started/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ You will be asked to choose an org type which is used to determine the which Sal

### Jetstream IP Addresses

If you need to whitelist IP addresses for your org, Jetream will use one of the following three ip addresses:
If you need to whitelist IP addresses for your org, Jetstream will use one of the following three ip addresses:

- `3.134.238.10`
- `3.129.111.220`
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion apps/jetstream/src/app/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ export const salesforceOrgsOmitSelectedState = selector({
export const selectSkipFrontdoorAuth = selector({
key: 'selectSkipFrontdoorAuth',
get: ({ get }) => {
return get(userProfileState)?.preferences?.skipFrontdoorLogin || false;
const userProfile = get(userProfileState);
return userProfile?.preferences?.skipFrontdoorLogin || false;
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import {
import classNames from 'classnames';
import { FunctionComponent, useState } from 'react';
import { Link } from 'react-router-dom';
import { useRecoilState, useRecoilValue } from 'recoil';
import { applicationCookieState, selectedOrgState } from '../../app-state';
import { useRecoilValue } from 'recoil';
import { applicationCookieState, selectSkipFrontdoorAuth, selectedOrgState } from '../../app-state';
import { RequireMetadataApiBanner } from '../core/RequireMetadataApiBanner';
import { useAmplitude } from '../core/analytics';
import * as fromJetstreamEvents from '../core/jetstream-events';
Expand Down Expand Up @@ -60,7 +60,9 @@ export const AutomationControlEditor: FunctionComponent<AutomationControlEditorP
const { trackEvent } = useAmplitude();

const selectedOrg = useRecoilValue<SalesforceOrgUi>(selectedOrgState);
const [{ serverUrl, defaultApiVersion, google_apiKey, google_appId, google_clientId }] = useRecoilState(applicationCookieState);
const { serverUrl, defaultApiVersion, google_apiKey, google_appId, google_clientId } = useRecoilValue(applicationCookieState);
const skipFrontdoorLogin = useRecoilValue(selectSkipFrontdoorAuth);

const selectedSObjects = useRecoilValue(fromAutomationCtlState.selectedSObjectsState);
const selectedAutomationTypes = useRecoilValue(fromAutomationCtlState.selectedAutomationTypes);

Expand Down Expand Up @@ -368,6 +370,7 @@ export const AutomationControlEditor: FunctionComponent<AutomationControlEditorP
>
<AutomationControlEditorTable
serverUrl={serverUrl}
skipFrontdoorLogin={skipFrontdoorLogin}
selectedOrg={selectedOrg}
rows={visibleRows}
quickFilterText={quickFilterText}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const getRowId = ({ key }: TableRowOrItemOrChild) => key;

export interface AutomationControlEditorTableProps {
serverUrl: string;
skipFrontdoorLogin: boolean;
selectedOrg: SalesforceOrgUi;
rows: TableRowOrItemOrChild[];
quickFilterText?: string | null;
Expand All @@ -34,7 +35,7 @@ export interface AutomationControlEditorTableProps {
}

export const AutomationControlEditorTable = forwardRef<any, AutomationControlEditorTableProps>(
({ serverUrl, selectedOrg, rows, quickFilterText, toggleRowExpand, updateIsActiveFlag }, ref) => {
({ serverUrl, skipFrontdoorLogin, selectedOrg, rows, quickFilterText, toggleRowExpand, updateIsActiveFlag }, ref) => {
const columns = useMemo(() => {
return [
{
Expand Down Expand Up @@ -96,6 +97,7 @@ export const AutomationControlEditorTable = forwardRef<any, AutomationControlEdi
<div className="h-100">
<DataTable
serverUrl={serverUrl}
skipFrontdoorLogin={skipFrontdoorLogin}
org={selectedOrg}
data={rows}
columns={columns}
Expand Down
8 changes: 5 additions & 3 deletions apps/jetstream/src/app/components/core/ViewChildRecords.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
import type { ChildRelationship, QueryResult } from 'jsforce';
import groupBy from 'lodash/groupBy';
import { FunctionComponent, MutableRefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilValue } from 'recoil';
import { composeQuery, getField } from 'soql-parser-js';
import { applicationCookieState, selectSkipFrontdoorAuth } from '../../app-state';
import { useAmplitude } from './analytics';
Expand Down Expand Up @@ -87,7 +87,7 @@ export const ViewChildRecords: FunctionComponent<ViewChildRecordsProps> = ({
}) => {
const { trackEvent } = useAmplitude();
const isMounted = useRef(true);
const [{ serverUrl }] = useRecoilState(applicationCookieState);
const { serverUrl } = useRecoilValue(applicationCookieState);
const skipFrontDoorAuth = useRecoilValue(selectSkipFrontdoorAuth);
const [loading, setLoading] = useState<boolean>(true);
const [rows, setRows] = useState<Record<ChildRecordRow>[]>([]);
Expand Down Expand Up @@ -171,7 +171,7 @@ export const ViewChildRecords: FunctionComponent<ViewChildRecordsProps> = ({
name: 'Created',
},
],
[selectedOrg, serverUrl]
[selectedOrg, serverUrl, skipFrontDoorAuth]
);

const fetchChildRecords = useCallback(
Expand Down Expand Up @@ -351,6 +351,8 @@ export const ViewChildRecords: FunctionComponent<ViewChildRecordsProps> = ({
<DataTree
columns={columns}
data={rows}
serverUrl={serverUrl}
skipFrontdoorLogin={skipFrontDoorAuth}
getRowKey={getRowId}
includeQuickFilter
groupBy={groupedRows}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { Link, NavLink, useLocation, useNavigate } from 'react-router-dom';
import { useRecoilState, useRecoilValue } from 'recoil';
import { filter } from 'rxjs/operators';
import { FieldSubquery, Query, composeQuery, isFieldSubquery, parseQuery } from 'soql-parser-js';
import { applicationCookieState, selectedOrgState } from '../../../app-state';
import { applicationCookieState, selectSkipFrontdoorAuth, selectedOrgState } from '../../../app-state';
import ViewEditCloneRecord from '../../core/ViewEditCloneRecord';
import { useAmplitude } from '../../core/analytics';
import * as fromJetstreamEvents from '../../core/jetstream-events';
Expand Down Expand Up @@ -100,7 +100,8 @@ export const QueryResults: FunctionComponent<QueryResultsProps> = React.memo(()
const [loading, setLoading] = useState<boolean>(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const selectedOrg = useRecoilValue<SalesforceOrgUi>(selectedOrgState);
const [{ serverUrl, defaultApiVersion, google_apiKey, google_appId, google_clientId }] = useRecoilState(applicationCookieState);
const { serverUrl, defaultApiVersion, google_apiKey, google_appId, google_clientId } = useRecoilValue(applicationCookieState);
const skipFrontdoorLogin = useRecoilValue(selectSkipFrontdoorAuth);
const [totalRecordCount, setTotalRecordCount] = useState<number | null>(null);
const [queryHistory, setQueryHistory] = useRecoilState(fromQueryHistory.queryHistoryState);
const bulkDeleteJob = useObservable(
Expand Down Expand Up @@ -660,6 +661,7 @@ export const QueryResults: FunctionComponent<QueryResultsProps> = React.memo(()
google_clientId={google_clientId}
isTooling={isTooling}
serverUrl={serverUrl}
skipFrontdoorLogin={skipFrontdoorLogin}
queryResults={queryResults}
fieldMetadata={fieldMetadata}
fieldMetadataSubquery={fieldMetadataSubquery}
Expand Down
17 changes: 11 additions & 6 deletions apps/jetstream/src/app/components/settings/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { logger } from '@jetstream/shared/client-logger';
import { ANALYTICS_KEYS, TITLES } from '@jetstream/shared/constants';
import { deleteUserProfile, getFullUserProfile, resendVerificationEmail, updateUserProfile } from '@jetstream/shared/data';
import {
deleteUserProfile,
getFullUserProfile,
getUserProfile as getUserProfileUi,
resendVerificationEmail,
updateUserProfile,
} from '@jetstream/shared/data';
import { eraseCookies, useRollbar, useTitle } from '@jetstream/shared/ui-utils';
import {
Auth0ConnectionName,
Expand All @@ -23,6 +29,8 @@ import {
} from '@jetstream/ui';
import localforage from 'localforage';
import { Fragment, FunctionComponent, useCallback, useEffect, useRef, useState } from 'react';
import { useSetRecoilState } from 'recoil';
import { userProfileState } from '../../app-state';
import { useAmplitude } from '../core/analytics';
import LoggerConfig from './LoggerConfig';
import SettingsDeleteAccount from './SettingsDeleteAccount';
Expand All @@ -32,11 +40,6 @@ import { useLinkAccount } from './useLinkAccount';

const HEIGHT_BUFFER = 170;

type UpdateUserRequest = {
name: string;
preferences: UserProfileUi['preferences'];
};

export interface SettingsProps {
userProfile: Maybe<UserProfileUi>;
featureFlags: Set<string>;
Expand All @@ -49,6 +52,7 @@ export const Settings: FunctionComponent<SettingsProps> = ({ userProfile, featur
const rollbar = useRollbar();
const [loading, setLoading] = useState(false);
const [loadingError, setLoadingError] = useState(false);
const setUserProfile = useSetRecoilState(userProfileState);
const [fullUserProfile, setFullUserProfile] = useState<UserProfileUiWithIdentities>();
const [modifiedUser, setModifiedUser] = useState<UserProfileUiWithIdentities>();
const [editMode, setEditMode] = useState(false);
Expand Down Expand Up @@ -94,6 +98,7 @@ export const Settings: FunctionComponent<SettingsProps> = ({ userProfile, featur
}
setLoading(true);
const userProfile = await updateUserProfile(_modifiedUser);
setUserProfile(await getUserProfileUi());
setFullUserProfile(userProfile);
trackEvent(ANALYTICS_KEYS.settings_update_user);
} catch (ex) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { css } from '@emotion/react';
import { UserProfileUiWithIdentities } from '@jetstream/types';
import { Form, FormRow, FormRowItem, Grid, Input, ReadOnlyFormItem } from '@jetstream/ui';
import { Fragment, FunctionComponent, useMemo } from 'react';
Expand Down Expand Up @@ -39,7 +40,12 @@ export const SettingsUserProfile: FunctionComponent<SettingsUserProfileProps> =
<button className="slds-button slds-button_neutral slds-m-left_small">Change picture</button>
</div> */}
</Grid>
<Grid className="slds-m-top_small slds-m-bottom_large">
<div
className="slds-m-top_small slds-m-bottom_large"
css={css`
max-width: 33rem;
`}
>
<Form>
<FormRow>
<FormRowItem>
Expand Down Expand Up @@ -82,7 +88,7 @@ export const SettingsUserProfile: FunctionComponent<SettingsUserProfileProps> =
</FormRow>
)}
</Form>
</Grid>
</div>
</Fragment>
);
};
Expand Down
21 changes: 19 additions & 2 deletions libs/ui/src/lib/data-table/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,27 @@ import './data-table-styles.scss';
import { ColumnWithFilter, ContextMenuActionData, RowWithKey } from './data-table-types';
import { useDataTable } from './useDataTable';

export interface DataTableProps<T = RowWithKey, TContext = Record<string, any>>
interface PropsWithServer {
serverUrl: string;
skipFrontdoorLogin: boolean;
}

interface PropsWithoutServer {
serverUrl?: never;
skipFrontdoorLogin?: never;
}

export type DataTableProps<T = RowWithKey, TContext = Record<string, any>> = DataTablePropsBase<T, TContext> &
(PropsWithServer | PropsWithoutServer);

interface DataTablePropsBase<T = RowWithKey, TContext = Record<string, any>>
extends Omit<DataGridProps<T>, 'columns' | 'rows' | 'rowKeyGetter' | 'onColumnsReorder'> {
data: T[];
columns: ColumnWithFilter<T>[];
serverUrl?: string;
org?: SalesforceOrgUi;
// Both of these are required if one is present, since the server url is most likely used for frontdoor login
// serverUrl
// skipFrontdoorLogin
quickFilterText?: string | null;
includeQuickFilter?: boolean;
context?: TContext;
Expand All @@ -35,6 +50,7 @@ export const DataTable = forwardRef<any, DataTableProps<any>>(
data,
columns: _columns,
serverUrl,
skipFrontdoorLogin,
org,
quickFilterText,
includeQuickFilter,
Expand Down Expand Up @@ -68,6 +84,7 @@ export const DataTable = forwardRef<any, DataTableProps<any>>(
data,
columns: _columns,
serverUrl,
skipFrontdoorLogin,
org,
quickFilterText,
includeQuickFilter,
Expand Down
6 changes: 4 additions & 2 deletions libs/ui/src/lib/data-table/DataTableRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ import { getRowId, getSfdcRetUrl, isFilterActive, resetFilter } from './data-tab

let _serverUrl: string;
let _org: SalesforceOrgUi;
let _skipFrontdoorLogin = false;

export function configIdLinkRenderer(serverUrl: string, org: SalesforceOrgUi) {
export function configIdLinkRenderer(serverUrl: string, org: SalesforceOrgUi, skipFrontdoorLogin?: boolean) {
if (_serverUrl !== serverUrl) {
_serverUrl = serverUrl;
}
if (_org !== org) {
_org = org;
}
_skipFrontdoorLogin = skipFrontdoorLogin ?? _skipFrontdoorLogin;
}

// HEADER RENDERERS
Expand Down Expand Up @@ -580,7 +582,7 @@ export const IdLinkRenderer: FunctionComponent<RenderCellProps<any, unknown>> =
onRecordAction?: (action: CloneEditView, recordId: string, sobjectName: string) => void;
};
const recordId = row[column.key];
const { skipFrontDoorAuth, url } = getSfdcRetUrl(row, recordId);
const { skipFrontDoorAuth, url } = getSfdcRetUrl(row, recordId, _skipFrontdoorLogin);
return (
<RecordLookupPopover
org={_org}
Expand Down
16 changes: 14 additions & 2 deletions libs/ui/src/lib/data-table/DataTableSubqueryRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,17 @@ export const SubqueryRenderer: FunctionComponent<RenderCellProps<RowWithKey, unk
if (!props) {
return null;
}
const { serverUrl, org, columnDefinitions, onSubqueryFieldReorder, isTooling, google_apiKey, google_appId, google_clientId } =
props;
const {
serverUrl,
skipFrontdoorLogin,
org,
columnDefinitions,
onSubqueryFieldReorder,
isTooling,
google_apiKey,
google_appId,
google_clientId,
} = props;

if (!columnDefinitions || !columnDefinitions[column.key]) {
return null;
Expand All @@ -148,6 +157,7 @@ export const SubqueryRenderer: FunctionComponent<RenderCellProps<RowWithKey, unk
org={org}
downloadModalIsActive={downloadModalIsActive}
serverUrl={serverUrl}
skipFrontdoorLogin={skipFrontdoorLogin}
google_apiKey={google_apiKey}
google_appId={google_appId}
google_clientId={google_clientId}
Expand Down Expand Up @@ -202,6 +212,7 @@ function ModalDataTable({
org,
downloadModalIsActive,
serverUrl,
skipFrontdoorLogin,
google_apiKey,
google_appId,
google_clientId,
Expand Down Expand Up @@ -315,6 +326,7 @@ function ModalDataTable({
<AutoFullHeightContainer fillHeight setHeightAttr bottomBuffer={300}>
<DataTable
serverUrl={serverUrl}
skipFrontdoorLogin={skipFrontdoorLogin}
org={org}
data={rows}
columns={columns}
Expand Down
Loading

0 comments on commit 7b81c77

Please sign in to comment.