@robelest/convex-auth 0.0.4-preview.22 → 0.0.4-preview.24
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/README.md +10 -11
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/index.js.map +1 -1
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +36 -39
- package/dist/client/index.js.map +1 -1
- package/dist/component/client/index.d.ts +1 -2
- package/dist/component/index.js +2 -2
- package/dist/component/model.d.ts +9 -9
- package/dist/component/model.d.ts.map +1 -1
- package/dist/component/public/enterprise/audit.d.ts.map +1 -1
- package/dist/component/public/enterprise/audit.js.map +1 -1
- package/dist/component/public/enterprise/core.d.ts.map +1 -1
- package/dist/component/public/enterprise/core.js.map +1 -1
- package/dist/component/public/enterprise/domains.d.ts.map +1 -1
- package/dist/component/public/enterprise/domains.js.map +1 -1
- package/dist/component/public/enterprise/scim.d.ts.map +1 -1
- package/dist/component/public/enterprise/scim.js.map +1 -1
- package/dist/component/public/enterprise/secrets.d.ts.map +1 -1
- package/dist/component/public/enterprise/secrets.js.map +1 -1
- package/dist/component/public/enterprise/webhooks.d.ts.map +1 -1
- package/dist/component/public/enterprise/webhooks.js.map +1 -1
- package/dist/component/public/factors/devices.d.ts.map +1 -1
- package/dist/component/public/factors/devices.js.map +1 -1
- package/dist/component/public/factors/passkeys.d.ts.map +1 -1
- package/dist/component/public/factors/passkeys.js.map +1 -1
- package/dist/component/public/factors/totp.d.ts.map +1 -1
- package/dist/component/public/factors/totp.js.map +1 -1
- package/dist/component/public/groups/core.js.map +1 -1
- package/dist/component/public/groups/invites.d.ts.map +1 -1
- package/dist/component/public/groups/invites.js.map +1 -1
- package/dist/component/public/groups/members.d.ts.map +1 -1
- package/dist/component/public/groups/members.js.map +1 -1
- package/dist/component/public/identity/accounts.d.ts.map +1 -1
- package/dist/component/public/identity/accounts.js.map +1 -1
- package/dist/component/public/identity/codes.d.ts.map +1 -1
- package/dist/component/public/identity/codes.js.map +1 -1
- package/dist/component/public/identity/sessions.d.ts.map +1 -1
- package/dist/component/public/identity/sessions.js.map +1 -1
- package/dist/component/public/identity/tokens.d.ts.map +1 -1
- package/dist/component/public/identity/tokens.js.map +1 -1
- package/dist/component/public/identity/users.d.ts.map +1 -1
- package/dist/component/public/identity/users.js.map +1 -1
- package/dist/component/public/identity/verifiers.d.ts.map +1 -1
- package/dist/component/public/identity/verifiers.js.map +1 -1
- package/dist/component/public/security/keys.d.ts.map +1 -1
- package/dist/component/public/security/keys.js.map +1 -1
- package/dist/component/public/security/limits.d.ts.map +1 -1
- package/dist/component/public/security/limits.js.map +1 -1
- package/dist/component/schema.d.ts +41 -41
- package/dist/component/server/auth.d.ts +127 -130
- package/dist/component/server/auth.d.ts.map +1 -1
- package/dist/component/server/auth.js +100 -64
- package/dist/component/server/auth.js.map +1 -1
- package/dist/component/server/context.js +53 -0
- package/dist/component/server/context.js.map +1 -0
- package/dist/component/server/core.js +113 -250
- package/dist/component/server/core.js.map +1 -1
- package/dist/component/server/crypto.js +25 -7
- package/dist/component/server/crypto.js.map +1 -1
- package/dist/component/server/device.js +59 -16
- package/dist/component/server/device.js.map +1 -1
- package/dist/component/server/enterprise/domain.js +148 -59
- package/dist/component/server/enterprise/domain.js.map +1 -1
- package/dist/component/server/enterprise/http.js +36 -15
- package/dist/component/server/enterprise/http.js.map +1 -1
- package/dist/component/server/enterprise/oidc.js +1 -1
- package/dist/component/server/http.d.ts +85 -0
- package/dist/component/server/http.d.ts.map +1 -0
- package/dist/component/server/http.js +85 -22
- package/dist/component/server/http.js.map +1 -1
- package/dist/component/server/identity.js +5 -2
- package/dist/component/server/identity.js.map +1 -1
- package/dist/component/server/limits.js +21 -30
- package/dist/component/server/limits.js.map +1 -1
- package/dist/component/server/mutations/account.js +12 -10
- package/dist/component/server/mutations/account.js.map +1 -1
- package/dist/component/server/mutations/code.js +5 -2
- package/dist/component/server/mutations/code.js.map +1 -1
- package/dist/component/server/mutations/invalidate.js +1 -1
- package/dist/component/server/mutations/invalidate.js.map +1 -1
- package/dist/component/server/mutations/oauth.js +10 -4
- package/dist/component/server/mutations/oauth.js.map +1 -1
- package/dist/component/server/mutations/refresh.js +2 -2
- package/dist/component/server/mutations/refresh.js.map +1 -1
- package/dist/component/server/mutations/register.js +46 -42
- package/dist/component/server/mutations/register.js.map +1 -1
- package/dist/component/server/mutations/retrieve.js +21 -25
- package/dist/component/server/mutations/retrieve.js.map +1 -1
- package/dist/component/server/mutations/signature.js +10 -4
- package/dist/component/server/mutations/signature.js.map +1 -1
- package/dist/component/server/mutations/signout.js.map +1 -1
- package/dist/component/server/mutations/store.js +9 -24
- package/dist/component/server/mutations/store.js.map +1 -1
- package/dist/component/server/mutations/verifier.js.map +1 -1
- package/dist/component/server/mutations/verify.js +1 -1
- package/dist/component/server/mutations/verify.js.map +1 -1
- package/dist/component/server/oauth.js +53 -16
- package/dist/component/server/oauth.js.map +1 -1
- package/dist/component/server/passkey.js +115 -31
- package/dist/component/server/passkey.js.map +1 -1
- package/dist/component/server/redirects.js +9 -3
- package/dist/component/server/redirects.js.map +1 -1
- package/dist/component/server/refresh.js +10 -7
- package/dist/component/server/refresh.js.map +1 -1
- package/dist/component/server/runtime.d.ts +5 -5
- package/dist/component/server/runtime.js +156 -113
- package/dist/component/server/runtime.js.map +1 -1
- package/dist/component/server/signin.js +34 -10
- package/dist/component/server/signin.js.map +1 -1
- package/dist/component/server/totp.js +79 -19
- package/dist/component/server/totp.js.map +1 -1
- package/dist/component/server/types.d.ts +12 -20
- package/dist/component/server/types.d.ts.map +1 -1
- package/dist/component/server/types.js.map +1 -1
- package/dist/component/server/users.js +6 -3
- package/dist/component/server/users.js.map +1 -1
- package/dist/component/server/utils.js +10 -4
- package/dist/component/server/utils.js.map +1 -1
- package/dist/core/types.d.ts +14 -22
- package/dist/core/types.d.ts.map +1 -1
- package/dist/factors/device.js +8 -9
- package/dist/factors/device.js.map +1 -1
- package/dist/factors/passkey.js +18 -21
- package/dist/factors/passkey.js.map +1 -1
- package/dist/providers/password.js +66 -81
- package/dist/providers/password.js.map +1 -1
- package/dist/runtime/invite.js +2 -8
- package/dist/runtime/invite.js.map +1 -1
- package/dist/server/auth.d.ts +127 -130
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +100 -64
- package/dist/server/auth.js.map +1 -1
- package/dist/server/context.d.ts +1 -0
- package/dist/server/context.js +53 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/core.d.ts +74 -195
- package/dist/server/core.d.ts.map +1 -1
- package/dist/server/core.js +113 -250
- package/dist/server/core.js.map +1 -1
- package/dist/server/crypto.d.ts.map +1 -1
- package/dist/server/crypto.js +25 -7
- package/dist/server/crypto.js.map +1 -1
- package/dist/server/device.js +59 -16
- package/dist/server/device.js.map +1 -1
- package/dist/server/enterprise/domain.d.ts +0 -8
- package/dist/server/enterprise/domain.d.ts.map +1 -1
- package/dist/server/enterprise/domain.js +148 -59
- package/dist/server/enterprise/domain.js.map +1 -1
- package/dist/server/enterprise/http.d.ts.map +1 -1
- package/dist/server/enterprise/http.js +35 -14
- package/dist/server/enterprise/http.js.map +1 -1
- package/dist/server/http.d.ts +81 -3
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +84 -21
- package/dist/server/http.js.map +1 -1
- package/dist/server/identity.js +5 -2
- package/dist/server/identity.js.map +1 -1
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +2 -2
- package/dist/server/limits.js +21 -30
- package/dist/server/limits.js.map +1 -1
- package/dist/server/mounts.d.ts +25 -63
- package/dist/server/mounts.d.ts.map +1 -1
- package/dist/server/mounts.js +46 -107
- package/dist/server/mounts.js.map +1 -1
- package/dist/server/mutations/account.d.ts +8 -9
- package/dist/server/mutations/account.d.ts.map +1 -1
- package/dist/server/mutations/account.js +11 -9
- package/dist/server/mutations/account.js.map +1 -1
- package/dist/server/mutations/code.d.ts +12 -12
- package/dist/server/mutations/code.d.ts.map +1 -1
- package/dist/server/mutations/code.js +5 -2
- package/dist/server/mutations/code.js.map +1 -1
- package/dist/server/mutations/invalidate.d.ts +4 -4
- package/dist/server/mutations/invalidate.d.ts.map +1 -1
- package/dist/server/mutations/invalidate.js.map +1 -1
- package/dist/server/mutations/oauth.d.ts +14 -12
- package/dist/server/mutations/oauth.d.ts.map +1 -1
- package/dist/server/mutations/oauth.js +9 -3
- package/dist/server/mutations/oauth.js.map +1 -1
- package/dist/server/mutations/refresh.d.ts +3 -3
- package/dist/server/mutations/refresh.d.ts.map +1 -1
- package/dist/server/mutations/refresh.js +1 -1
- package/dist/server/mutations/refresh.js.map +1 -1
- package/dist/server/mutations/register.d.ts +11 -11
- package/dist/server/mutations/register.d.ts.map +1 -1
- package/dist/server/mutations/register.js +45 -41
- package/dist/server/mutations/register.js.map +1 -1
- package/dist/server/mutations/retrieve.d.ts +6 -6
- package/dist/server/mutations/retrieve.d.ts.map +1 -1
- package/dist/server/mutations/retrieve.js +20 -24
- package/dist/server/mutations/retrieve.js.map +1 -1
- package/dist/server/mutations/signature.d.ts +6 -7
- package/dist/server/mutations/signature.d.ts.map +1 -1
- package/dist/server/mutations/signature.js +9 -3
- package/dist/server/mutations/signature.js.map +1 -1
- package/dist/server/mutations/signin.d.ts +5 -5
- package/dist/server/mutations/signout.js.map +1 -1
- package/dist/server/mutations/store.d.ts +83 -83
- package/dist/server/mutations/store.js +8 -23
- package/dist/server/mutations/store.js.map +1 -1
- package/dist/server/mutations/verifier.js.map +1 -1
- package/dist/server/mutations/verify.d.ts +7 -7
- package/dist/server/mutations/verify.d.ts.map +1 -1
- package/dist/server/mutations/verify.js.map +1 -1
- package/dist/server/oauth.js +53 -16
- package/dist/server/oauth.js.map +1 -1
- package/dist/server/passkey.d.ts +2 -2
- package/dist/server/passkey.d.ts.map +1 -1
- package/dist/server/passkey.js +114 -30
- package/dist/server/passkey.js.map +1 -1
- package/dist/server/redirects.js +9 -3
- package/dist/server/redirects.js.map +1 -1
- package/dist/server/refresh.js +10 -7
- package/dist/server/refresh.js.map +1 -1
- package/dist/server/runtime.d.ts +11 -11
- package/dist/server/runtime.js +155 -112
- package/dist/server/runtime.js.map +1 -1
- package/dist/server/signin.js +34 -10
- package/dist/server/signin.js.map +1 -1
- package/dist/server/ssr.d.ts.map +1 -1
- package/dist/server/ssr.js +175 -184
- package/dist/server/ssr.js.map +1 -1
- package/dist/server/totp.js +78 -18
- package/dist/server/totp.js.map +1 -1
- package/dist/server/types.d.ts +13 -21
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js.map +1 -1
- package/dist/server/users.js +6 -3
- package/dist/server/users.js.map +1 -1
- package/dist/server/utils.js +10 -4
- package/dist/server/utils.js.map +1 -1
- package/package.json +1 -5
- package/src/authorization/index.ts +1 -1
- package/src/client/core/types.ts +14 -14
- package/src/client/factors/device.ts +10 -12
- package/src/client/factors/passkey.ts +23 -26
- package/src/client/index.ts +54 -64
- package/src/client/runtime/invite.ts +5 -7
- package/src/component/index.ts +9 -3
- package/src/component/public/enterprise/audit.ts +6 -1
- package/src/component/public/enterprise/core.ts +1 -0
- package/src/component/public/enterprise/domains.ts +5 -1
- package/src/component/public/enterprise/scim.ts +1 -0
- package/src/component/public/enterprise/secrets.ts +1 -0
- package/src/component/public/enterprise/webhooks.ts +1 -0
- package/src/component/public/factors/devices.ts +1 -0
- package/src/component/public/factors/passkeys.ts +1 -0
- package/src/component/public/factors/totp.ts +1 -0
- package/src/component/public/groups/core.ts +1 -1
- package/src/component/public/groups/invites.ts +7 -1
- package/src/component/public/groups/members.ts +1 -0
- package/src/component/public/identity/accounts.ts +1 -0
- package/src/component/public/identity/codes.ts +1 -0
- package/src/component/public/identity/sessions.ts +1 -0
- package/src/component/public/identity/tokens.ts +1 -0
- package/src/component/public/identity/users.ts +1 -0
- package/src/component/public/identity/verifiers.ts +1 -0
- package/src/component/public/security/keys.ts +1 -0
- package/src/component/public/security/limits.ts +1 -0
- package/src/providers/password.ts +89 -110
- package/src/server/auth.ts +240 -182
- package/src/server/context.ts +90 -0
- package/src/server/core.ts +195 -286
- package/src/server/crypto.ts +31 -29
- package/src/server/device.ts +65 -32
- package/src/server/enterprise/domain.ts +158 -170
- package/src/server/enterprise/http.ts +46 -39
- package/src/server/http.ts +289 -30
- package/src/server/identity.ts +5 -5
- package/src/server/index.ts +9 -3
- package/src/server/limits.ts +53 -80
- package/src/server/mounts.ts +56 -80
- package/src/server/mutations/account.ts +22 -36
- package/src/server/mutations/code.ts +6 -6
- package/src/server/mutations/invalidate.ts +1 -1
- package/src/server/mutations/oauth.ts +14 -8
- package/src/server/mutations/refresh.ts +5 -4
- package/src/server/mutations/register.ts +87 -132
- package/src/server/mutations/retrieve.ts +44 -44
- package/src/server/mutations/signature.ts +13 -6
- package/src/server/mutations/signout.ts +1 -1
- package/src/server/mutations/store.ts +16 -31
- package/src/server/mutations/verifier.ts +1 -1
- package/src/server/mutations/verify.ts +3 -5
- package/src/server/oauth.ts +60 -69
- package/src/server/passkey.ts +567 -517
- package/src/server/redirects.ts +10 -6
- package/src/server/refresh.ts +14 -18
- package/src/server/runtime.ts +340 -302
- package/src/server/signin.ts +44 -37
- package/src/server/ssr.ts +390 -407
- package/src/server/totp.ts +85 -35
- package/src/server/types.ts +19 -22
- package/src/server/users.ts +7 -6
- package/src/server/utils.ts +10 -12
- package/dist/component/server/authError.js +0 -34
- package/dist/component/server/authError.js.map +0 -1
- package/dist/component/server/errors.d.ts +0 -1
- package/dist/component/server/errors.js +0 -137
- package/dist/component/server/errors.js.map +0 -1
- package/dist/server/authError.d.ts +0 -46
- package/dist/server/authError.d.ts.map +0 -1
- package/dist/server/authError.js +0 -34
- package/dist/server/authError.js.map +0 -1
- package/dist/server/errors.d.ts +0 -177
- package/dist/server/errors.d.ts.map +0 -1
- package/dist/server/errors.js +0 -212
- package/dist/server/errors.js.map +0 -1
- package/src/server/authError.ts +0 -44
- package/src/server/errors.ts +0 -290
package/src/server/limits.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Fx } from "@robelest/fx";
|
|
2
|
+
import { ConvexError } from "convex/values";
|
|
2
3
|
|
|
3
4
|
import { authDb } from "./db";
|
|
4
|
-
import { AuthError } from "./authError";
|
|
5
5
|
import { Doc, MutationCtx } from "./types";
|
|
6
6
|
import { ConvexAuthConfig } from "./types";
|
|
7
|
-
import { errorMessage } from "./utils";
|
|
8
7
|
|
|
9
8
|
const DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR = 10;
|
|
10
9
|
|
|
@@ -16,7 +15,7 @@ export const isSignInRateLimited = (
|
|
|
16
15
|
ctx: MutationCtx,
|
|
17
16
|
identifier: string,
|
|
18
17
|
config: ConvexAuthConfig,
|
|
19
|
-
): Fx<boolean,
|
|
18
|
+
): Fx<boolean, ConvexError<any>> =>
|
|
20
19
|
getRateLimitState(ctx, identifier, config).pipe(
|
|
21
20
|
Fx.map((state) => state !== null && state.attemptsLeft < 1),
|
|
22
21
|
);
|
|
@@ -31,40 +30,28 @@ export const recordFailedSignIn = (
|
|
|
31
30
|
ctx: MutationCtx,
|
|
32
31
|
identifier: string,
|
|
33
32
|
config: ConvexAuthConfig,
|
|
34
|
-
): Fx<void,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR) - 1,
|
|
57
|
-
lastAttemptTime: Date.now(),
|
|
58
|
-
}),
|
|
59
|
-
err: (e) =>
|
|
60
|
-
new AuthError(
|
|
61
|
-
"INTERNAL_ERROR",
|
|
62
|
-
`Failed to create rate limit: ${errorMessage(e)}`,
|
|
63
|
-
),
|
|
64
|
-
}),
|
|
65
|
-
),
|
|
66
|
-
Fx.map(() => undefined),
|
|
67
|
-
);
|
|
33
|
+
): Fx<void, ConvexError<any>> =>
|
|
34
|
+
Fx.gen(function* () {
|
|
35
|
+
const state = yield* getRateLimitState(ctx, identifier, config);
|
|
36
|
+
if (state !== null) {
|
|
37
|
+
yield* Fx.promise(() =>
|
|
38
|
+
authDb(ctx, config).rateLimits.patch(state.limit._id, {
|
|
39
|
+
attemptsLeft: state.attemptsLeft - 1,
|
|
40
|
+
lastAttemptTime: Date.now(),
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
} else {
|
|
44
|
+
yield* Fx.promise(() =>
|
|
45
|
+
authDb(ctx, config).rateLimits.create({
|
|
46
|
+
identifier,
|
|
47
|
+
attemptsLeft:
|
|
48
|
+
(config.signIn?.maxFailedAttemptsPerHour ??
|
|
49
|
+
DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR) - 1,
|
|
50
|
+
lastAttemptTime: Date.now(),
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
68
55
|
|
|
69
56
|
/**
|
|
70
57
|
* Reset the rate limit for the given identifier (e.g. after successful sign-in).
|
|
@@ -74,21 +61,15 @@ export const resetSignInRateLimit = (
|
|
|
74
61
|
ctx: MutationCtx,
|
|
75
62
|
identifier: string,
|
|
76
63
|
config: ConvexAuthConfig,
|
|
77
|
-
): Fx<void,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
`Failed to delete rate limit: ${errorMessage(e)}`,
|
|
87
|
-
),
|
|
88
|
-
})
|
|
89
|
-
: Fx.unit,
|
|
90
|
-
),
|
|
91
|
-
);
|
|
64
|
+
): Fx<void, ConvexError<any>> =>
|
|
65
|
+
Fx.gen(function* () {
|
|
66
|
+
const state = yield* getRateLimitState(ctx, identifier, config);
|
|
67
|
+
if (state !== null) {
|
|
68
|
+
yield* Fx.promise(() =>
|
|
69
|
+
authDb(ctx, config).rateLimits.delete(state.limit._id),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
92
73
|
|
|
93
74
|
// ---------------------------------------------------------------------------
|
|
94
75
|
// Internal
|
|
@@ -103,32 +84,24 @@ const getRateLimitState = (
|
|
|
103
84
|
ctx: MutationCtx,
|
|
104
85
|
identifier: string,
|
|
105
86
|
config: ConvexAuthConfig,
|
|
106
|
-
): Fx<RateLimitState,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
87
|
+
): Fx<RateLimitState, ConvexError<any>> =>
|
|
88
|
+
Fx.gen(function* () {
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
const maxAttemptsPerHour =
|
|
91
|
+
config.signIn?.maxFailedAttemptsPerHour ??
|
|
92
|
+
DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR;
|
|
111
93
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const maxAttemptsPerMs = maxAttemptsPerHour / (60 * 60 * 1000);
|
|
127
|
-
const attemptsLeft = Math.min(
|
|
128
|
-
maxAttemptsPerHour,
|
|
129
|
-
limit.attemptsLeft + elapsed * maxAttemptsPerMs,
|
|
130
|
-
);
|
|
131
|
-
return { limit, attemptsLeft };
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
};
|
|
94
|
+
const limit = (yield* Fx.promise(() =>
|
|
95
|
+
authDb(ctx, config).rateLimits.get(identifier),
|
|
96
|
+
)) as
|
|
97
|
+
| (Doc<"RateLimit"> & { attemptsLeft: number; lastAttemptTime: number })
|
|
98
|
+
| null;
|
|
99
|
+
if (limit === null) return null;
|
|
100
|
+
const elapsed = now - limit.lastAttemptTime;
|
|
101
|
+
const maxAttemptsPerMs = maxAttemptsPerHour / (60 * 60 * 1000);
|
|
102
|
+
const attemptsLeft = Math.min(
|
|
103
|
+
maxAttemptsPerHour,
|
|
104
|
+
limit.attemptsLeft + elapsed * maxAttemptsPerMs,
|
|
105
|
+
);
|
|
106
|
+
return { limit, attemptsLeft };
|
|
107
|
+
});
|
package/src/server/mounts.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Cv } from "@robelest/fx/convex";
|
|
1
2
|
import { actionGeneric, mutationGeneric, queryGeneric } from "convex/server";
|
|
2
3
|
import { ConvexError, v } from "convex/values";
|
|
3
4
|
|
|
@@ -62,11 +63,11 @@ export type EnterpriseAdminAuthorizationInput = {
|
|
|
62
63
|
/**
|
|
63
64
|
* App-defined authorization hook for mounted enterprise admin APIs.
|
|
64
65
|
*
|
|
65
|
-
* Return `void` (or resolve) to allow the operation, or
|
|
66
|
+
* Return `void` (or resolve) to allow the operation, or throw to deny it.
|
|
66
67
|
*
|
|
67
68
|
* @param ctx - Convex context with `ctx.auth` for identity checks.
|
|
68
69
|
* @param input - The {@link EnterpriseAdminAuthorizationInput} describing who is doing what.
|
|
69
|
-
* @returns `void` to allow
|
|
70
|
+
* @returns `void` to allow; throw to deny.
|
|
70
71
|
*
|
|
71
72
|
* @example
|
|
72
73
|
* ```ts
|
|
@@ -74,7 +75,7 @@ export type EnterpriseAdminAuthorizationInput = {
|
|
|
74
75
|
*
|
|
75
76
|
* const authorized: EnterpriseAuthorizer = async (ctx, input) => {
|
|
76
77
|
* const identity = await ctx.auth.getUserIdentity();
|
|
77
|
-
* if (!identity)
|
|
78
|
+
* if (!identity) throw new Error("Forbidden");
|
|
78
79
|
* // Allow all admin ops for the org owner
|
|
79
80
|
* };
|
|
80
81
|
* ```
|
|
@@ -82,7 +83,7 @@ export type EnterpriseAdminAuthorizationInput = {
|
|
|
82
83
|
export type EnterpriseAuthorizer = (
|
|
83
84
|
ctx: { auth: import("convex/server").Auth },
|
|
84
85
|
input: EnterpriseAdminAuthorizationInput,
|
|
85
|
-
) => Promise<void
|
|
86
|
+
) => Promise<void>;
|
|
86
87
|
|
|
87
88
|
type RoleRef<TRoleId extends string> = { id: TRoleId };
|
|
88
89
|
|
|
@@ -126,11 +127,11 @@ type MountedEnterpriseTarget = {
|
|
|
126
127
|
domain?: string;
|
|
127
128
|
};
|
|
128
129
|
|
|
129
|
-
function requireSignedInUser(auth: Pick<AuthApi, "
|
|
130
|
+
function requireSignedInUser(auth: Pick<AuthApi, "context">) {
|
|
130
131
|
return async (ctx: {
|
|
131
132
|
auth: import("convex/server").Auth;
|
|
132
133
|
}): Promise<string | null> => {
|
|
133
|
-
return await auth.
|
|
134
|
+
return (await auth.context(ctx as never, { optional: true })).userId;
|
|
134
135
|
};
|
|
135
136
|
}
|
|
136
137
|
|
|
@@ -197,7 +198,7 @@ async function resolveMountedEnterpriseTarget(
|
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
function createMountedAdminAuthorizer(
|
|
200
|
-
auth: Pick<AuthApi, "
|
|
201
|
+
auth: Pick<AuthApi, "context" | "sso">,
|
|
201
202
|
options?: MountedEnterpriseOptions,
|
|
202
203
|
) {
|
|
203
204
|
const requireUserId = requireSignedInUser(auth);
|
|
@@ -209,23 +210,26 @@ function createMountedAdminAuthorizer(
|
|
|
209
210
|
) => {
|
|
210
211
|
const userId = await requireUserId(ctx);
|
|
211
212
|
if (userId === null) {
|
|
212
|
-
|
|
213
|
+
throw Cv.error({
|
|
214
|
+
code: "NOT_SIGNED_IN",
|
|
215
|
+
message: "You must be signed in to perform this action.",
|
|
216
|
+
});
|
|
213
217
|
}
|
|
214
218
|
if (!options?.admin?.authorized) {
|
|
215
|
-
|
|
219
|
+
throw Cv.error({
|
|
220
|
+
code: "FORBIDDEN",
|
|
221
|
+
message: "Access denied.",
|
|
222
|
+
});
|
|
216
223
|
}
|
|
217
224
|
const resolved = await resolveMountedEnterpriseTarget(auth, ctx, target);
|
|
218
|
-
|
|
225
|
+
await options.admin.authorized(ctx, {
|
|
219
226
|
userId,
|
|
220
227
|
permission,
|
|
221
228
|
enterpriseId: resolved.enterpriseId,
|
|
222
229
|
groupId: resolved.groupId,
|
|
223
230
|
resolvedGroupId: resolved.resolvedGroupId,
|
|
224
231
|
});
|
|
225
|
-
|
|
226
|
-
return { ok: false as const, code: "FORBIDDEN" as const };
|
|
227
|
-
}
|
|
228
|
-
return { ok: true as const, userId, ...resolved };
|
|
232
|
+
return { userId, ...resolved };
|
|
229
233
|
};
|
|
230
234
|
}
|
|
231
235
|
|
|
@@ -265,7 +269,10 @@ function createMountedAdminAuthorizer(
|
|
|
265
269
|
export function sso<
|
|
266
270
|
TAuthorization extends AuthAuthorizationConfig | undefined = undefined,
|
|
267
271
|
>(
|
|
268
|
-
auth: Pick<
|
|
272
|
+
auth: Pick<
|
|
273
|
+
AuthApi<TAuthorization>,
|
|
274
|
+
"context" | "group" | "member" | "sso"
|
|
275
|
+
>,
|
|
269
276
|
options?: MountedEnterpriseOptions<AuthRoleId<TAuthorization>>,
|
|
270
277
|
) {
|
|
271
278
|
const authorize = createMountedAdminAuthorizer(auth, options);
|
|
@@ -286,8 +293,6 @@ export function sso<
|
|
|
286
293
|
const authResult = await authorize(ctx, "sso.connection.create", {
|
|
287
294
|
groupId: args.groupId,
|
|
288
295
|
});
|
|
289
|
-
if (!authResult.ok)
|
|
290
|
-
return { ok: false as const, code: authResult.code };
|
|
291
296
|
const { userId } = authResult;
|
|
292
297
|
const createsGroup = args.groupId === undefined;
|
|
293
298
|
const groupId =
|
|
@@ -332,10 +337,9 @@ export function sso<
|
|
|
332
337
|
get: queryGeneric({
|
|
333
338
|
args: { enterpriseId: v.string() },
|
|
334
339
|
handler: async (ctx, args) => {
|
|
335
|
-
|
|
340
|
+
await authorize(ctx, "sso.connection.read", {
|
|
336
341
|
enterpriseId: args.enterpriseId,
|
|
337
342
|
});
|
|
338
|
-
if (!_auth.ok) return null;
|
|
339
343
|
return await auth.sso.admin.connection.get(
|
|
340
344
|
ctx as never,
|
|
341
345
|
args.enterpriseId,
|
|
@@ -345,10 +349,9 @@ export function sso<
|
|
|
345
349
|
getByGroup: queryGeneric({
|
|
346
350
|
args: { groupId: v.string() },
|
|
347
351
|
handler: async (ctx, args) => {
|
|
348
|
-
|
|
352
|
+
await authorize(ctx, "sso.connection.read", {
|
|
349
353
|
groupId: args.groupId,
|
|
350
354
|
});
|
|
351
|
-
if (!_auth.ok) return null;
|
|
352
355
|
return await auth.sso.admin.connection.getByGroup(
|
|
353
356
|
ctx as never,
|
|
354
357
|
args.groupId,
|
|
@@ -358,10 +361,9 @@ export function sso<
|
|
|
358
361
|
getByDomain: queryGeneric({
|
|
359
362
|
args: { domain: v.string() },
|
|
360
363
|
handler: async (ctx, args) => {
|
|
361
|
-
|
|
364
|
+
await authorize(ctx, "sso.connection.read", {
|
|
362
365
|
domain: args.domain,
|
|
363
366
|
});
|
|
364
|
-
if (!_auth.ok) return null;
|
|
365
367
|
return await auth.sso.admin.connection.getByDomain(
|
|
366
368
|
ctx as never,
|
|
367
369
|
args.domain,
|
|
@@ -377,10 +379,9 @@ export function sso<
|
|
|
377
379
|
order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
|
|
378
380
|
},
|
|
379
381
|
handler: async (ctx, args) => {
|
|
380
|
-
|
|
382
|
+
await authorize(ctx, "sso.connection.read", {
|
|
381
383
|
groupId: args.where?.groupId,
|
|
382
384
|
});
|
|
383
|
-
if (!_auth.ok) return null;
|
|
384
385
|
return await auth.sso.admin.connection.list(
|
|
385
386
|
ctx as never,
|
|
386
387
|
args as never,
|
|
@@ -397,25 +398,23 @@ export function sso<
|
|
|
397
398
|
}),
|
|
398
399
|
},
|
|
399
400
|
handler: async (ctx, args) => {
|
|
400
|
-
|
|
401
|
+
await authorize(ctx, "sso.connection.manage", {
|
|
401
402
|
enterpriseId: args.enterpriseId,
|
|
402
403
|
});
|
|
403
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
404
404
|
await auth.sso.admin.connection.update(
|
|
405
405
|
ctx as never,
|
|
406
406
|
args.enterpriseId,
|
|
407
407
|
args.data,
|
|
408
408
|
);
|
|
409
|
-
return {
|
|
409
|
+
return { enterpriseId: args.enterpriseId };
|
|
410
410
|
},
|
|
411
411
|
}),
|
|
412
412
|
delete: mutationGeneric({
|
|
413
413
|
args: { enterpriseId: v.string() },
|
|
414
414
|
handler: async (ctx, args) => {
|
|
415
|
-
|
|
415
|
+
await authorize(ctx, "sso.connection.manage", {
|
|
416
416
|
enterpriseId: args.enterpriseId,
|
|
417
417
|
});
|
|
418
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
419
418
|
return await auth.sso.admin.connection.delete(
|
|
420
419
|
ctx as never,
|
|
421
420
|
args.enterpriseId,
|
|
@@ -425,10 +424,9 @@ export function sso<
|
|
|
425
424
|
status: queryGeneric({
|
|
426
425
|
args: { enterpriseId: v.string() },
|
|
427
426
|
handler: async (ctx, args) => {
|
|
428
|
-
|
|
427
|
+
await authorize(ctx, "sso.connection.read", {
|
|
429
428
|
enterpriseId: args.enterpriseId,
|
|
430
429
|
});
|
|
431
|
-
if (!_auth.ok) return null;
|
|
432
430
|
return await auth.sso.admin.connection.status(
|
|
433
431
|
ctx as never,
|
|
434
432
|
args.enterpriseId,
|
|
@@ -439,10 +437,9 @@ export function sso<
|
|
|
439
437
|
list: queryGeneric({
|
|
440
438
|
args: { enterpriseId: v.string() },
|
|
441
439
|
handler: async (ctx, args) => {
|
|
442
|
-
|
|
440
|
+
await authorize(ctx, "sso.connection.read", {
|
|
443
441
|
enterpriseId: args.enterpriseId,
|
|
444
442
|
});
|
|
445
|
-
if (!_auth.ok) return null;
|
|
446
443
|
return await auth.sso.admin.connection.domain.list(
|
|
447
444
|
ctx as never,
|
|
448
445
|
args.enterpriseId,
|
|
@@ -452,10 +449,9 @@ export function sso<
|
|
|
452
449
|
validate: queryGeneric({
|
|
453
450
|
args: { enterpriseId: v.string() },
|
|
454
451
|
handler: async (ctx, args) => {
|
|
455
|
-
|
|
452
|
+
await authorize(ctx, "sso.domain.manage", {
|
|
456
453
|
enterpriseId: args.enterpriseId,
|
|
457
454
|
});
|
|
458
|
-
if (!_auth.ok) return null;
|
|
459
455
|
return await auth.sso.admin.connection.domain.validate(
|
|
460
456
|
ctx as never,
|
|
461
457
|
args.enterpriseId,
|
|
@@ -468,10 +464,9 @@ export function sso<
|
|
|
468
464
|
domains: v.array(enterpriseDomainInputValidator),
|
|
469
465
|
},
|
|
470
466
|
handler: async (ctx, args) => {
|
|
471
|
-
|
|
467
|
+
await authorize(ctx, "sso.domain.manage", {
|
|
472
468
|
enterpriseId: args.enterpriseId,
|
|
473
469
|
});
|
|
474
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
475
470
|
return await auth.sso.admin.connection.domain.set(
|
|
476
471
|
ctx as never,
|
|
477
472
|
args.enterpriseId,
|
|
@@ -483,10 +478,9 @@ export function sso<
|
|
|
483
478
|
request: mutationGeneric({
|
|
484
479
|
args: enterpriseDomainVerificationInputValidator,
|
|
485
480
|
handler: async (ctx, args) => {
|
|
486
|
-
|
|
481
|
+
await authorize(ctx, "sso.domain.manage", {
|
|
487
482
|
enterpriseId: args.enterpriseId,
|
|
488
483
|
});
|
|
489
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
490
484
|
return await auth.sso.admin.connection.domain.verification.request(
|
|
491
485
|
ctx as never,
|
|
492
486
|
args,
|
|
@@ -496,10 +490,9 @@ export function sso<
|
|
|
496
490
|
confirm: actionGeneric({
|
|
497
491
|
args: enterpriseDomainVerificationInputValidator,
|
|
498
492
|
handler: async (ctx, args) => {
|
|
499
|
-
|
|
493
|
+
await authorize(ctx, "sso.domain.manage", {
|
|
500
494
|
enterpriseId: args.enterpriseId,
|
|
501
495
|
});
|
|
502
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
503
496
|
return await auth.sso.admin.connection.domain.verification.confirm(
|
|
504
497
|
ctx as never,
|
|
505
498
|
args,
|
|
@@ -524,20 +517,18 @@ export function sso<
|
|
|
524
517
|
extraFields: v.optional(v.record(v.string(), v.string())),
|
|
525
518
|
},
|
|
526
519
|
handler: async (ctx, args) => {
|
|
527
|
-
|
|
520
|
+
await authorize(ctx, "sso.protocol.manage", {
|
|
528
521
|
enterpriseId: args.enterpriseId,
|
|
529
522
|
});
|
|
530
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
531
523
|
return await auth.sso.admin.oidc.configure(ctx as never, args);
|
|
532
524
|
},
|
|
533
525
|
}),
|
|
534
526
|
get: queryGeneric({
|
|
535
527
|
args: { enterpriseId: v.string() },
|
|
536
528
|
handler: async (ctx, args) => {
|
|
537
|
-
|
|
529
|
+
await authorize(ctx, "sso.connection.read", {
|
|
538
530
|
enterpriseId: args.enterpriseId,
|
|
539
531
|
});
|
|
540
|
-
if (!_auth.ok) return null;
|
|
541
532
|
return await auth.sso.admin.oidc.get(
|
|
542
533
|
ctx as never,
|
|
543
534
|
args.enterpriseId,
|
|
@@ -547,10 +538,9 @@ export function sso<
|
|
|
547
538
|
validate: actionGeneric({
|
|
548
539
|
args: { enterpriseId: v.string() },
|
|
549
540
|
handler: async (ctx, args) => {
|
|
550
|
-
|
|
541
|
+
await authorize(ctx, "sso.protocol.manage", {
|
|
551
542
|
enterpriseId: args.enterpriseId,
|
|
552
543
|
});
|
|
553
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
554
544
|
return await auth.sso.admin.oidc.validate(
|
|
555
545
|
ctx as never,
|
|
556
546
|
args.enterpriseId,
|
|
@@ -572,20 +562,18 @@ export function sso<
|
|
|
572
562
|
sp: v.optional(enterpriseSamlSpValidator),
|
|
573
563
|
},
|
|
574
564
|
handler: async (ctx, args) => {
|
|
575
|
-
|
|
565
|
+
await authorize(ctx, "sso.protocol.manage", {
|
|
576
566
|
enterpriseId: args.enterpriseId,
|
|
577
567
|
});
|
|
578
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
579
568
|
return await auth.sso.admin.saml.configure(ctx as never, args);
|
|
580
569
|
},
|
|
581
570
|
}),
|
|
582
571
|
validate: queryGeneric({
|
|
583
572
|
args: { enterpriseId: v.string() },
|
|
584
573
|
handler: async (ctx, args) => {
|
|
585
|
-
|
|
574
|
+
await authorize(ctx, "sso.protocol.manage", {
|
|
586
575
|
enterpriseId: args.enterpriseId,
|
|
587
576
|
});
|
|
588
|
-
if (!_auth.ok) return null;
|
|
589
577
|
return await auth.sso.admin.saml.validate(
|
|
590
578
|
ctx as never,
|
|
591
579
|
args.enterpriseId,
|
|
@@ -597,10 +585,9 @@ export function sso<
|
|
|
597
585
|
get: queryGeneric({
|
|
598
586
|
args: { enterpriseId: v.string() },
|
|
599
587
|
handler: async (ctx, args) => {
|
|
600
|
-
|
|
588
|
+
await authorize(ctx, "sso.connection.read", {
|
|
601
589
|
enterpriseId: args.enterpriseId,
|
|
602
590
|
});
|
|
603
|
-
if (!_auth.ok) return null;
|
|
604
591
|
return await auth.sso.admin.policy.get(
|
|
605
592
|
ctx as never,
|
|
606
593
|
args.enterpriseId,
|
|
@@ -613,10 +600,9 @@ export function sso<
|
|
|
613
600
|
patch: enterprisePolicyPatchValidator,
|
|
614
601
|
},
|
|
615
602
|
handler: async (ctx, args) => {
|
|
616
|
-
|
|
603
|
+
await authorize(ctx, "sso.policy.manage", {
|
|
617
604
|
enterpriseId: args.enterpriseId,
|
|
618
605
|
});
|
|
619
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
620
606
|
return await auth.sso.admin.policy.update(
|
|
621
607
|
ctx as never,
|
|
622
608
|
args.enterpriseId,
|
|
@@ -627,10 +613,9 @@ export function sso<
|
|
|
627
613
|
validate: queryGeneric({
|
|
628
614
|
args: { enterpriseId: v.string() },
|
|
629
615
|
handler: async (ctx, args) => {
|
|
630
|
-
|
|
616
|
+
await authorize(ctx, "sso.policy.manage", {
|
|
631
617
|
enterpriseId: args.enterpriseId,
|
|
632
618
|
});
|
|
633
|
-
if (!_auth.ok) return null;
|
|
634
619
|
return await auth.sso.admin.policy.validate(
|
|
635
620
|
ctx as never,
|
|
636
621
|
args.enterpriseId,
|
|
@@ -646,11 +631,10 @@ export function sso<
|
|
|
646
631
|
limit: v.optional(v.number()),
|
|
647
632
|
},
|
|
648
633
|
handler: async (ctx, args) => {
|
|
649
|
-
|
|
634
|
+
await authorize(ctx, "sso.audit.read", {
|
|
650
635
|
enterpriseId: args.enterpriseId,
|
|
651
636
|
groupId: args.groupId,
|
|
652
637
|
});
|
|
653
|
-
if (!_auth.ok) return null;
|
|
654
638
|
return await auth.sso.admin.audit.list(ctx as never, args);
|
|
655
639
|
},
|
|
656
640
|
}),
|
|
@@ -663,10 +647,9 @@ export function sso<
|
|
|
663
647
|
limit: v.optional(v.number()),
|
|
664
648
|
},
|
|
665
649
|
handler: async (ctx, args) => {
|
|
666
|
-
|
|
650
|
+
await authorize(ctx, "sso.webhook.manage", {
|
|
667
651
|
enterpriseId: args.enterpriseId,
|
|
668
652
|
});
|
|
669
|
-
if (!_auth.ok) return null;
|
|
670
653
|
return await (auth.sso.admin.webhook as any).delivery.list(
|
|
671
654
|
ctx as never,
|
|
672
655
|
args,
|
|
@@ -687,8 +670,6 @@ export function sso<
|
|
|
687
670
|
const authResult = await authorize(ctx, "sso.webhook.manage", {
|
|
688
671
|
enterpriseId: args.enterpriseId,
|
|
689
672
|
});
|
|
690
|
-
if (!authResult.ok)
|
|
691
|
-
return { ok: false as const, code: authResult.code };
|
|
692
673
|
const { userId } = authResult;
|
|
693
674
|
const result = await auth.sso.admin.webhook.endpoint.create(
|
|
694
675
|
ctx as never,
|
|
@@ -711,10 +692,9 @@ export function sso<
|
|
|
711
692
|
list: queryGeneric({
|
|
712
693
|
args: { enterpriseId: v.string() },
|
|
713
694
|
handler: async (ctx, args) => {
|
|
714
|
-
|
|
695
|
+
await authorize(ctx, "sso.webhook.manage", {
|
|
715
696
|
enterpriseId: args.enterpriseId,
|
|
716
697
|
});
|
|
717
|
-
if (!_auth.ok) return null;
|
|
718
698
|
const endpoints = await auth.sso.admin.webhook.endpoint.list(
|
|
719
699
|
ctx as never,
|
|
720
700
|
args.enterpriseId,
|
|
@@ -733,16 +713,15 @@ export function sso<
|
|
|
733
713
|
args.endpointId,
|
|
734
714
|
);
|
|
735
715
|
if (!endpoint) {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
};
|
|
716
|
+
throw Cv.error({
|
|
717
|
+
code: "INVALID_PARAMETERS",
|
|
718
|
+
message: "Webhook endpoint not found.",
|
|
719
|
+
});
|
|
740
720
|
}
|
|
741
|
-
|
|
721
|
+
await authorize(ctx, "sso.webhook.manage", {
|
|
742
722
|
enterpriseId: endpoint.enterpriseId,
|
|
743
723
|
groupId: endpoint.groupId,
|
|
744
724
|
});
|
|
745
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
746
725
|
return await auth.sso.admin.webhook.endpoint.disable(
|
|
747
726
|
ctx as never,
|
|
748
727
|
args.endpointId,
|
|
@@ -811,7 +790,7 @@ export function sso<
|
|
|
811
790
|
export function scim<
|
|
812
791
|
TAuthorization extends AuthAuthorizationConfig | undefined = undefined,
|
|
813
792
|
>(
|
|
814
|
-
auth: Pick<AuthApi<TAuthorization>, "
|
|
793
|
+
auth: Pick<AuthApi<TAuthorization>, "context" | "scim" | "sso">,
|
|
815
794
|
options?: MountedEnterpriseOptions<AuthRoleId<TAuthorization>>,
|
|
816
795
|
) {
|
|
817
796
|
const authorize = createMountedAdminAuthorizer(auth, options);
|
|
@@ -825,30 +804,27 @@ export function scim<
|
|
|
825
804
|
status: v.optional(enterpriseStatusValidator),
|
|
826
805
|
},
|
|
827
806
|
handler: async (ctx, args) => {
|
|
828
|
-
|
|
807
|
+
await authorize(ctx, "scim.manage", {
|
|
829
808
|
enterpriseId: args.enterpriseId,
|
|
830
809
|
});
|
|
831
|
-
if (!_auth.ok) return { ok: false as const, code: _auth.code };
|
|
832
810
|
return await auth.scim.admin.configure(ctx as never, args);
|
|
833
811
|
},
|
|
834
812
|
}),
|
|
835
813
|
get: queryGeneric({
|
|
836
814
|
args: { enterpriseId: v.string() },
|
|
837
815
|
handler: async (ctx, args) => {
|
|
838
|
-
|
|
816
|
+
await authorize(ctx, "scim.manage", {
|
|
839
817
|
enterpriseId: args.enterpriseId,
|
|
840
818
|
});
|
|
841
|
-
if (!_auth.ok) return null;
|
|
842
819
|
return await auth.scim.admin.get(ctx as never, args.enterpriseId);
|
|
843
820
|
},
|
|
844
821
|
}),
|
|
845
822
|
validate: queryGeneric({
|
|
846
823
|
args: { enterpriseId: v.string() },
|
|
847
824
|
handler: async (ctx, args) => {
|
|
848
|
-
|
|
825
|
+
await authorize(ctx, "scim.manage", {
|
|
849
826
|
enterpriseId: args.enterpriseId,
|
|
850
827
|
});
|
|
851
|
-
if (!_auth.ok) return null;
|
|
852
828
|
return await auth.scim.admin.validate(
|
|
853
829
|
ctx as never,
|
|
854
830
|
args.enterpriseId,
|
|
@@ -899,7 +875,7 @@ export function enterprise<
|
|
|
899
875
|
>(
|
|
900
876
|
auth: Pick<
|
|
901
877
|
AuthApi<TAuthorization>,
|
|
902
|
-
"
|
|
878
|
+
"context" | "group" | "member" | "scim" | "sso"
|
|
903
879
|
>,
|
|
904
880
|
options: EnterpriseMountOptions<AuthRoleId<TAuthorization>>,
|
|
905
881
|
) {
|