Skip to content

Commit

Permalink
Allow opting out of record sync
Browse files Browse the repository at this point in the history
  • Loading branch information
paustint committed Feb 4, 2025
1 parent b15a089 commit 30c20d7
Show file tree
Hide file tree
Showing 13 changed files with 43 additions and 21 deletions.
3 changes: 2 additions & 1 deletion apps/api/src/app/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export const routeDefinition = {
name: z.string().min(1).max(255).trim().optional(),
preferences: z
.object({
skipFrontdoorLogin: z.boolean(),
skipFrontdoorLogin: z.boolean().optional(),
recordSyncEnabled: z.boolean().optional(),
})
.optional(),
}),
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/app/controllers/web-extension.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const initSession = createRoute(routeDefinition.initSession.validators, async ({
name: user.name,
emailVerified: user.emailVerified,
picture: user.picture,
preferences: { skipFrontdoorLogin: false },
preferences: { skipFrontdoorLogin: false, recordSyncEnabled: true },
billingAccount: user.billingAccount,
entitlements: {
chromeExtension: true,
Expand Down
13 changes: 8 additions & 5 deletions apps/api/src/app/db/user.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,25 @@ export const checkUserEntitlement = ({

export async function updateUser(
user: UserProfileSession,
data: { name?: string; preferences?: { skipFrontdoorLogin: boolean } }
data: { name?: string; preferences?: { skipFrontdoorLogin?: boolean; recordSyncEnabled?: boolean } }
): Promise<User> {
try {
const existingUser = await prisma.user.findUniqueOrThrow({
where: { id: user.id },
select: { id: true, name: true, preferences: { select: { skipFrontdoorLogin: true } } },
select: { id: true, name: true, preferences: { select: { skipFrontdoorLogin: true, recordSyncEnabled: true } } },
});
const skipFrontdoorLogin = data.preferences?.skipFrontdoorLogin ?? (existingUser?.preferences?.skipFrontdoorLogin || false);
// PATCH update
const skipFrontdoorLogin = data.preferences?.skipFrontdoorLogin ?? existingUser?.preferences?.skipFrontdoorLogin ?? false;
const recordSyncEnabled = data.preferences?.recordSyncEnabled ?? existingUser?.preferences?.recordSyncEnabled ?? true;

const updatedUser = await prisma.user.update({
where: { id: user.id },
data: {
name: data.name ?? existingUser.name,
preferences: {
upsert: {
create: { skipFrontdoorLogin },
update: { skipFrontdoorLogin },
create: { skipFrontdoorLogin, recordSyncEnabled },
update: { skipFrontdoorLogin, recordSyncEnabled },
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion apps/jetstream/src/app/components/billing/Billing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const Billing = () => {
<BillingExistingSubscriptions customerWithSubscriptions={customerWithSubscriptions} />
) : (
<form method="POST" action="/api/billing/checkout-session">
<p className="slds-text-title_bold">Professional plan includes</p>
<p className="slds-text-title_bold">Upgrading to a Jetstream Professional plan includes</p>
<ul className="slds-list_dotted slds-m-bottom_small">
<li>
Access to the{' '}
Expand Down
8 changes: 6 additions & 2 deletions apps/jetstream/src/app/components/core/AppInitializer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-restricted-globals */
import { logger } from '@jetstream/shared/client-logger';
import { HTTP } from '@jetstream/shared/constants';
import { checkHeartbeat, initSocket, registerMiddleware } from '@jetstream/shared/data';
import { checkHeartbeat, disconnectSocket, initSocket, registerMiddleware } from '@jetstream/shared/data';
import { useObservable, useRollbar } from '@jetstream/shared/ui-utils';
import { Announcement, ApplicationCookie, SalesforceOrgUi, UserProfileUi } from '@jetstream/types';
import { initDexieDb, useAmplitude, usePageViews } from '@jetstream/ui-core';
Expand Down Expand Up @@ -41,7 +41,9 @@ export const AppInitializer: FunctionComponent<AppInitializerProps> = ({ onAnnou
const appCookie = useRecoilValue<ApplicationCookie>(fromAppState.applicationCookieState);
const [orgs, setOrgs] = useRecoilState(fromAppState.salesforceOrgsState);
const invalidOrg = useObservable(orgConnectionError$);
const recordSyncEnabled = useRecoilValue(fromAppState.userProfileEntitlementState('recordSync'));

const recordSyncEntitlementEnabled = useRecoilValue(fromAppState.userProfileEntitlementState('recordSync'));
const recordSyncEnabled = recordSyncEntitlementEnabled && userProfile.preferences.recordSyncEnabled;

useEffect(() => {
console.log(
Expand All @@ -67,6 +69,8 @@ APP VERSION ${version}
useEffect(() => {
if (recordSyncEnabled) {
initSocket();
} else {
disconnectSocket();
}
initDexieDb({ recordSyncEnabled }).catch((ex) => {
logger.error('[DB] Error initializing db', ex);
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
Expand Up @@ -102,6 +102,12 @@ export const Settings = () => {
handleSave(_modifiedUser);
}

function handleRecordSyncChange(recordSyncEnabled: boolean) {
const _modifiedUser = { ...modifiedUser, preferences: { recordSyncEnabled } } as UserProfileUiWithIdentities;
setModifiedUser(_modifiedUser);
handleSave(_modifiedUser);
}

async function handleDelete(reason: string) {
/**
* FUTURE:
Expand Down Expand Up @@ -163,7 +169,7 @@ export const Settings = () => {
<h2 className="slds-text-heading_medium slds-m-vertical_small">General Settings</h2>
<CheckboxToggle
id="frontdoor-toggle"
checked={modifiedUser?.preferences?.skipFrontdoorLogin || false}
checked={modifiedUser?.preferences?.skipFrontdoorLogin ?? false}
label="Don't Auto-Login on Link Clicks"
labelHelp="When enabled, Jetstream will not attempt to auto-login to Salesforce when you click a link in Jetstream. If you have issues with multi-factor authentication when clicking links, enable this."
onChange={handleFrontdoorLoginChange}
Expand All @@ -172,14 +178,13 @@ export const Settings = () => {
{recordSyncEnabled && (
<div className="slds-m-top_large">
<h2 className="slds-text-heading_medium slds-m-vertical_small">Data Sync</h2>
{/* FIXME: add option for user to opt-out of this behavior (e.g. user preference?) */}
{/* <CheckboxToggle
<CheckboxToggle
id="enable-record-sync-button"
checked={recordSyncEnabled}
checked={modifiedUser?.preferences?.recordSyncEnabled ?? true}
label="Data Sync"
labelHelp="Enable to sync Query History with the Jetstream server."
onChange={(value) => setRecordSyncEnabled(value)}
/> */}
onChange={handleRecordSyncChange}
/>
<button className="slds-button slds-button_text-destructive slds-m-top_small slds-is-relative" onClick={resetSync}>
{resetSyncLoading && <Spinner className="slds-spinner slds-spinner_small" />}
Reset Sync
Expand Down
1 change: 1 addition & 0 deletions libs/api-config/src/lib/env-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const EXAMPLE_USER_FULL_PROFILE: UserProfileUiWithIdentities = {
updatedAt: new Date(),
preferences: {
skipFrontdoorLogin: false,
recordSyncEnabled: false,
id: 'AAAAAAAA-0000-0000-0000-AAAAAAAAAAAA',
userId: 'test|TEST_USER_ID',
createdAt: new Date(),
Expand Down
1 change: 1 addition & 0 deletions libs/auth/types/src/lib/auth-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface UserProfileUiWithIdentities extends UserProfile {
createdAt: Date;
updatedAt: Date;
skipFrontdoorLogin: boolean;
recordSyncEnabled: boolean;
} | null;
identities: UserProfileIdentity[];
authFactors: UserProfileAuthFactor[];
Expand Down
1 change: 1 addition & 0 deletions libs/shared/ui-app-state/src/lib/ui-app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const DEFAULT_PROFILE: UserProfileUi = {
picture: null,
preferences: {
skipFrontdoorLogin: true,
recordSyncEnabled: true,
},
// FIXME: we want these true for the chrome extension
entitlements: {
Expand Down
12 changes: 7 additions & 5 deletions libs/shared/ui-core/src/app/HeaderNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,23 @@ function getMenuItems({
}) {
const menu: DropDownItem[] = [];

menu.push({ id: 'profile', value: 'Your Profile', subheader: userProfile.email, icon: { type: 'utility', icon: 'profile_alt' } });
menu.push({ id: 'profile', value: 'Profile', subheader: userProfile.email, icon: { type: 'utility', icon: 'profile_alt' } });
menu.push({ id: 'settings', value: 'Settings', icon: { type: 'utility', icon: 'settings' } });

if (isBillingEnabled) {
menu.push({ id: 'billing', value: 'Billing', icon: { type: 'utility', icon: 'your_account' } });
menu.push({ id: 'billing', value: 'Billing & Subscription', subheader: 'Billing', icon: { type: 'utility', icon: 'your_account' } });
}
menu.push({ id: 'settings', value: 'Settings', icon: { type: 'utility', icon: 'settings' } });

menu.push({ id: 'nav-user-logout', value: 'Logout', icon: { type: 'utility', icon: 'logout' } });
if (deniedNotifications && window.Notification && window.Notification.permission === 'default') {
menu.unshift({
menu.push({
id: 'enable-notifications',
value: 'Enable Notifications',
subheader: 'Notifications',
icon: { type: 'utility', icon: 'notification' },
});
}

menu.push({ id: 'nav-user-logout', subheader: 'Logout', value: 'Logout', icon: { type: 'utility', icon: 'logout' } });
return menu;
}

Expand Down
1 change: 1 addition & 0 deletions libs/types/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export interface UserProfileUi {
picture?: Maybe<string>;
preferences: {
skipFrontdoorLogin: boolean;
recordSyncEnabled: boolean;
};
billingAccount?: Maybe<{
customerId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "UserPreference" ADD COLUMN "recordSyncEnabled" BOOLEAN NOT NULL DEFAULT true;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ model UserPreference {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @unique @db.Uuid
skipFrontdoorLogin Boolean @default(false)
recordSyncEnabled Boolean @default(true)
createdAt DateTime @default(now()) @db.Timestamp(6)
updatedAt DateTime @updatedAt
}
Expand Down

0 comments on commit 30c20d7

Please sign in to comment.