Skip to content

Commit 0f13720

Browse files
jog1tNathanFlurry
authored andcommitted
feat(engine): ask for token when unauth
1 parent b1d8942 commit 0f13720

31 files changed

+569
-124
lines changed

frontend/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@
5050
"@radix-ui/react-tooltip": "^1.1.1",
5151
"@radix-ui/react-visually-hidden": "^1.0.3",
5252
"@rivet-gg/icons": "file:./vendor/rivet-icons.tgz",
53-
"@rivetkit/actor": "file:./vendor/rivetkit-actor.tgz",
54-
"@rivetkit/core": "file:./vendor/rivetkit-core.tgz",
53+
"rivetkit": "*",
5554
"@rivetkit/engine-api-full": "workspace:*",
5655
"@sentry/react": "^8.26.0",
5756
"@sentry/vite-plugin": "^2.22.2",

frontend/src/app.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ declare module "@tanstack/react-router" {
2222
}
2323
}
2424

25+
declare module "@tanstack/react-query" {
26+
interface Register {
27+
queryMeta: {
28+
mightRequireAuth?: boolean;
29+
};
30+
}
31+
}
32+
2533
export const router = createRouter({
2634
basepath: import.meta.env.BASE_URL,
2735
routeTree,
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import * as EngineCredentialsForm from "@/app/forms/engine-credentials-form";
2+
import {
3+
DialogDescription,
4+
DialogFooter,
5+
DialogHeader,
6+
DialogTitle,
7+
Flex,
8+
getConfig,
9+
ls,
10+
toast,
11+
} from "@/components";
12+
import type { DialogContentProps } from "@/components/actors/hooks";
13+
import { queryClient } from "@/queries/global";
14+
import { createClient } from "@/queries/manager-engine";
15+
16+
interface ProvideEngineCredentialsDialogContentProps
17+
extends DialogContentProps {}
18+
19+
export default function ProvideEngineCredentialsDialogContent({
20+
onClose,
21+
}: ProvideEngineCredentialsDialogContentProps) {
22+
return (
23+
<EngineCredentialsForm.Form
24+
defaultValues={{ token: "" }}
25+
errors={
26+
ls.engineCredentials.get(getConfig().apiUrl)
27+
? { token: { message: "Invalid token.", type: "manual" } }
28+
: {}
29+
}
30+
onSubmit={async (values, form) => {
31+
const client = createClient({
32+
token: values.token,
33+
});
34+
35+
try {
36+
await client.namespaces.list();
37+
38+
ls.engineCredentials.set(getConfig().apiUrl, values.token);
39+
40+
toast.success(
41+
"Successfully authenticated with Rivet Engine",
42+
);
43+
44+
await queryClient.refetchQueries();
45+
46+
onClose?.();
47+
} catch (e) {
48+
if (e && typeof e === "object" && "statusCode" in e) {
49+
if (e.statusCode === 403) {
50+
form.setError("token", {
51+
message: "Invalid token.",
52+
});
53+
return;
54+
}
55+
}
56+
57+
form.setError("token", {
58+
message: "Failed to connect. Please try again.",
59+
});
60+
return;
61+
}
62+
}}
63+
>
64+
<DialogHeader>
65+
<DialogTitle>Missing Rivet Engine credentials</DialogTitle>
66+
<DialogDescription>
67+
It looks like the instance of Rivet Engine that you're
68+
connected to requires additional credentials, please provide
69+
them below.
70+
</DialogDescription>
71+
</DialogHeader>
72+
<Flex gap="4" direction="col">
73+
<EngineCredentialsForm.Token />
74+
</Flex>
75+
<DialogFooter>
76+
<EngineCredentialsForm.Submit type="submit" allowPristine>
77+
Save
78+
</EngineCredentialsForm.Submit>
79+
</DialogFooter>
80+
</EngineCredentialsForm.Form>
81+
);
82+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { type UseFormReturn, useFormContext } from "react-hook-form";
2+
import z from "zod";
3+
import {
4+
createSchemaForm,
5+
FormControl,
6+
FormField,
7+
FormItem,
8+
FormLabel,
9+
FormMessage,
10+
Input,
11+
} from "@/components";
12+
13+
export const formSchema = z.object({
14+
token: z.string().nonempty("Token is required"),
15+
});
16+
17+
export type FormValues = z.infer<typeof formSchema>;
18+
export type SubmitHandler = (
19+
values: FormValues,
20+
form: UseFormReturn<FormValues>,
21+
) => Promise<void>;
22+
23+
const { Form, Submit, SetValue } = createSchemaForm(formSchema);
24+
export { Form, Submit, SetValue };
25+
26+
export const Token = ({ className }: { className?: string }) => {
27+
const { control } = useFormContext<FormValues>();
28+
return (
29+
<FormField
30+
control={control}
31+
name="token"
32+
render={({ field }) => (
33+
<FormItem className={className}>
34+
<FormLabel className="col-span-1">Token</FormLabel>
35+
<FormControl className="row-start-2">
36+
<Input
37+
placeholder="Enter a token..."
38+
type="password"
39+
{...field}
40+
/>
41+
</FormControl>
42+
<FormMessage className="col-span-1" />
43+
</FormItem>
44+
)}
45+
/>
46+
);
47+
};

frontend/src/app/use-dialog.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
import { createDialogHook, useDialog } from "@/components/actors";
1+
import {
2+
useDialog as baseUseDialog,
3+
createDialogHook,
4+
} from "@/components/actors";
25

3-
const d = useDialog as typeof useDialog &
4-
Record<string, ReturnType<typeof createDialogHook>>;
5-
d.CreateNamespace = createDialogHook(
6-
import("@/app/dialogs/create-namespace-dialog"),
7-
);
8-
9-
export { d as useDialog };
6+
export const useDialog = {
7+
...baseUseDialog,
8+
CreateNamespace: createDialogHook(
9+
import("@/app/dialogs/create-namespace-dialog"),
10+
),
11+
ProvideEngineCredentials: createDialogHook(
12+
import("@/app/dialogs/provide-engine-credentials-dialog"),
13+
),
14+
};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export {
22
createActorInspectorClient,
33
createManagerInspectorClient,
4-
} from "@rivetkit/core/inspector";
4+
} from "rivetkit/inspector";

frontend/src/components/actors/actor-events-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import {
66
faUnlink,
77
Icon,
88
} from "@rivet-gg/icons";
9-
import type { RecordedRealtimeEvent } from "@rivetkit/core/inspector";
109
import { useQuery } from "@tanstack/react-query";
1110
import { format } from "date-fns";
1211
import { type PropsWithChildren, useEffect, useRef } from "react";
12+
import type { RecordedRealtimeEvent } from "rivetkit/inspector";
1313
import { Badge } from "../ui/badge";
1414
import { useActor } from "./actor-queries-context";
1515
import { ActorObjectInspector } from "./console/actor-inspector";

frontend/src/components/actors/actor-queries-context.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { createActorInspectorClient } from "@rivetkit/core/inspector";
21
import { queryOptions } from "@tanstack/react-query";
32
import { createContext, useContext } from "react";
3+
import { createActorInspectorClient } from "rivetkit/inspector";
44
import type { ActorId } from "./queries";
55

66
type RequestOptions = Parameters<typeof createActorInspectorClient>[1];

frontend/src/components/actors/database/database-table.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
faLink,
66
Icon,
77
} from "@rivet-gg/icons";
8-
import type { Column, Columns, ForeignKeys } from "@rivetkit/core/inspector";
98
import {
109
createColumnHelper,
1110
// SortingState,
@@ -19,6 +18,7 @@ import {
1918
useReactTable as useTable,
2019
} from "@tanstack/react-table";
2120
import { Fragment, useMemo, useState } from "react";
21+
import type { Column, Columns, ForeignKeys } from "rivetkit/inspector";
2222
import {
2323
Badge,
2424
Button,

frontend/src/components/actors/guard-connectable-inspector.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from "@/queries/manager-engine";
1111
import { DiscreteCopyButton } from "../copy-area";
1212
import { getConfig } from "../lib/config";
13+
import { ls } from "../lib/utils";
1314
import { Button } from "../ui/button";
1415
import { useFiltersValue } from "./actor-filters-context";
1516
import { ActorProvider } from "./actor-queries-context";
@@ -157,6 +158,7 @@ function useActorEngineContext({ actorId }: { actorId: ActorId }) {
157158
return createInspectorActorContext({
158159
url: getConfig().apiUrl,
159160
token: (runner?.metadata?.inspectorToken as string) || "",
161+
engineToken: ls.engineCredentials.get(getConfig().apiUrl) || "",
160162
});
161163
}, [runner?.metadata?.inspectorToken]);
162164

0 commit comments

Comments
 (0)