tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
27
pulls
pipelines
add token and dynamically lookup route
awarm.space
1 year ago
19562cd3
d3955f56
+155
-22
5 changed files
expand all
collapse all
unified
split
drizzle
relations.ts
schema.ts
middleware.ts
supabase
database.types.ts
migrations
20250117205106_add_token_to_custom_domain_routes.sql
+42
-21
drizzle/relations.ts
···
1
1
import { relations } from "drizzle-orm/relations";
2
2
-
import { entities, facts, entity_sets, permission_tokens, identities, email_subscriptions_to_entity, email_auth_tokens, phone_rsvps_to_entity, permission_token_on_homepage, permission_token_rights } from "./schema";
2
2
+
import { identities, custom_domains, custom_domain_routes, permission_tokens, entities, facts, entity_sets, email_subscriptions_to_entity, email_auth_tokens, phone_rsvps_to_entity, permission_token_on_homepage, permission_token_rights } from "./schema";
3
3
+
4
4
+
export const custom_domainsRelations = relations(custom_domains, ({one, many}) => ({
5
5
+
identity: one(identities, {
6
6
+
fields: [custom_domains.identity],
7
7
+
references: [identities.email]
8
8
+
}),
9
9
+
custom_domain_routes: many(custom_domain_routes),
10
10
+
}));
11
11
+
12
12
+
export const identitiesRelations = relations(identities, ({one, many}) => ({
13
13
+
custom_domains: many(custom_domains),
14
14
+
permission_token: one(permission_tokens, {
15
15
+
fields: [identities.home_page],
16
16
+
references: [permission_tokens.id]
17
17
+
}),
18
18
+
email_auth_tokens: many(email_auth_tokens),
19
19
+
permission_token_on_homepages: many(permission_token_on_homepage),
20
20
+
}));
21
21
+
22
22
+
export const custom_domain_routesRelations = relations(custom_domain_routes, ({one}) => ({
23
23
+
custom_domain: one(custom_domains, {
24
24
+
fields: [custom_domain_routes.domain],
25
25
+
references: [custom_domains.domain]
26
26
+
}),
27
27
+
permission_token: one(permission_tokens, {
28
28
+
fields: [custom_domain_routes.permission_token],
29
29
+
references: [permission_tokens.id]
30
30
+
}),
31
31
+
}));
32
32
+
33
33
+
export const permission_tokensRelations = relations(permission_tokens, ({one, many}) => ({
34
34
+
custom_domain_routes: many(custom_domain_routes),
35
35
+
entity: one(entities, {
36
36
+
fields: [permission_tokens.root_entity],
37
37
+
references: [entities.id]
38
38
+
}),
39
39
+
identities: many(identities),
40
40
+
email_subscriptions_to_entities: many(email_subscriptions_to_entity),
41
41
+
permission_token_on_homepages: many(permission_token_on_homepage),
42
42
+
permission_token_rights: many(permission_token_rights),
43
43
+
}));
3
44
4
45
export const factsRelations = relations(facts, ({one}) => ({
5
46
entity: one(entities, {
···
22
63
export const entity_setsRelations = relations(entity_sets, ({many}) => ({
23
64
entities: many(entities),
24
65
permission_token_rights: many(permission_token_rights),
25
25
-
}));
26
26
-
27
27
-
export const permission_tokensRelations = relations(permission_tokens, ({one, many}) => ({
28
28
-
entity: one(entities, {
29
29
-
fields: [permission_tokens.root_entity],
30
30
-
references: [entities.id]
31
31
-
}),
32
32
-
identities: many(identities),
33
33
-
email_subscriptions_to_entities: many(email_subscriptions_to_entity),
34
34
-
permission_token_on_homepages: many(permission_token_on_homepage),
35
35
-
permission_token_rights: many(permission_token_rights),
36
36
-
}));
37
37
-
38
38
-
export const identitiesRelations = relations(identities, ({one, many}) => ({
39
39
-
permission_token: one(permission_tokens, {
40
40
-
fields: [identities.home_page],
41
41
-
references: [permission_tokens.id]
42
42
-
}),
43
43
-
email_auth_tokens: many(email_auth_tokens),
44
44
-
permission_token_on_homepages: many(permission_token_on_homepage),
45
66
}));
46
67
47
68
export const email_subscriptions_to_entityRelations = relations(email_subscriptions_to_entity, ({one}) => ({
+25
-1
drizzle/schema.ts
···
1
1
-
import { pgTable, foreignKey, pgEnum, uuid, text, jsonb, timestamp, bigint, boolean, uniqueIndex, primaryKey } from "drizzle-orm/pg-core"
1
1
+
import { pgTable, foreignKey, pgEnum, text, boolean, unique, uuid, jsonb, timestamp, bigint, uniqueIndex, smallint, primaryKey } from "drizzle-orm/pg-core"
2
2
import { sql } from "drizzle-orm"
3
3
4
4
export const aal_level = pgEnum("aal_level", ['aal1', 'aal2', 'aal3'])
···
14
14
export const equality_op = pgEnum("equality_op", ['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in'])
15
15
16
16
17
17
+
export const custom_domains = pgTable("custom_domains", {
18
18
+
domain: text("domain").primaryKey().notNull(),
19
19
+
identity: text("identity").default('').notNull().references(() => identities.email, { onDelete: "cascade", onUpdate: "cascade" } ),
20
20
+
confirmed: boolean("confirmed").notNull(),
21
21
+
});
22
22
+
23
23
+
export const custom_domain_routes = pgTable("custom_domain_routes", {
24
24
+
id: uuid("id").defaultRandom().primaryKey().notNull(),
25
25
+
domain: text("domain").notNull().references(() => custom_domains.domain),
26
26
+
route: text("route").notNull(),
27
27
+
permission_token: uuid("permission_token").notNull().references(() => permission_tokens.id, { onDelete: "cascade", onUpdate: "cascade" } ),
28
28
+
},
29
29
+
(table) => {
30
30
+
return {
31
31
+
custom_domain_routes_domain_route_key: unique("custom_domain_routes_domain_route_key").on(table.domain, table.route),
32
32
+
}
33
33
+
});
34
34
+
17
35
export const facts = pgTable("facts", {
18
36
id: uuid("id").primaryKey().notNull(),
19
37
entity: uuid("entity").notNull().references(() => entities.id, { onDelete: "cascade", onUpdate: "restrict" } ),
···
53
71
created_at: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
54
72
home_page: uuid("home_page").notNull().references(() => permission_tokens.id, { onDelete: "cascade" } ),
55
73
email: text("email"),
74
74
+
},
75
75
+
(table) => {
76
76
+
return {
77
77
+
identities_email_key: unique("identities_email_key").on(table.email),
78
78
+
}
56
79
});
57
80
58
81
export const email_subscriptions_to_entity = pgTable("email_subscriptions_to_entity", {
···
91
114
entity: uuid("entity").notNull().references(() => entities.id, { onDelete: "cascade", onUpdate: "cascade" } ),
92
115
name: text("name").default('').notNull(),
93
116
country_code: text("country_code").notNull(),
117
117
+
plus_ones: smallint("plus_ones").default(0).notNull(),
94
118
},
95
119
(table) => {
96
120
return {
+16
middleware.ts
···
1
1
+
import { createClient } from "@supabase/supabase-js";
1
2
import { NextRequest, NextResponse } from "next/server";
3
3
+
import { Database } from "supabase/database.types";
2
4
3
5
export const config = {
4
6
matcher: [
···
13
15
],
14
16
};
15
17
18
18
+
let supabase = createClient<Database>(
19
19
+
process.env.NEXT_PUBLIC_SUPABASE_API_URL as string,
20
20
+
process.env.SUPABASE_SERVICE_ROLE_KEY as string,
21
21
+
);
16
22
export default async function middleware(req: NextRequest) {
17
23
let hostname = req.headers.get("host")!;
24
24
+
if (hostname === "leaflet.pub") return;
25
25
+
let { data: route } = await supabase
26
26
+
.from("custom_domain_routes")
27
27
+
.select("*")
28
28
+
.eq("domain", hostname)
29
29
+
.eq("route", req.nextUrl.pathname)
30
30
+
.single();
31
31
+
if (route)
32
32
+
return NextResponse.rewrite(new URL(`/${route.permission_token}`, req.url));
33
33
+
18
34
if (hostname === "guilds.nyc")
19
35
return NextResponse.rewrite(
20
36
new URL("/b64bc712-c9c1-4ed3-a8f4-d33f33d3bfdb", req.url),
+65
supabase/database.types.ts
···
34
34
}
35
35
public: {
36
36
Tables: {
37
37
+
custom_domain_routes: {
38
38
+
Row: {
39
39
+
domain: string
40
40
+
id: string
41
41
+
permission_token: string
42
42
+
route: string
43
43
+
}
44
44
+
Insert: {
45
45
+
domain: string
46
46
+
id?: string
47
47
+
permission_token: string
48
48
+
route: string
49
49
+
}
50
50
+
Update: {
51
51
+
domain?: string
52
52
+
id?: string
53
53
+
permission_token?: string
54
54
+
route?: string
55
55
+
}
56
56
+
Relationships: [
57
57
+
{
58
58
+
foreignKeyName: "custom_domain_routes_domain_fkey"
59
59
+
columns: ["domain"]
60
60
+
isOneToOne: false
61
61
+
referencedRelation: "custom_domains"
62
62
+
referencedColumns: ["domain"]
63
63
+
},
64
64
+
{
65
65
+
foreignKeyName: "custom_domain_routes_permission_token_fkey"
66
66
+
columns: ["permission_token"]
67
67
+
isOneToOne: false
68
68
+
referencedRelation: "permission_tokens"
69
69
+
referencedColumns: ["id"]
70
70
+
},
71
71
+
]
72
72
+
}
73
73
+
custom_domains: {
74
74
+
Row: {
75
75
+
confirmed: boolean
76
76
+
domain: string
77
77
+
identity: string
78
78
+
}
79
79
+
Insert: {
80
80
+
confirmed: boolean
81
81
+
domain: string
82
82
+
identity?: string
83
83
+
}
84
84
+
Update: {
85
85
+
confirmed?: boolean
86
86
+
domain?: string
87
87
+
identity?: string
88
88
+
}
89
89
+
Relationships: [
90
90
+
{
91
91
+
foreignKeyName: "custom_domains_identity_fkey"
92
92
+
columns: ["identity"]
93
93
+
isOneToOne: false
94
94
+
referencedRelation: "identities"
95
95
+
referencedColumns: ["email"]
96
96
+
},
97
97
+
]
98
98
+
}
37
99
email_auth_tokens: {
38
100
Row: {
39
101
confirmation_code: string
···
358
420
id: string
359
421
name: string
360
422
phone_number: string
423
423
+
plus_ones: number
361
424
status: Database["public"]["Enums"]["rsvp_status"]
362
425
}
363
426
Insert: {
···
367
430
id?: string
368
431
name?: string
369
432
phone_number: string
433
433
+
plus_ones?: number
370
434
status: Database["public"]["Enums"]["rsvp_status"]
371
435
}
372
436
Update: {
···
376
440
id?: string
377
441
name?: string
378
442
phone_number?: string
443
443
+
plus_ones?: number
379
444
status?: Database["public"]["Enums"]["rsvp_status"]
380
445
}
381
446
Relationships: [
+7
supabase/migrations/20250117205106_add_token_to_custom_domain_routes.sql
···
1
1
+
alter table "public"."custom_domain_routes" add column "permission_token" uuid not null;
2
2
+
3
3
+
alter table "public"."custom_domain_routes" enable row level security;
4
4
+
5
5
+
alter table "public"."custom_domain_routes" add constraint "custom_domain_routes_permission_token_fkey" FOREIGN KEY (permission_token) REFERENCES permission_tokens(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
6
6
+
7
7
+
alter table "public"."custom_domain_routes" validate constraint "custom_domain_routes_permission_token_fkey";