@sudobility/auth_lib 0.0.12 → 0.0.14
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/admin/index.d.ts +5 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +5 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useSiteAdmin.d.ts +67 -0
- package/dist/hooks/useSiteAdmin.d.ts.map +1 -0
- package/dist/hooks/useSiteAdmin.js +69 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +6 -3
- package/dist/admin/admin-emails.d.ts +0 -56
- package/dist/admin/admin-emails.d.ts.map +0 -1
- package/dist/admin/admin-emails.js +0 -73
package/dist/admin/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Admin utilities exports
|
|
3
|
+
*
|
|
4
|
+
* Re-exports admin utilities from @sudobility/types for backwards compatibility.
|
|
5
|
+
* These utilities are now defined in @sudobility/types to be shared between
|
|
6
|
+
* frontend (auth_lib) and backend (auth_service) packages.
|
|
3
7
|
*/
|
|
4
|
-
export { parseAdminEmails, isAdminEmail, createAdminChecker, } from '
|
|
8
|
+
export { parseAdminEmails, isAdminEmail, createAdminChecker, } from '@sudobility/types';
|
|
5
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,GACnB,MAAM,mBAAmB,CAAC"}
|
package/dist/admin/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Admin utilities exports
|
|
3
|
+
*
|
|
4
|
+
* Re-exports admin utilities from @sudobility/types for backwards compatibility.
|
|
5
|
+
* These utilities are now defined in @sudobility/types to be shared between
|
|
6
|
+
* frontend (auth_lib) and backend (auth_service) packages.
|
|
3
7
|
*/
|
|
4
|
-
export { parseAdminEmails, isAdminEmail, createAdminChecker, } from '
|
|
8
|
+
export { parseAdminEmails, isAdminEmail, createAdminChecker, } from '@sudobility/types';
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
* @fileoverview Hooks exports
|
|
3
3
|
*/
|
|
4
4
|
export { useFirebaseAuthNetworkClient } from './useFirebaseAuthNetworkClient';
|
|
5
|
+
export { useSiteAdmin, siteAdminQueryKey, type UseSiteAdminOptions, type UseSiteAdminResult, type UserInfoResponse, } from './useSiteAdmin';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Hook to check if the current user is a site admin.
|
|
3
|
+
*
|
|
4
|
+
* Fetches user info from the backend API and caches the result using TanStack Query.
|
|
5
|
+
* This provides a single source of truth for site admin status from the backend.
|
|
6
|
+
*/
|
|
7
|
+
import type { NetworkClient, UserInfoResponse } from '@sudobility/types';
|
|
8
|
+
export type { UserInfoResponse } from '@sudobility/types';
|
|
9
|
+
/**
|
|
10
|
+
* Options for useSiteAdmin hook
|
|
11
|
+
*/
|
|
12
|
+
export interface UseSiteAdminOptions {
|
|
13
|
+
/** Network client for making API requests */
|
|
14
|
+
networkClient: NetworkClient;
|
|
15
|
+
/** Base URL of the API (e.g., "https://api.example.com/api/v1") */
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
/** Firebase user ID */
|
|
18
|
+
userId: string | undefined;
|
|
19
|
+
/** Firebase ID token for authentication */
|
|
20
|
+
token: string | undefined;
|
|
21
|
+
/** Cache time in milliseconds (default: 5 minutes) */
|
|
22
|
+
staleTime?: number;
|
|
23
|
+
/** Whether to enable the query (default: true when userId and token are provided) */
|
|
24
|
+
enabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Return type for useSiteAdmin hook
|
|
28
|
+
*/
|
|
29
|
+
export interface UseSiteAdminResult {
|
|
30
|
+
/** Whether the user is a site admin */
|
|
31
|
+
isSiteAdmin: boolean;
|
|
32
|
+
/** Full user info from the API */
|
|
33
|
+
userInfo: UserInfoResponse | null;
|
|
34
|
+
/** Whether the query is loading */
|
|
35
|
+
isLoading: boolean;
|
|
36
|
+
/** Whether the query has an error */
|
|
37
|
+
isError: boolean;
|
|
38
|
+
/** Error object if query failed */
|
|
39
|
+
error: Error | null;
|
|
40
|
+
/** Refetch the user info */
|
|
41
|
+
refetch: () => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Query key for site admin queries
|
|
45
|
+
*/
|
|
46
|
+
export declare const siteAdminQueryKey: (userId: string) => readonly ["siteAdmin", string];
|
|
47
|
+
/**
|
|
48
|
+
* Hook to check if the current user is a site admin.
|
|
49
|
+
*
|
|
50
|
+
* Fetches user info from the backend /users/:userId endpoint and caches the result.
|
|
51
|
+
* The backend is the single source of truth for site admin status.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* const { isSiteAdmin, isLoading } = useSiteAdmin({
|
|
56
|
+
* networkClient,
|
|
57
|
+
* baseUrl: 'https://api.example.com/api/v1',
|
|
58
|
+
* userId: user?.uid,
|
|
59
|
+
* token: idToken,
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* if (isLoading) return <Loading />;
|
|
63
|
+
* if (isSiteAdmin) return <AdminPanel />;
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function useSiteAdmin(options: UseSiteAdminOptions): UseSiteAdminResult;
|
|
67
|
+
//# sourceMappingURL=useSiteAdmin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSiteAdmin.d.ts","sourceRoot":"","sources":["../../src/hooks/useSiteAdmin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGzE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAW1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,6CAA6C;IAC7C,aAAa,EAAE,aAAa,CAAC;IAC7B,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,kCAAkC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,mCAChB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAqD7E"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Hook to check if the current user is a site admin.
|
|
3
|
+
*
|
|
4
|
+
* Fetches user info from the backend API and caches the result using TanStack Query.
|
|
5
|
+
* This provides a single source of truth for site admin status from the backend.
|
|
6
|
+
*/
|
|
7
|
+
import { useQuery } from '@tanstack/react-query';
|
|
8
|
+
/**
|
|
9
|
+
* Query key for site admin queries
|
|
10
|
+
*/
|
|
11
|
+
export const siteAdminQueryKey = (userId) => ['siteAdmin', userId];
|
|
12
|
+
/**
|
|
13
|
+
* Hook to check if the current user is a site admin.
|
|
14
|
+
*
|
|
15
|
+
* Fetches user info from the backend /users/:userId endpoint and caches the result.
|
|
16
|
+
* The backend is the single source of truth for site admin status.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const { isSiteAdmin, isLoading } = useSiteAdmin({
|
|
21
|
+
* networkClient,
|
|
22
|
+
* baseUrl: 'https://api.example.com/api/v1',
|
|
23
|
+
* userId: user?.uid,
|
|
24
|
+
* token: idToken,
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* if (isLoading) return <Loading />;
|
|
28
|
+
* if (isSiteAdmin) return <AdminPanel />;
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function useSiteAdmin(options) {
|
|
32
|
+
const { networkClient, baseUrl, userId, token, staleTime = 5 * 60 * 1000, // 5 minutes default
|
|
33
|
+
enabled, } = options;
|
|
34
|
+
const isEnabled = enabled ?? (!!userId && !!token);
|
|
35
|
+
const query = useQuery({
|
|
36
|
+
queryKey: siteAdminQueryKey(userId ?? ''),
|
|
37
|
+
queryFn: async () => {
|
|
38
|
+
if (!userId || !token) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const url = `${baseUrl}/users/${userId}`;
|
|
42
|
+
const response = await networkClient.get(url, {
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${token}`,
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok || !response.data?.success || !response.data.data) {
|
|
49
|
+
// User not found or not authorized - not an admin
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return response.data.data;
|
|
53
|
+
},
|
|
54
|
+
enabled: isEnabled,
|
|
55
|
+
staleTime,
|
|
56
|
+
// Retry once on failure (might be a transient network error)
|
|
57
|
+
retry: 1,
|
|
58
|
+
// Don't refetch on window focus for admin status
|
|
59
|
+
refetchOnWindowFocus: false,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
isSiteAdmin: query.data?.siteAdmin ?? false,
|
|
63
|
+
userInfo: query.data ?? null,
|
|
64
|
+
isLoading: query.isLoading,
|
|
65
|
+
isError: query.isError,
|
|
66
|
+
error: query.error,
|
|
67
|
+
refetch: query.refetch,
|
|
68
|
+
};
|
|
69
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
export { initializeFirebaseAuth, getFirebaseApp, getFirebaseAuth, getFirebaseConfig, isFirebaseConfigured, } from './config';
|
|
10
10
|
export type { FirebaseConfig, FirebaseInitOptions, FirebaseInitResult, FirebaseAuthNetworkClientOptions, } from './config';
|
|
11
11
|
export { useFirebaseAuthNetworkClient } from './hooks';
|
|
12
|
+
export { useSiteAdmin, siteAdminQueryKey, type UseSiteAdminOptions, type UseSiteAdminResult, type UserInfoResponse, } from './hooks';
|
|
12
13
|
export { getFirebaseErrorMessage, getFirebaseErrorCode, formatFirebaseError, isFirebaseAuthError, } from './utils';
|
|
13
14
|
export { parseAdminEmails, isAdminEmail, createAdminChecker } from './admin';
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,gCAAgC,GACjC,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,gCAAgC,GACjC,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAEvD,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
export { initializeFirebaseAuth, getFirebaseApp, getFirebaseAuth, getFirebaseConfig, isFirebaseConfigured, } from './config';
|
|
11
11
|
// Hooks
|
|
12
12
|
export { useFirebaseAuthNetworkClient } from './hooks';
|
|
13
|
+
export { useSiteAdmin, siteAdminQueryKey, } from './hooks';
|
|
13
14
|
// Utils
|
|
14
15
|
export { getFirebaseErrorMessage, getFirebaseErrorCode, formatFirebaseError, isFirebaseAuthError, } from './utils';
|
|
15
16
|
// Admin
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/auth_lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Firebase authentication utilities with token refresh handling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,10 +31,13 @@
|
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"react": "^19.2.3",
|
|
33
33
|
"firebase": "^12.7.0",
|
|
34
|
-
"@sudobility/di": "^1.5.
|
|
35
|
-
"@sudobility/types": "^1.9.
|
|
34
|
+
"@sudobility/di": "^1.5.21",
|
|
35
|
+
"@sudobility/types": "^1.9.48",
|
|
36
|
+
"@tanstack/react-query": "^5.0.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
39
|
+
"@sudobility/types": "^1.9.48",
|
|
40
|
+
"@tanstack/react-query": "^5.80.7",
|
|
38
41
|
"vitest": "^4.0.4",
|
|
39
42
|
"@eslint/js": "^9.0.0",
|
|
40
43
|
"@types/bun": "^1.2.8",
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Admin email whitelist utilities
|
|
3
|
-
*
|
|
4
|
-
* Provides functions for parsing and checking admin email whitelists,
|
|
5
|
-
* typically used for bypassing rate limits and subscription checks.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Parse admin emails from environment variable or string
|
|
9
|
-
*
|
|
10
|
-
* @param input - Comma-separated string of admin emails (e.g., "admin@example.com, other@example.com")
|
|
11
|
-
* @returns Array of normalized (lowercase, trimmed) email addresses
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const adminEmails = parseAdminEmails(process.env.ADMIN_EMAILS || "");
|
|
16
|
-
* // Returns: ["admin@example.com", "other@example.com"]
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
export declare function parseAdminEmails(input: string | undefined | null): string[];
|
|
20
|
-
/**
|
|
21
|
-
* Check if an email is in the admin whitelist
|
|
22
|
-
*
|
|
23
|
-
* @param email - Email address to check
|
|
24
|
-
* @param adminEmails - Array of admin emails (from parseAdminEmails)
|
|
25
|
-
* @returns True if the email is an admin
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```typescript
|
|
29
|
-
* const adminEmails = parseAdminEmails(process.env.ADMIN_EMAILS || "");
|
|
30
|
-
* if (isAdminEmail(user.email, adminEmails)) {
|
|
31
|
-
* // Skip rate limiting, subscription checks, etc.
|
|
32
|
-
* }
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export declare function isAdminEmail(email: string | undefined | null, adminEmails: string[]): boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Create a cached admin email checker
|
|
38
|
-
*
|
|
39
|
-
* Parses the admin emails once and returns a checker function.
|
|
40
|
-
* Useful for middleware where you don't want to re-parse on every request.
|
|
41
|
-
*
|
|
42
|
-
* @param input - Comma-separated string of admin emails
|
|
43
|
-
* @returns Function that checks if an email is an admin
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```typescript
|
|
47
|
-
* const isAdmin = createAdminChecker(process.env.ADMIN_EMAILS);
|
|
48
|
-
*
|
|
49
|
-
* // In middleware:
|
|
50
|
-
* if (isAdmin(user.email)) {
|
|
51
|
-
* // Bypass checks
|
|
52
|
-
* }
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
export declare function createAdminChecker(input: string | undefined | null): (email: string | undefined | null) => boolean;
|
|
56
|
-
//# sourceMappingURL=admin-emails.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"admin-emails.d.ts","sourceRoot":"","sources":["../../src/admin/admin-emails.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,EAAE,CAS3E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAChC,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAMT;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC/B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,KAAK,OAAO,CAM/C"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Admin email whitelist utilities
|
|
3
|
-
*
|
|
4
|
-
* Provides functions for parsing and checking admin email whitelists,
|
|
5
|
-
* typically used for bypassing rate limits and subscription checks.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Parse admin emails from environment variable or string
|
|
9
|
-
*
|
|
10
|
-
* @param input - Comma-separated string of admin emails (e.g., "admin@example.com, other@example.com")
|
|
11
|
-
* @returns Array of normalized (lowercase, trimmed) email addresses
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const adminEmails = parseAdminEmails(process.env.ADMIN_EMAILS || "");
|
|
16
|
-
* // Returns: ["admin@example.com", "other@example.com"]
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
export function parseAdminEmails(input) {
|
|
20
|
-
if (!input) {
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
return input
|
|
24
|
-
.split(',')
|
|
25
|
-
.map(email => email.trim().toLowerCase())
|
|
26
|
-
.filter(email => email.length > 0 && email.includes('@'));
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Check if an email is in the admin whitelist
|
|
30
|
-
*
|
|
31
|
-
* @param email - Email address to check
|
|
32
|
-
* @param adminEmails - Array of admin emails (from parseAdminEmails)
|
|
33
|
-
* @returns True if the email is an admin
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```typescript
|
|
37
|
-
* const adminEmails = parseAdminEmails(process.env.ADMIN_EMAILS || "");
|
|
38
|
-
* if (isAdminEmail(user.email, adminEmails)) {
|
|
39
|
-
* // Skip rate limiting, subscription checks, etc.
|
|
40
|
-
* }
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
export function isAdminEmail(email, adminEmails) {
|
|
44
|
-
if (!email) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
return adminEmails.includes(email.toLowerCase());
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Create a cached admin email checker
|
|
51
|
-
*
|
|
52
|
-
* Parses the admin emails once and returns a checker function.
|
|
53
|
-
* Useful for middleware where you don't want to re-parse on every request.
|
|
54
|
-
*
|
|
55
|
-
* @param input - Comma-separated string of admin emails
|
|
56
|
-
* @returns Function that checks if an email is an admin
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* const isAdmin = createAdminChecker(process.env.ADMIN_EMAILS);
|
|
61
|
-
*
|
|
62
|
-
* // In middleware:
|
|
63
|
-
* if (isAdmin(user.email)) {
|
|
64
|
-
* // Bypass checks
|
|
65
|
-
* }
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
export function createAdminChecker(input) {
|
|
69
|
-
const adminEmails = parseAdminEmails(input);
|
|
70
|
-
return (email) => {
|
|
71
|
-
return isAdminEmail(email, adminEmails);
|
|
72
|
-
};
|
|
73
|
-
}
|