Skip to content

Commit cd087c5

Browse files
authored
Merge branch 'dev' into local-emulator-image-optimization
2 parents d724eb2 + 9e342da commit cd087c5

48 files changed

Lines changed: 296 additions & 24869 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/db-migration-backwards-compatibility.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ jobs:
200200
uses: JarvusInnovations/background-action@v1.0.7
201201
if: ${{ hashFiles('apps/backend/scripts/run-cron-jobs.ts') != '' }}
202202
with:
203-
run: pnpm -C apps/backend run with-env:dev tsx scripts/run-cron-jobs.ts --log-order=stream &
203+
run: pnpm -C apps/backend run run-cron-jobs:test --log-order=stream &
204204
wait-on: |
205205
http://localhost:8102
206206
tail: true
@@ -394,7 +394,7 @@ jobs:
394394
uses: JarvusInnovations/background-action@v1.0.7
395395
if: ${{ hashFiles('apps/backend/scripts/run-cron-jobs.ts') != '' }}
396396
with:
397-
run: pnpm -C apps/backend run with-env:dev tsx scripts/run-cron-jobs.ts --log-order=stream &
397+
run: pnpm -C apps/backend run run-cron-jobs:test --log-order=stream &
398398
wait-on: |
399399
http://localhost:8102
400400
tail: true

.github/workflows/e2e-custom-base-port-api-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ jobs:
145145
- name: Start run-cron-jobs in background
146146
uses: JarvusInnovations/background-action@v1.0.7
147147
with:
148-
run: pnpm -C apps/backend run run-cron-jobs --log-order=stream &
148+
run: pnpm -C apps/backend run run-cron-jobs:test --log-order=stream &
149149
wait-on: |
150150
http://localhost:6702
151151
tail: true

apps/backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@stackframe/backend",
3-
"version": "2.8.80",
3+
"version": "2.8.81",
44
"repository": "https://github.com/stack-auth/stack-auth",
55
"private": true,
66
"type": "module",

apps/backend/scripts/verify-data-integrity/clickhouse-sync-verifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const SORT_KEYS = {
1818
team_invitations: ["id"],
1919
email_outboxes: ["id"],
2020
project_permissions: ["user_id", "permission_id"],
21-
notification_preferences: ["id"],
21+
notification_preferences: ["user_id", "notification_category_id"],
2222
refresh_tokens: ["id"],
2323
connected_accounts: ["user_id", "provider", "provider_account_id"],
2424
} satisfies Record<keyof typeof DEFAULT_DB_SYNC_MAPPINGS, string[]>;

apps/backend/scripts/verify-data-integrity/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { syncExternalDatabases } from "@/lib/external-db-sync";
12
import { DEFAULT_BRANCH_ID, getSoleTenancyFromProjectBranch } from "@/lib/tenancies";
23
import { getPrismaClientForTenancy, globalPrismaClient } from "@/prisma-client";
34
import type { OrganizationRenderedConfig } from "@stackframe/stack-shared/dist/config/schema";
@@ -228,6 +229,10 @@ async function main() {
228229

229230
if (!shouldSkipClickhouse && clickhouseAvailable && tenancy) {
230231
await recurse("[clickhouse sync]", async (recurse) => {
232+
// Flush any pending ClickHouse syncs by running a direct sync before verifying.
233+
// This avoids race conditions where QStash hasn't delivered all sync callbacks yet.
234+
await syncExternalDatabases(tenancy);
235+
231236
await verifyClickhouseSync({
232237
tenancy,
233238
projectId,

apps/backend/src/lib/emailable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async function verifyWithRetries(verifyFn: () => Promise<unknown>, maxAttempts:
4343
for (let i = 0; i < maxAttempts; i++) {
4444
const res: any = await verifyFn();
4545
if (!("state" in res)) {
46-
if ("message" in res && res.message.includes("Your request is taking longer than normal")) {
46+
if ("message" in res && (res.message.includes("Your request is taking longer than normal") || res.message.includes("Your email is still being verified"))) {
4747
await wait((Math.random() + 0.5) * delayBaseMs * (2 ** i));
4848
continue;
4949
}

apps/backend/src/oauth/providers/base.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export abstract class OAuthBaseProvider {
4747
public readonly defaultAccessTokenExpiresInMillis?: number,
4848
public readonly noPKCE?: boolean,
4949
public readonly openid?: boolean,
50+
public readonly alternativeIssuers?: string[],
5051
) {}
5152

5253
protected static async createConstructorArgs(options:
@@ -59,6 +60,7 @@ export abstract class OAuthBaseProvider {
5960
defaultAccessTokenExpiresInMillis?: number,
6061
tokenEndpointAuthMethod?: "client_secret_post" | "client_secret_basic",
6162
noPKCE?: boolean,
63+
alternativeIssuers?: string[],
6264
}
6365
& (
6466
| ({
@@ -106,6 +108,7 @@ export abstract class OAuthBaseProvider {
106108
options.defaultAccessTokenExpiresInMillis,
107109
options.noPKCE,
108110
options.openid,
111+
options.alternativeIssuers,
109112
] as const;
110113
}
111114

@@ -134,9 +137,22 @@ export abstract class OAuthBaseProvider {
134137
state: string,
135138
}): Promise<{ userInfo: OAuthUserInfo, tokenSet: TokenSet }> {
136139
let tokenSet;
140+
const callbackParams = { ...options.callbackParams };
141+
142+
// If the authorization server returns an `iss` parameter (RFC 9207) that matches
143+
// one of the known alternative issuers, rewrite it to the configured issuer so
144+
// openid-client's validation accepts it.
145+
if (
146+
this.alternativeIssuers
147+
&& typeof callbackParams.iss === "string"
148+
&& this.alternativeIssuers.includes(callbackParams.iss)
149+
) {
150+
callbackParams.iss = this.oauthClient.issuer.metadata.issuer;
151+
}
152+
137153
const params = [
138154
this.redirectUri,
139-
options.callbackParams,
155+
callbackParams,
140156
{
141157
code_verifier: this.noPKCE ? undefined : options.codeVerifier,
142158
state: options.state,

apps/backend/src/oauth/providers/github.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class GithubProvider extends OAuthBaseProvider {
1717
}) {
1818
return new GithubProvider(...await OAuthBaseProvider.createConstructorArgs({
1919
issuer: "https://github.com",
20+
alternativeIssuers: ["https://github.com/login/oauth"],
2021
authorizationEndpoint: "https://github.com/login/oauth/authorize",
2122
tokenEndpoint: "https://github.com/login/oauth/access_token",
2223
userinfoEndpoint: "https://api.github.com/user",

apps/dashboard/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@stackframe/dashboard",
3-
"version": "2.8.80",
3+
"version": "2.8.81",
44
"repository": "https://github.com/stack-auth/stack-auth",
55
"private": true,
66
"scripts": {

0 commit comments

Comments
 (0)