@protobase/server 0.66.1 → 0.66.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/better-auth/auth-settings.d.ts +47 -0
- package/dist/better-auth/create-auth.d.ts +47 -0
- package/dist/better-auth/create-auth.js +3 -1
- package/dist/package.js +1 -1
- package/dist/personal-mail/linked-accounts.js +3 -2
- package/dist/personal-mail/mail-link-hooks.js +34 -0
- package/dist/personal-mail/personal-mailer.js +6 -2
- package/package.json +4 -4
|
@@ -8714,6 +8714,53 @@ export declare const buildAppAuth: (settings: AuthSettings, input: AppAuthInput)
|
|
|
8714
8714
|
}, ctx: ReplacingContext | null) => Promise<void>;
|
|
8715
8715
|
};
|
|
8716
8716
|
};
|
|
8717
|
+
account: {
|
|
8718
|
+
create?: {
|
|
8719
|
+
before?: (account: import("better-auth").Account, context: import("better-auth").GenericEndpointContext | null) => Promise<boolean | void | {
|
|
8720
|
+
data: {
|
|
8721
|
+
id?: string | undefined;
|
|
8722
|
+
createdAt?: Date | undefined;
|
|
8723
|
+
updatedAt?: Date | undefined;
|
|
8724
|
+
providerId?: string | undefined;
|
|
8725
|
+
accountId?: string | undefined;
|
|
8726
|
+
userId?: string | undefined;
|
|
8727
|
+
accessToken?: string | null | undefined;
|
|
8728
|
+
refreshToken?: string | null | undefined;
|
|
8729
|
+
idToken?: string | null | undefined;
|
|
8730
|
+
accessTokenExpiresAt?: Date | null | undefined;
|
|
8731
|
+
refreshTokenExpiresAt?: Date | null | undefined;
|
|
8732
|
+
scope?: string | null | undefined;
|
|
8733
|
+
password?: string | null | undefined;
|
|
8734
|
+
} & Record<string, any>;
|
|
8735
|
+
}>;
|
|
8736
|
+
after?: (account: import("better-auth").Account, context: import("better-auth").GenericEndpointContext | null) => Promise<void>;
|
|
8737
|
+
};
|
|
8738
|
+
update?: {
|
|
8739
|
+
before?: (account: Partial<import("better-auth").Account> & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<boolean | void | {
|
|
8740
|
+
data: {
|
|
8741
|
+
[x: string]: any;
|
|
8742
|
+
id?: string | undefined;
|
|
8743
|
+
createdAt?: Date | undefined;
|
|
8744
|
+
updatedAt?: Date | undefined;
|
|
8745
|
+
providerId?: string | undefined;
|
|
8746
|
+
accountId?: string | undefined;
|
|
8747
|
+
userId?: string | undefined;
|
|
8748
|
+
accessToken?: string | null | undefined;
|
|
8749
|
+
refreshToken?: string | null | undefined;
|
|
8750
|
+
idToken?: string | null | undefined;
|
|
8751
|
+
accessTokenExpiresAt?: Date | null | undefined;
|
|
8752
|
+
refreshTokenExpiresAt?: Date | null | undefined;
|
|
8753
|
+
scope?: string | null | undefined;
|
|
8754
|
+
password?: string | null | undefined;
|
|
8755
|
+
};
|
|
8756
|
+
}>;
|
|
8757
|
+
after?: (account: import("better-auth").Account & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<void>;
|
|
8758
|
+
};
|
|
8759
|
+
delete?: {
|
|
8760
|
+
before?: (account: import("better-auth").Account & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<boolean | void>;
|
|
8761
|
+
after?: (account: import("better-auth").Account & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<void>;
|
|
8762
|
+
};
|
|
8763
|
+
};
|
|
8717
8764
|
};
|
|
8718
8765
|
rateLimit: {
|
|
8719
8766
|
enabled: true;
|
|
@@ -8832,6 +8832,53 @@ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlug
|
|
|
8832
8832
|
}, ctx: ReplacingContext | null) => Promise<void>;
|
|
8833
8833
|
};
|
|
8834
8834
|
};
|
|
8835
|
+
account: {
|
|
8836
|
+
create?: {
|
|
8837
|
+
before?: (account: import("better-auth").Account, context: import("better-auth").GenericEndpointContext | null) => Promise<boolean | void | {
|
|
8838
|
+
data: {
|
|
8839
|
+
id?: string | undefined;
|
|
8840
|
+
createdAt?: Date | undefined;
|
|
8841
|
+
updatedAt?: Date | undefined;
|
|
8842
|
+
providerId?: string | undefined;
|
|
8843
|
+
accountId?: string | undefined;
|
|
8844
|
+
userId?: string | undefined;
|
|
8845
|
+
accessToken?: string | null | undefined;
|
|
8846
|
+
refreshToken?: string | null | undefined;
|
|
8847
|
+
idToken?: string | null | undefined;
|
|
8848
|
+
accessTokenExpiresAt?: Date | null | undefined;
|
|
8849
|
+
refreshTokenExpiresAt?: Date | null | undefined;
|
|
8850
|
+
scope?: string | null | undefined;
|
|
8851
|
+
password?: string | null | undefined;
|
|
8852
|
+
} & Record<string, any>;
|
|
8853
|
+
}>;
|
|
8854
|
+
after?: (account: import("better-auth").Account, context: import("better-auth").GenericEndpointContext | null) => Promise<void>;
|
|
8855
|
+
};
|
|
8856
|
+
update?: {
|
|
8857
|
+
before?: (account: Partial<import("better-auth").Account> & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<boolean | void | {
|
|
8858
|
+
data: {
|
|
8859
|
+
[x: string]: any;
|
|
8860
|
+
id?: string | undefined;
|
|
8861
|
+
createdAt?: Date | undefined;
|
|
8862
|
+
updatedAt?: Date | undefined;
|
|
8863
|
+
providerId?: string | undefined;
|
|
8864
|
+
accountId?: string | undefined;
|
|
8865
|
+
userId?: string | undefined;
|
|
8866
|
+
accessToken?: string | null | undefined;
|
|
8867
|
+
refreshToken?: string | null | undefined;
|
|
8868
|
+
idToken?: string | null | undefined;
|
|
8869
|
+
accessTokenExpiresAt?: Date | null | undefined;
|
|
8870
|
+
refreshTokenExpiresAt?: Date | null | undefined;
|
|
8871
|
+
scope?: string | null | undefined;
|
|
8872
|
+
password?: string | null | undefined;
|
|
8873
|
+
};
|
|
8874
|
+
}>;
|
|
8875
|
+
after?: (account: import("better-auth").Account & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<void>;
|
|
8876
|
+
};
|
|
8877
|
+
delete?: {
|
|
8878
|
+
before?: (account: import("better-auth").Account & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<boolean | void>;
|
|
8879
|
+
after?: (account: import("better-auth").Account & Record<string, unknown>, context: import("better-auth").GenericEndpointContext | null) => Promise<void>;
|
|
8880
|
+
};
|
|
8881
|
+
};
|
|
8835
8882
|
};
|
|
8836
8883
|
rateLimit: {
|
|
8837
8884
|
enabled: true;
|
|
@@ -8,6 +8,7 @@ import { goTrueSessionsPlugin } from "../gotrue/sessions-plugin.js";
|
|
|
8
8
|
import { betterAuthLinkedAccounts } from "../personal-mail/linked-accounts.js";
|
|
9
9
|
import { resolvePersonalMail } from "../personal-mail/personal-mail-providers.js";
|
|
10
10
|
import { personalMailer } from "../personal-mail/personal-mailer.js";
|
|
11
|
+
import { mailLinkHooks } from "../personal-mail/mail-link-hooks.js";
|
|
11
12
|
import { endReplacedSession } from "./end-replaced-session.js";
|
|
12
13
|
import { authBasePath } from "./auth-base-path.js";
|
|
13
14
|
import { authLogger } from "./auth-logger.js";
|
|
@@ -299,7 +300,8 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
|
|
|
299
300
|
},
|
|
300
301
|
update: { before: async (user) => ({ data: confirmedOnUpdate(user, /* @__PURE__ */ new Date()) }) }
|
|
301
302
|
},
|
|
302
|
-
session: withEndedReplaced(organizations ? sessionOrganizationHooks(context) : {})
|
|
303
|
+
session: withEndedReplaced(organizations ? sessionOrganizationHooks(context) : {}),
|
|
304
|
+
account: mailLinkHooks(resolvePersonalMail(options.personalMail ?? [], Object.keys(options.socialProviders ?? {}), options.encryptOAuthTokens === true))
|
|
303
305
|
},
|
|
304
306
|
rateLimit: {
|
|
305
307
|
enabled: true,
|
package/dist/package.js
CHANGED
|
@@ -12,7 +12,8 @@ const betterAuthLinkedAccounts = (auth) => ({
|
|
|
12
12
|
return (await (await auth.$context).internalAdapter.findAccounts(userId)).map((account) => ({
|
|
13
13
|
id: account.id,
|
|
14
14
|
providerId: account.providerId,
|
|
15
|
-
scopes: storedScopes(account.scope)
|
|
15
|
+
scopes: storedScopes(account.scope),
|
|
16
|
+
createdAt: account.createdAt
|
|
16
17
|
}));
|
|
17
18
|
},
|
|
18
19
|
accessToken: async (userId, account, provider) => {
|
|
@@ -33,4 +34,4 @@ const validAccessToken = async (auth, userId, accountId, provider) => {
|
|
|
33
34
|
}
|
|
34
35
|
};
|
|
35
36
|
//#endregion
|
|
36
|
-
export { betterAuthLinkedAccounts };
|
|
37
|
+
export { betterAuthLinkedAccounts, storedScopes };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { storedScopes } from "./linked-accounts.js";
|
|
2
|
+
import { getOAuthState } from "better-auth/api";
|
|
3
|
+
//#region src/personal-mail/mail-link-hooks.ts
|
|
4
|
+
const holds = (scope, scopes) => scopes.every((wanted) => storedScopes(scope).includes(wanted));
|
|
5
|
+
/** The mail provider whose scopes `account` holds, of the app's `providers`. */
|
|
6
|
+
const mailProviderOf = (providers, account) => providers.find((candidate) => candidate.signInProvider === account.providerId && holds(account.scope, candidate.scopes));
|
|
7
|
+
/**
|
|
8
|
+
* The new scopes of `userAccounts` once `linked` holds `provider`'s mail scopes: each other account of its sign-in
|
|
9
|
+
* provider that holds them too loses them, so mail goes through `linked` alone.
|
|
10
|
+
*/
|
|
11
|
+
const scopesHandedOver = (provider, linked, userAccounts) => userAccounts.filter((account) => account.id !== linked.id && account.providerId === linked.providerId && holds(account.scope, provider.scopes)).map((account) => ({
|
|
12
|
+
id: account.id,
|
|
13
|
+
scope: storedScopes(account.scope).filter((scope) => !provider.scopes.includes(scope)).join(",") || null
|
|
14
|
+
}));
|
|
15
|
+
/**
|
|
16
|
+
* Better Auth's `databaseHooks.account`: an account written by a link, whose OAuth state names the person it links to,
|
|
17
|
+
* becomes the one mail goes through when it holds a mail provider's scopes (see `scopesHandedOver`); other writes read nothing. Only a link
|
|
18
|
+
* writes an existing account's scopes: a sign-in or a token refresh rewrites its tokens and leaves its scopes as they
|
|
19
|
+
* were, so signing in with an older account does not take the mail back to it.
|
|
20
|
+
*/
|
|
21
|
+
const mailLinkHooks = (providers) => {
|
|
22
|
+
const handOver = async (account, context) => {
|
|
23
|
+
const provider = mailProviderOf(providers, account);
|
|
24
|
+
if (!context || !provider || !(await getOAuthState())?.link) return;
|
|
25
|
+
const adapter = context.context.internalAdapter;
|
|
26
|
+
for (const { id, scope } of scopesHandedOver(provider, account, await adapter.findAccounts(account.userId))) await adapter.updateAccount(id, { scope });
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
create: { after: handOver },
|
|
30
|
+
update: { after: handOver }
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { mailLinkHooks, mailProviderOf, scopesHandedOver };
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { PersonalMailError } from "./personal-mail-error.js";
|
|
2
2
|
//#region src/personal-mail/personal-mailer.ts
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* The mail provider `userId` linked, of the app's `providers` in their order, with the account that holds its tokens.
|
|
5
|
+
* Linking a mailbox takes the mail scopes off the person's other accounts of that provider (`mailLinkHooks`), so one
|
|
6
|
+
* account holds them; of accounts that still both hold them, as when both were linked before that, the one created last.
|
|
7
|
+
*/
|
|
4
8
|
const linkedProvider = async (accounts, providers, userId) => {
|
|
5
9
|
const linked = await accounts.accounts(userId);
|
|
6
10
|
for (const provider of providers) {
|
|
7
|
-
const account = linked.
|
|
11
|
+
const account = linked.filter((candidate) => candidate.providerId === provider.signInProvider && provider.scopes.every((scope) => candidate.scopes.includes(scope))).reduce((latest, candidate) => latest && latest.createdAt >= candidate.createdAt ? latest : candidate, void 0);
|
|
8
12
|
if (account) return {
|
|
9
13
|
provider,
|
|
10
14
|
account
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protobase/server",
|
|
3
|
-
"version": "0.66.
|
|
3
|
+
"version": "0.66.3",
|
|
4
4
|
"description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"@better-auth/sso": "^1.7.12",
|
|
43
43
|
"@livekit/protocol": "1.53.1",
|
|
44
44
|
"@modelcontextprotocol/server": "^2.3.1",
|
|
45
|
-
"@protobase/layout": "0.66.
|
|
46
|
-
"@protobase/query": "0.66.
|
|
47
|
-
"@protobase/schema": "0.66.
|
|
45
|
+
"@protobase/layout": "0.66.3",
|
|
46
|
+
"@protobase/query": "0.66.3",
|
|
47
|
+
"@protobase/schema": "0.66.3",
|
|
48
48
|
"@react-email/render": "^2.1.0",
|
|
49
49
|
"@scalar/hono-api-reference": "^0.12.10",
|
|
50
50
|
"@sentry/core": "^11.7.0",
|