Skip to content

Commit 02b913a

Browse files
committed
ENG-1703: Send tokens over to vercel
1 parent 8c86b7a commit 02b913a

9 files changed

Lines changed: 186 additions & 18 deletions

File tree

apps/obsidian/src/components/AdminPanelSettings.tsx

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { useState, useCallback } from "react";
1+
import { useState, useCallback, useEffect } from "react";
22
import { usePlugin } from "./PluginContext";
33
import { Notice } from "obsidian";
44
import { updateUsername } from "~/utils/supabaseContext";
55
import { initializeSupabaseSync } from "~/utils/syncDgNodesToSupabase";
6+
import { nextRoot } from "@repo/utils/execContext";
7+
import { getLoggedInClient } from "~/utils/supabaseContext";
68

79
export const AdminPanelSettings = () => {
810
const plugin = usePlugin();
@@ -12,6 +14,26 @@ export const AdminPanelSettings = () => {
1214
const [username, setUsername] = useState<string>(
1315
plugin.settings.username || "",
1416
);
17+
const [accessToken, setAccessToken] = useState<string | null>(null);
18+
const [refreshToken, setRefreshToken] = useState<string | null>(null);
19+
useEffect(() => {
20+
if (syncModeEnabled) {
21+
const fetchTokens = async () => {
22+
const client = await getLoggedInClient(plugin);
23+
if (client) {
24+
const session = await client.auth.getSession();
25+
if (session.data.session) {
26+
setAccessToken(session.data.session.access_token);
27+
setRefreshToken(session.data.session.refresh_token);
28+
}
29+
}
30+
};
31+
void fetchTokens();
32+
} else {
33+
setAccessToken(null);
34+
setRefreshToken(null);
35+
}
36+
}, [syncModeEnabled]);
1537

1638
const handleSyncModeToggle = useCallback(
1739
async (newValue: boolean) => {
@@ -80,6 +102,32 @@ export const AdminPanelSettings = () => {
80102
/>
81103
</div>
82104
</div>
105+
<div
106+
className={
107+
"setting-item " + (accessToken && refreshToken ? "" : "hidden")
108+
}
109+
>
110+
<div className="setting-item-info">
111+
<div className="setting-item-name">Group management</div>
112+
<div className="setting-item-description">
113+
This will allow you to view and manage your sharing groups
114+
</div>
115+
</div>
116+
<div className="setting-item-control">
117+
{accessToken && refreshToken && (
118+
<button
119+
onClick={() => {
120+
window.open(
121+
`${nextRoot()}/auth/token?t=${accessToken}&r=${refreshToken}&url=/`,
122+
"_blank",
123+
);
124+
}}
125+
>
126+
Manage groups
127+
</button>
128+
)}
129+
</div>
130+
</div>
83131
</div>
84132
);
85133
};

apps/roam/src/components/settings/AdminPanel.tsx

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
} from "~/components/settings/utils/accessors";
3535
import { FeatureFlagPanel } from "./components/BlockPropSettingPanels";
3636
import type { FeatureFlags } from "./utils/zodSchema";
37+
import { nextRoot } from "@repo/utils/execContext";
3738

3839
const NodeRow = ({ node }: { node: PConceptFull }) => {
3940
return (
@@ -266,13 +267,32 @@ const FeatureFlagsTab = (): React.ReactElement => {
266267
const [suggestiveOverlayValue, setSuggestiveOverlayValue] = useState(
267268
getFeatureFlag("Suggestive mode overlay enabled"),
268269
);
269-
270-
const syncAlreadyEnabled = duplicateNodeAlertValue || suggestiveOverlayValue;
270+
const [accessToken, setAccessToken] = useState<string | null>(null);
271+
const [refreshToken, setRefreshToken] = useState<string | null>(null);
272+
//const syncAlreadyEnabled = duplicateNodeAlertValue || suggestiveOverlayValue;
273+
useEffect(() => {
274+
if (duplicateNodeAlertValue || suggestiveOverlayValue) {
275+
const fetchTokens = async () => {
276+
const client = await getLoggedInClient();
277+
if (client) {
278+
const session = await client.auth.getSession();
279+
if (session.data.session) {
280+
setAccessToken(session.data.session.access_token);
281+
setRefreshToken(session.data.session.refresh_token);
282+
}
283+
}
284+
};
285+
void fetchTokens();
286+
} else {
287+
setAccessToken(null);
288+
setRefreshToken(null);
289+
}
290+
}, [duplicateNodeAlertValue, suggestiveOverlayValue]);
271291

272292
const ensureSyncEnabled = (
273293
featureKey: keyof FeatureFlags,
274294
): Promise<boolean> => {
275-
if (syncAlreadyEnabled) {
295+
if (duplicateNodeAlertValue || suggestiveOverlayValue) {
276296
return Promise.resolve(true);
277297
}
278298
setPendingFeatureKey(featureKey);
@@ -393,6 +413,20 @@ const FeatureFlagsTab = (): React.ReactElement => {
393413
>
394414
Send Error Email
395415
</Button>
416+
{accessToken && refreshToken && (
417+
<Button
418+
className="w-96"
419+
icon="document-open"
420+
onClick={() => {
421+
window.open(
422+
`${nextRoot()}/auth/token?t=${accessToken}&r=${refreshToken}&url=/`,
423+
"_blank",
424+
);
425+
}}
426+
>
427+
Manage groups
428+
</Button>
429+
)}
396430
</div>
397431
);
398432
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { LoginWithToken } from "~/components/auth/LoginWithToken";
2+
3+
const Page = () => (
4+
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
5+
<LoginWithToken />
6+
</div>
7+
);
8+
9+
export default Page;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"use client";
2+
3+
import { createClient } from "~/utils/supabase/client";
4+
import { useRouter, useSearchParams } from "next/navigation";
5+
import { useState, useEffect, useCallback } from "react";
6+
7+
export const LoginWithToken = () => {
8+
const searchParams = useSearchParams();
9+
const router = useRouter();
10+
const [accessToken] = useState(searchParams.get("t"));
11+
const [refreshToken] = useState(searchParams.get("r"));
12+
const [url] = useState(searchParams.get("url"));
13+
const [done, setDone] = useState(false);
14+
const [error, setError] = useState<string | null>(
15+
accessToken === null || refreshToken == null
16+
? "Please provide tokens"
17+
: null,
18+
);
19+
20+
const login = useCallback(async () => {
21+
try {
22+
const client = createClient();
23+
const response = await client.auth.setSession({
24+
/* eslint-disable @typescript-eslint/naming-convention */
25+
access_token: accessToken!,
26+
refresh_token: refreshToken!,
27+
/* eslint-enable @typescript-eslint/naming-convention */
28+
});
29+
if (response.error) {
30+
setError(response.error.message);
31+
} else if (url) {
32+
router.replace(url);
33+
}
34+
} catch (error) {
35+
setError("error");
36+
} finally {
37+
setDone(true);
38+
}
39+
}, [accessToken, refreshToken, url, router]);
40+
useEffect(() => {
41+
if (!error && !done) {
42+
void login();
43+
}
44+
}, [error, login, accessToken, refreshToken, done]);
45+
return (
46+
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
47+
<div className="w-full max-w-sm">
48+
{error ? "Error: " + error : done ? "Logged in" : "Logging in"}
49+
</div>
50+
</div>
51+
);
52+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createBrowserClient } from "@supabase/ssr";
2+
3+
export const createClient = () => {
4+
return createBrowserClient(
5+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
6+
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
7+
);
8+
};

apps/website/next.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { DOCS_REDIRECTS } from "./docsRouteMap";
55

66
config();
77

8+
// expose supabase credentials to the client
9+
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY =
10+
process.env.SUPABASE_PUBLISHABLE_KEY;
11+
process.env.NEXT_PUBLIC_SUPABASE_URL = process.env.SUPABASE_URL;
12+
813
const withNextra = nextra({
914
contentDirBasePath: "/docs",
1015
});

apps/website/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@repo/ui": "workspace:*",
1919
"@supabase/ssr": "^0.8.0",
2020
"@supabase/supabase-js": "catalog:",
21+
"@supabase/auth-js": "catalog:",
2122
"clsx": "^2.1.1",
2223
"gray-matter": "^4.0.3",
2324
"lucide-react": "^0.540.0",

packages/utils/src/execContext.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
const IS_DEV = process.env.NODE_ENV !== "production";
22

3+
export const nextRoot = (): string => {
4+
if (
5+
process.env.NEXT_API_ROOT !== undefined &&
6+
process.env.NEXT_API_ROOT !== ""
7+
)
8+
return process.env.NEXT_API_ROOT.split("/").slice(0, 3).join("");
9+
return IS_DEV ? "http://localhost:3000/" : "https://discoursegraphs.com/";
10+
};
11+
312
export const nextApiRoot = (): string => {
413
if (
514
process.env.NEXT_API_ROOT !== undefined &&
615
process.env.NEXT_API_ROOT !== ""
716
)
817
return process.env.NEXT_API_ROOT;
9-
return IS_DEV
10-
? "http://localhost:3000/api"
11-
: "https://discoursegraphs.com/api";
18+
return nextRoot() + "api";
1219
};

pnpm-lock.yaml

Lines changed: 15 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)