@better-auth/stripe 1.5.0-beta.2 → 1.5.0-beta.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/src/middleware.ts CHANGED
@@ -1,57 +1,104 @@
1
1
  import { createAuthMiddleware } from "@better-auth/core/api";
2
- import { APIError } from "better-auth/api";
3
- import type { SubscriptionOptions } from "./types";
2
+ import { APIError } from "@better-auth/core/error";
3
+ import { sessionMiddleware } from "better-auth/api";
4
+ import { STRIPE_ERROR_CODES } from "./error-codes";
5
+ import type {
6
+ AuthorizeReferenceAction,
7
+ CustomerType,
8
+ StripeCtxSession,
9
+ SubscriptionOptions,
10
+ } from "./types";
11
+
12
+ export const stripeSessionMiddleware = createAuthMiddleware(
13
+ {
14
+ use: [sessionMiddleware],
15
+ },
16
+ async (ctx) => {
17
+ const session = ctx.context.session as StripeCtxSession;
18
+ return {
19
+ session,
20
+ };
21
+ },
22
+ );
4
23
 
5
24
  export const referenceMiddleware = (
6
25
  subscriptionOptions: SubscriptionOptions,
7
- action:
8
- | "upgrade-subscription"
9
- | "list-subscription"
10
- | "cancel-subscription"
11
- | "restore-subscription"
12
- | "billing-portal",
26
+ action: AuthorizeReferenceAction,
13
27
  ) =>
14
28
  createAuthMiddleware(async (ctx) => {
15
- const session = ctx.context.session;
16
- if (!session) {
17
- throw new APIError("UNAUTHORIZED");
29
+ const ctxSession = ctx.context.session as StripeCtxSession;
30
+ if (!ctxSession) {
31
+ throw APIError.from("UNAUTHORIZED", STRIPE_ERROR_CODES.UNAUTHORIZED);
32
+ }
33
+
34
+ const customerType: CustomerType =
35
+ ctx.body?.customerType || ctx.query?.customerType;
36
+ const explicitReferenceId = ctx.body?.referenceId || ctx.query?.referenceId;
37
+
38
+ if (customerType === "organization") {
39
+ // Organization subscriptions always require authorizeReference
40
+ if (!subscriptionOptions.authorizeReference) {
41
+ ctx.context.logger.error(
42
+ `Organization subscriptions require authorizeReference to be defined in your stripe plugin config.`,
43
+ );
44
+ throw APIError.from(
45
+ "BAD_REQUEST",
46
+ STRIPE_ERROR_CODES.ORGANIZATION_SUBSCRIPTION_NOT_ENABLED,
47
+ );
48
+ }
49
+
50
+ const referenceId =
51
+ explicitReferenceId || ctxSession.session.activeOrganizationId;
52
+ if (!referenceId) {
53
+ throw APIError.from(
54
+ "BAD_REQUEST",
55
+ STRIPE_ERROR_CODES.ORGANIZATION_REFERENCE_ID_REQUIRED,
56
+ );
57
+ }
58
+ const isAuthorized = await subscriptionOptions.authorizeReference(
59
+ {
60
+ user: ctxSession.user,
61
+ session: ctxSession.session,
62
+ referenceId,
63
+ action,
64
+ },
65
+ ctx,
66
+ );
67
+ if (!isAuthorized) {
68
+ throw APIError.from("UNAUTHORIZED", STRIPE_ERROR_CODES.UNAUTHORIZED);
69
+ }
70
+ return;
18
71
  }
19
- const referenceId =
20
- ctx.body?.referenceId || ctx.query?.referenceId || session.user.id;
21
72
 
22
- if (
23
- referenceId !== session.user.id &&
24
- !subscriptionOptions.authorizeReference
25
- ) {
73
+ // User subscriptions - pass if no explicit referenceId
74
+ if (!explicitReferenceId) {
75
+ return;
76
+ }
77
+
78
+ // Pass if referenceId is user id
79
+ if (explicitReferenceId === ctxSession.user.id) {
80
+ return;
81
+ }
82
+
83
+ if (!subscriptionOptions.authorizeReference) {
26
84
  ctx.context.logger.error(
27
85
  `Passing referenceId into a subscription action isn't allowed if subscription.authorizeReference isn't defined in your stripe plugin config.`,
28
86
  );
29
- throw new APIError("BAD_REQUEST", {
30
- message:
31
- "Reference id is not allowed. Read server logs for more details.",
32
- });
87
+ throw APIError.from(
88
+ "BAD_REQUEST",
89
+ STRIPE_ERROR_CODES.REFERENCE_ID_NOT_ALLOWED,
90
+ );
33
91
  }
34
- /**
35
- * if referenceId is the same as the active session user's id
36
- */
37
- const sameReference =
38
- ctx.query?.referenceId === session.user.id ||
39
- ctx.body?.referenceId === session.user.id;
40
- const isAuthorized =
41
- ctx.body?.referenceId || ctx.query?.referenceId
42
- ? (await subscriptionOptions.authorizeReference?.(
43
- {
44
- user: session.user,
45
- session: session.session,
46
- referenceId,
47
- action,
48
- },
49
- ctx,
50
- )) || sameReference
51
- : true;
92
+ const isAuthorized = await subscriptionOptions.authorizeReference(
93
+ {
94
+ user: ctxSession.user,
95
+ session: ctxSession.session,
96
+ referenceId: explicitReferenceId,
97
+ action,
98
+ },
99
+ ctx,
100
+ );
52
101
  if (!isAuthorized) {
53
- throw new APIError("UNAUTHORIZED", {
54
- message: "Unauthorized",
55
- });
102
+ throw APIError.from("UNAUTHORIZED", STRIPE_ERROR_CODES.UNAUTHORIZED);
56
103
  }
57
104
  });