Skip to content

Commit 46c76ae

Browse files
committed
WIP
1 parent fe669c9 commit 46c76ae

35 files changed

+1867
-565
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@
144144
"bentocache": "patches/bentocache.patch",
145145
"nextra": "patches/nextra.patch",
146146
"nextra-theme-docs": "patches/nextra-theme-docs.patch",
147-
"@graphql-codegen/schema-ast": "patches/@graphql-codegen__schema-ast.patch"
147+
"@graphql-codegen/schema-ast": "patches/@graphql-codegen__schema-ast.patch",
148+
"@better-auth/core": "patches/@better-auth__core.patch"
148149
}
149150
}
150151
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { type MigrationExecutor } from '../pg-migrator';
2+
3+
/**
4+
* Initializes DB for Better Auth and migrates SuperTokens auth data to it
5+
*/
6+
export default {
7+
name: '2025.10.24T00-00-00.better-auth.ts',
8+
noTransaction: true,
9+
run: ({ sql }) => [
10+
{
11+
name: 'Setup better-auth tables',
12+
query: sql`
13+
CREATE TABLE IF NOT EXISTS "better_auth_users" (
14+
"id" text NOT NULL PRIMARY KEY
15+
, "name" text NOT NULL
16+
, "email" text NOT NULL UNIQUE
17+
, "emailVerified" boolean NOT NULL DEFAULT FALSE
18+
, "image" text
19+
, "createdAt" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL
20+
, "updatedAt" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL
21+
);
22+
23+
CREATE TABLE IF NOT EXISTS "better_auth_sessions" (
24+
"id" text NOT NULL PRIMARY KEY
25+
, "expiresAt" timestamptz NOT NULL
26+
, "token" text NOT NULL UNIQUE
27+
, "createdAt" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL
28+
, "updatedAt" timestamptz NOT NULL
29+
, "ipAddress" text
30+
, "userAgent" text
31+
, "userId" text NOT NULL REFERENCES "better_auth_users" ("id") ON DELETE CASCADE
32+
);
33+
34+
CREATE TABLE IF NOT EXISTS "better_auth_accounts" (
35+
"id" text NOT NULL PRIMARY KEY
36+
, "accountId" text NOT NULL
37+
, "providerId" text NOT NULL
38+
, "userId" text NOT NULL REFERENCES "better_auth_users" ("id") ON DELETE CASCADE
39+
, "accessToken" text
40+
, "refreshToken" text
41+
, "idToken" text
42+
, "accessTokenExpiresAt" timestamptz
43+
, "refreshTokenExpiresAt" timestamptz
44+
, "scope" text
45+
, "password" text
46+
, "createdAt" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL
47+
, "updatedAt" timestamptz NOT NULL
48+
);
49+
50+
CREATE TABLE IF NOT EXISTS "better_auth_verifications" (
51+
"id" text NOT NULL PRIMARY KEY
52+
, "identifier" text NOT NULL
53+
, "value" text NOT NULL
54+
, "expiresAt" timestamptz NOT NULL
55+
, "createdAt" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL
56+
, "updatedAt" timestamptz NOT NULL
57+
);
58+
59+
CREATE TABLE IF NOT EXISTS "better_auth_sso_providers" (
60+
"id" text NOT NULL PRIMARY KEY
61+
, "issuer" text NOT NULL
62+
, "oidcConfig" text
63+
, "samlConfig" text
64+
, "userId" text NOT NULL REFERENCES "better_auth_users" ("id") ON DELETE CASCADE
65+
, "providerId" text NOT NULL UNIQUE
66+
, "organizationId" text
67+
, "domain" text NOT NULL
68+
);
69+
`,
70+
},
71+
{
72+
name: 'Migrate emailpassword users and accounts',
73+
query: sql`
74+
INSERT INTO "better_auth_users"
75+
("id", "name", "email", "createdAt")
76+
SELECT
77+
"sepu"."user_id" AS "id",
78+
"u"."full_name" AS "name",
79+
"sepu"."email" AS "email",
80+
TO_TIMESTAMP("sepu"."time_joined" / 1000.0) AS "createdAt"
81+
FROM "supertokens_emailpassword_users" "sepu"
82+
INNER JOIN "users" "u"
83+
ON "sepu"."user_id" = "u"."supertoken_user_id"
84+
ON CONFLICT DO NOTHING;
85+
86+
INSERT INTO "better_auth_accounts"
87+
("id", "accountId", "providerId", "userId", "password", "createdAt", "updatedAt")
88+
SELECT
89+
REPLACE(uuid_generate_v4()::text, '-', '') AS "id",
90+
"sepu"."user_id" AS "accountId",
91+
'credential' AS "providerId",
92+
"sepu"."user_id" AS "userId",
93+
"sepu"."password_hash" AS "password",
94+
TO_TIMESTAMP("sepu"."time_joined" / 1000.0) AS "createdAt",
95+
CURRENT_TIMESTAMP AS "updatedAt"
96+
FROM "supertokens_emailpassword_users" "sepu"
97+
INNER JOIN "users" "u"
98+
ON "sepu"."user_id" = "u"."supertoken_user_id";
99+
`,
100+
},
101+
{
102+
name: "Migrate thirdparty users and accounts",
103+
query: sql`
104+
INSERT INTO "better_auth_users"
105+
("id", "name", "email", "createdAt")
106+
SELECT
107+
"stpu"."user_id" AS "id",
108+
"u"."full_name" AS "name",
109+
"stpu"."email" AS "email",
110+
TO_TIMESTAMP("stpu"."time_joined" / 1000.0) AS "createdAt"
111+
FROM "supertokens_thirdparty_users" "stpu"
112+
INNER JOIN "users" "u"
113+
ON "stpu"."user_id" = "u"."supertoken_user_id";
114+
115+
INSERT INTO "better_auth_accounts"
116+
("id", "accountId", "providerId", "userId", "createdAt", "updatedAt")
117+
SELECT
118+
REPLACE(uuid_generate_v4()::text, '-', '') AS "id",
119+
"stpu"."third_party_user_id" AS "accountId",
120+
"stpu"."third_party_id" AS "providerId",
121+
"stpu"."user_id" AS "userId",
122+
TO_TIMESTAMP("supertokens_thirdparty_users"."time_joined" / 1000.0) AS "createdAt",
123+
CURRENT_TIMESTAMP AS "updatedAt"
124+
FROM "supertokens_thirdparty_users" "stpu"
125+
INNER JOIN "users" "u"
126+
ON "stpu"."user_id" = "u"."supertoken_user_id";
127+
`,
128+
},
129+
{
130+
name: 'Migrate email verifications',
131+
query: sql`
132+
UPDATE "better_auth_users" "bau"
133+
SET "emailVerified" = TRUE
134+
WHERE "bau"."email" IN (
135+
SELECT "email" FROM "supertokens_emailverification_verified_emails"
136+
);
137+
`,
138+
},
139+
],
140+
} satisfies MigrationExecutor;

