Skip to content

Commit e657cca

Browse files
auth checks
1 parent 7978bc6 commit e657cca

File tree

6 files changed

+34
-14
lines changed

6 files changed

+34
-14
lines changed

apps/client/src/routes/$workspaceId/token.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ function RouteComponent() {
4646
scope: "read_write",
4747
},
4848
});
49+
50+
yield* Effect.promise(() => router.invalidate({ sync: true }));
4951
})
5052
);
5153

apps/server/src/group/sync-auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const SyncAuthGroupLive = HttpApiBuilder.group(
2525

2626
const scope: typeof Scope.Type = "read_write";
2727
const isMaster = true;
28-
const issuedAt = new Date();
28+
const issuedAt = DateTime.toDate(yield* DateTime.now);
2929

3030
yield* query({
3131
Request: Schema.Struct({ workspaceId: Schema.String }),

apps/server/src/group/sync-data.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { HttpApiBuilder } from "@effect/platform";
22
import { AuthWorkspace, SyncApi } from "@local/sync";
33
import { SnapshotToLoroDoc } from "@local/sync/loro";
4-
import { and, desc, eq } from "drizzle-orm";
4+
import { and, desc, eq, gt, isNull, or } from "drizzle-orm";
55
import { Array, Effect, Layer, Schema } from "effect";
66
import { tokenTable, workspaceTable } from "../db/schema";
77
import { AuthorizationLive } from "../middleware/authorization";
@@ -24,8 +24,7 @@ export const SyncDataGroupLive = HttpApiBuilder.group(
2424

2525
yield* Effect.log(`Pushing workspace ${workspaceId}`);
2626

27-
doc.import(workspace.snapshot); // 🪄
28-
27+
doc.import(workspace.snapshot);
2928
const newSnapshot = yield* Schema.encode(SnapshotToLoroDoc)(doc);
3029

3130
const newWorkspace = yield* query({
@@ -69,7 +68,15 @@ export const SyncDataGroupLive = HttpApiBuilder.group(
6968
.where(
7069
and(
7170
eq(tokenTable.workspaceId, workspaceId),
72-
eq(tokenTable.clientId, clientId)
71+
eq(tokenTable.clientId, clientId),
72+
or(
73+
isNull(tokenTable.revokedAt),
74+
gt(tokenTable.revokedAt, new Date())
75+
),
76+
or(
77+
isNull(tokenTable.expiresAt),
78+
gt(tokenTable.expiresAt, new Date())
79+
)
7380
)
7481
)
7582
.orderBy(desc(tokenTable.issuedAt))

apps/server/src/middleware/authorization.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export const AuthorizationLive = Layer.effect(
4040
and(
4141
eq(tokenTable.workspaceId, workspaceId),
4242
eq(tokenTable.clientId, clientId),
43+
or(
44+
isNull(tokenTable.revokedAt),
45+
gt(tokenTable.revokedAt, new Date())
46+
),
4347
or(
4448
isNull(tokenTable.expiresAt),
4549
gt(tokenTable.expiresAt, new Date())
@@ -54,7 +58,12 @@ export const AuthorizationLive = Layer.effect(
5458
}).pipe(
5559
Effect.flatMap(Array.head),
5660
Effect.tapError(Effect.logError),
57-
Effect.mapError(() => new Unauthorized())
61+
Effect.mapError(
62+
() =>
63+
new Unauthorized({
64+
message: "Missing, expired, or revoked token",
65+
})
66+
)
5867
);
5968

6069
return yield* query({
@@ -76,9 +85,10 @@ export const AuthorizationLive = Layer.effect(
7685
Match.value(error).pipe(
7786
Match.tagsExhaustive({
7887
NoSuchElementException: () => new MissingWorkspace(),
79-
Unauthorized: () => new Unauthorized(),
80-
JwtError: () => new Unauthorized(),
81-
ParseError: () => new Unauthorized(),
88+
Unauthorized: (error) => error,
89+
JwtError: () => new Unauthorized({ message: "Invalid token" }),
90+
ParseError: () =>
91+
new Unauthorized({ message: "Invalid parameters" }),
8292
QueryError: () => new DatabaseError(),
8393
})
8494
)

apps/server/src/middleware/master-authorization.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ export const MasterAuthorizationLive = Layer.effect(
4747
}).pipe(Effect.flatMap(Array.head));
4848
}
4949

50-
return yield* new Unauthorized();
50+
return yield* new Unauthorized({ message: "Not master access" });
5151
}).pipe(
5252
Effect.mapError((error) =>
5353
Match.value(error).pipe(
5454
Match.tagsExhaustive({
5555
NoSuchElementException: () => new MissingWorkspace(),
56-
Unauthorized: () => new Unauthorized(),
57-
JwtError: () => new Unauthorized(),
58-
ParseError: () => new Unauthorized(),
56+
Unauthorized: (error) => error,
57+
JwtError: () => new Unauthorized({ message: "Invalid token" }),
58+
ParseError: () =>
59+
new Unauthorized({ message: "Invalid parameters" }),
5960
QueryError: () => new DatabaseError(),
6061
})
6162
)

packages/sync/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { Snapshot } from "./loro";
1111

1212
export class Unauthorized extends Schema.TaggedError<Unauthorized>()(
1313
"Unauthorized",
14-
{},
14+
{ message: Schema.String },
1515
HttpApiSchema.annotations({ status: 401 })
1616
) {}
1717

0 commit comments

Comments
 (0)