Skip to content

Commit 3072ed6

Browse files
committed
feat: cloud acl (#3052)
1 parent 80b50b9 commit 3072ed6

29 files changed

+1411
-427
lines changed

frontend/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@
5858
"@radix-ui/react-toggle-group": "^1.1.11",
5959
"@radix-ui/react-tooltip": "^1.2.8",
6060
"@radix-ui/react-visually-hidden": "^1.2.3",
61-
"@rivet-gg/cloud": "file:vendor/rivet-cloud.tgz",
61+
"@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@7090780",
6262
"@rivet-gg/icons": "workspace:*",
63-
"rivetkit": "*",
6463
"@rivetkit/engine-api-full": "workspace:*",
6564
"@sentry/react": "^8.55.0",
6665
"@sentry/vite-plugin": "^2.23.1",
6766
"@shikijs/langs": "^3.12.2",
6867
"@shikijs/transformers": "^3.12.2",
68+
"@stepperize/react": "^5.1.8",
6969
"@tailwindcss/container-queries": "^0.1.1",
7070
"@tailwindcss/typography": "^0.5.16",
7171
"@tanstack/query-core": "^5.87.1",
@@ -118,6 +118,7 @@
118118
"react-inspector": "^6.0.2",
119119
"react-resizable-panels": "^2.1.9",
120120
"recharts": "^2.15.4",
121+
"rivetkit": "*",
121122
"shiki": "^3.12.2",
122123
"sonner": "^1.7.4",
123124
"tailwind-merge": "^2.6.0",

frontend/src/app/data-providers/cloud-data-provider.tsx

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type Rivet, RivetClient } from "@rivet-gg/cloud";
33
import { type FetchFunction, fetcher } from "@rivetkit/engine-api-full/core";
44
import { infiniteQueryOptions, queryOptions } from "@tanstack/react-query";
55
import { cloudEnv } from "@/lib/env";
6+
import { queryClient } from "@/queries/global";
67
import { RECORDS_PER_PAGE } from "./default-data-provider";
78
import {
89
type CreateNamespace,
@@ -170,6 +171,7 @@ export const createOrganizationContext = ({
170171
};
171172

172173
return {
174+
organization,
173175
orgProjectNamespacesQueryOptions,
174176
currentOrgProjectNamespacesQueryOptions: (opts: {
175177
project: string;
@@ -209,8 +211,7 @@ export const createOrganizationContext = ({
209211
}) => {
210212
const response = await client.projects.create({
211213
displayName: data.displayName,
212-
name: data.nameId,
213-
organizationId: organization,
214+
org: organization,
214215
});
215216

216217
return response;
@@ -233,6 +234,7 @@ export const createProjectContext = ({
233234
} & ReturnType<typeof createOrganizationContext> &
234235
ReturnType<typeof createGlobalContext>) => {
235236
return {
237+
project,
236238
createNamespaceMutationOptions(opts: {
237239
onSuccess?: (data: Namespace) => void;
238240
}) {
@@ -241,7 +243,6 @@ export const createProjectContext = ({
241243
mutationKey: ["namespaces"],
242244
mutationFn: async (data: CreateNamespace) => {
243245
const response = await client.namespaces.create(project, {
244-
name: data.name,
245246
displayName: data.displayName,
246247
org: organization,
247248
});
@@ -304,20 +305,37 @@ export const createProjectContext = ({
304305
},
305306
};
306307
},
308+
accessTokenQueryOptions({ namespace }: { namespace: string }) {
309+
return queryOptions({
310+
staleTime: 15 * 60 * 1000, // 15 minutes
311+
gcTime: 15 * 60 * 1000, // 15 minutes
312+
queryKey: [
313+
{ organization, project, namespace },
314+
"access-token",
315+
],
316+
queryFn: async ({ signal: abortSignal }) => {
317+
const response = await client.namespaces.createAccessToken(
318+
project,
319+
namespace,
320+
{ org: organization },
321+
{ abortSignal },
322+
);
323+
return response;
324+
},
325+
});
326+
},
307327
};
308328
};
309329

310330
export const createNamespaceContext = ({
311331
namespace,
312332
engineNamespaceName,
313333
engineNamespaceId,
314-
engineToken,
315334
...parent
316335
}: {
317336
namespace: string;
318337
engineNamespaceName: string;
319338
engineNamespaceId: string;
320-
engineToken?: (() => string) | string;
321339
} & ReturnType<typeof createProjectContext> &
322340
ReturnType<typeof createOrganizationContext> &
323341
ReturnType<typeof createGlobalContext>) => {
@@ -327,11 +345,41 @@ export const createNamespaceContext = ({
327345
namespace: engineNamespaceName,
328346
namespaceId: engineNamespaceId,
329347
client: createEngineClient(cloudEnv().VITE_APP_CLOUD_ENGINE_URL, {
330-
token: engineToken,
348+
token: async () => {
349+
const response = await queryClient.fetchQuery(
350+
parent.accessTokenQueryOptions({ namespace }),
351+
);
352+
353+
return response.token;
354+
},
331355
}),
332356
}),
333357
namespaceQueryOptions() {
334358
return parent.currentProjectNamespaceQueryOptions({ namespace });
335359
},
360+
connectRunnerTokenQueryOptions() {
361+
return queryOptions({
362+
staleTime: 5 * 60 * 1000, // 5 minutes
363+
gcTime: 5 * 60 * 1000, // 5 minutes
364+
queryKey: [
365+
{
366+
namespace,
367+
project: parent.project,
368+
organization: parent.organization,
369+
},
370+
"runners",
371+
"connect",
372+
],
373+
queryFn: async () => {
374+
const f = parent.client.namespaces.createPublishableToken(
375+
parent.project,
376+
namespace,
377+
{ org: parent.organization },
378+
);
379+
const t = await f;
380+
return t.token;
381+
},
382+
});
383+
},
336384
};
337385
};

frontend/src/app/data-providers/engine-data-provider.tsx

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { type Rivet, RivetClient } from "@rivetkit/engine-api-full";
22
import { infiniteQueryOptions, queryOptions } from "@tanstack/react-query";
3+
import { getConfig, ls } from "@/components";
34
import {
45
type Actor,
56
ActorFeature,
@@ -15,11 +16,11 @@ import {
1516
type DefaultDataProvider,
1617
RECORDS_PER_PAGE,
1718
} from "./default-data-provider";
18-
import { getConfig } from "@/components/lib/config";
19+
20+
const mightRequireAuth = __APP_TYPE__ === "engine";
1921

2022
export type CreateNamespace = {
2123
displayName: string;
22-
name?: string;
2324
};
2425

2526
export type Namespace = {
@@ -30,8 +31,8 @@ export type Namespace = {
3031
};
3132

3233
export function createClient(
33-
baseUrl = getConfig().apiUrl,
34-
opts: { token: (() => string) | string },
34+
baseUrl = engineEnv().VITE_APP_API_URL,
35+
opts: { token: (() => string) | string | (() => Promise<string>) },
3536
) {
3637
return new RivetClient({
3738
baseUrl: () => baseUrl,
@@ -43,7 +44,7 @@ export function createClient(
4344
export const createGlobalContext = (opts: {
4445
engineToken: (() => string) | string;
4546
}) => {
46-
const client = createClient(getConfig().apiUrl, {
47+
const client = createClient(engineEnv().VITE_APP_API_URL, {
4748
token: opts.engineToken,
4849
});
4950
return {
@@ -88,7 +89,7 @@ export const createGlobalContext = (opts: {
8889
mutationFn: async (data: CreateNamespace) => {
8990
const response = await client.namespaces.create({
9091
displayName: data.displayName,
91-
name: data.name || convertStringToId(data.displayName),
92+
name: convertStringToId(data.displayName),
9293
});
9394

9495
return {
@@ -133,7 +134,7 @@ export const createNamespaceContext = ({
133134
retry: shouldRetryAllExpect403,
134135
throwOnError: noThrow,
135136
meta: {
136-
mightRequireAuth: true,
137+
mightRequireAuth,
137138
},
138139
});
139140
},
@@ -158,7 +159,7 @@ export const createNamespaceContext = ({
158159
retry: shouldRetryAllExpect403,
159160
throwOnError: noThrow,
160161
meta: {
161-
mightRequireAuth: true,
162+
mightRequireAuth,
162163
},
163164
});
164165
},
@@ -187,7 +188,7 @@ export const createNamespaceContext = ({
187188
retry: shouldRetryAllExpect403,
188189
throwOnError: noThrow,
189190
meta: {
190-
mightRequireAuth: true,
191+
mightRequireAuth,
191192
},
192193
});
193194
},
@@ -214,7 +215,7 @@ export const createNamespaceContext = ({
214215
retry: shouldRetryAllExpect403,
215216
throwOnError: noThrow,
216217
meta: {
217-
mightRequireAuth: true,
218+
mightRequireAuth,
218219
},
219220
});
220221
},
@@ -289,7 +290,7 @@ export const createNamespaceContext = ({
289290
retry: shouldRetryAllExpect403,
290291
throwOnError: noThrow,
291292
meta: {
292-
mightRequireAuth: true,
293+
mightRequireAuth,
293294
},
294295
});
295296
},
@@ -330,7 +331,7 @@ export const createNamespaceContext = ({
330331
retry: shouldRetryAllExpect403,
331332
throwOnError: noThrow,
332333
meta: {
333-
mightRequireAuth: true,
334+
mightRequireAuth,
334335
},
335336
});
336337
},
@@ -354,7 +355,7 @@ export const createNamespaceContext = ({
354355
throwOnError: noThrow,
355356
retry: shouldRetryAllExpect403,
356357
meta: {
357-
mightRequireAuth: true,
358+
mightRequireAuth,
358359
},
359360
};
360361
},
@@ -364,7 +365,7 @@ export const createNamespaceContext = ({
364365
throwOnError: noThrow,
365366
retry: shouldRetryAllExpect403,
366367
meta: {
367-
mightRequireAuth: true,
368+
mightRequireAuth,
368369
},
369370
mutationFn: async () => {
370371
await client.actorsDelete(actorId);
@@ -375,14 +376,14 @@ export const createNamespaceContext = ({
375376

376377
return {
377378
...dataProvider,
378-
runnersQueryOptions(opts: { namespace: string }) {
379+
runnersQueryOptions() {
379380
return infiniteQueryOptions({
380-
queryKey: [opts.namespace, "runners"],
381+
queryKey: [{ namespace }, "runners"],
381382
initialPageParam: undefined as string | undefined,
382383
queryFn: async ({ pageParam, signal: abortSignal }) => {
383384
const data = await client.runners.list(
384385
{
385-
namespace: opts.namespace,
386+
namespace,
386387
cursor: pageParam ?? undefined,
387388
limit: RECORDS_PER_PAGE,
388389
},
@@ -399,7 +400,7 @@ export const createNamespaceContext = ({
399400
select: (data) => data.pages.flatMap((page) => page.runners),
400401
retry: shouldRetryAllExpect403,
401402
meta: {
402-
mightRequireAuth: true,
403+
mightRequireAuth,
403404
},
404405
});
405406
},
@@ -430,7 +431,7 @@ export const createNamespaceContext = ({
430431
retry: shouldRetryAllExpect403,
431432
throwOnError: noThrow,
432433
meta: {
433-
mightRequireAuth: true,
434+
mightRequireAuth,
434435
},
435436
});
436437
},
@@ -457,7 +458,7 @@ export const createNamespaceContext = ({
457458
throwOnError: noThrow,
458459
retry: shouldRetryAllExpect403,
459460
meta: {
460-
mightRequireAuth: true,
461+
mightRequireAuth,
461462
},
462463
});
463464
},
@@ -482,7 +483,7 @@ export const createNamespaceContext = ({
482483
},
483484
retry: shouldRetryAllExpect403,
484485
meta: {
485-
mightRequireAuth: true,
486+
mightRequireAuth,
486487
},
487488
});
488489
},
@@ -507,6 +508,10 @@ export const createNamespaceContext = ({
507508
});
508509
return response;
509510
},
511+
retry: shouldRetryAllExpect403,
512+
meta: {
513+
mightRequireAuth,
514+
},
510515
};
511516
},
512517
runnerConfigsQueryOptions() {
@@ -539,6 +544,25 @@ export const createNamespaceContext = ({
539544
}
540545
return lastPage.pagination.cursor;
541546
},
547+
548+
retryDelay: 50_000,
549+
retry: shouldRetryAllExpect403,
550+
meta: {
551+
mightRequireAuth,
552+
},
553+
});
554+
},
555+
connectRunnerTokenQueryOptions() {
556+
return queryOptions({
557+
staleTime: 1000,
558+
gcTime: 1000,
559+
queryKey: [{ namespace }, "runners", "connect"],
560+
queryFn: async () => {
561+
return ls.engineCredentials.get(getConfig().apiUrl) || "";
562+
},
563+
meta: {
564+
mightRequireAuth,
565+
},
542566
});
543567
},
544568
};

0 commit comments

Comments
 (0)