packages/services/api/src/create.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { AuditLogRecorder } from './modules/audit-logs/providers/audit-log-recor
1010
import { AuditLogS3Config } from './modules/audit-logs/providers/audit-logs-manager';
1111
import { authModule } from './modules/auth';
1212
import { Session } from './modules/auth/lib/authz';
13+
import { AuthInstance, provideAuthInstance } from './modules/auth/providers/auth-instance';
1314
import { cdnModule } from './modules/cdn';
1415
import { AwsClient } from './modules/cdn/providers/aws';
1516
import { CDN_CONFIG, CDNConfig } from './modules/cdn/providers/tokens';
@@ -114,6 +115,7 @@ export function createRegistry({
114115
pubSub,
115116
appDeploymentsEnabled,
116117
prometheus,
118+
authInstance,
117119
}: {
118120
logger: Logger;
119121
storage: Storage;
@@ -158,6 +160,7 @@ export function createRegistry({
158160
pubSub: HivePubSub;
159161
appDeploymentsEnabled: boolean;
160162
prometheus: null | Record<string, unknown>;
163+
authInstance: AuthInstance;
161164
}) {
162165
const s3Config: S3Config = [
163166
{
@@ -298,6 +301,7 @@ export function createRegistry({
298301
encryptionSecretProvider(encryptionSecret),
299302
provideSchemaModuleConfig(schemaConfig),
300303
provideCommerceConfig(commerce),
304+
provideAuthInstance(authInstance),
301305
{
302306
provide: Session,
303307
useFactory(context: { session: Session }) {

packages/services/api/src/modules/auth/lib/authz.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export abstract class Session {
9292

9393
/**
9494
* Retrieve the Viewer of the session.
95-
* A viewer can only be a {User} aka {SuperTokensSessions{}.
95+
* A viewer can only be a {User}.
9696
* If the session does not have a user an exception is raised.
9797
*/
9898
public async getViewer(): Promise<User> {
@@ -539,7 +539,7 @@ class UnauthenticatedSession extends Session {
539539

540540
/**
541541
* Strategy to authenticate a session from an incoming request.
542-
* E.g. SuperTokens, JWT, etc.
542+
* E.g. Better Auth, JWT, etc.
543543
*/
544544
export abstract class AuthNStrategy<TSession extends Session> {
545545
/**

0 commit comments

Comments
 (0)