@djangocfg/api 2.1.542 → 2.1.543
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/auth-server.cjs +1 -0
- package/dist/auth-server.cjs.map +1 -1
- package/dist/auth.cjs +57 -59
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +134 -7
- package/dist/auth.d.ts +134 -7
- package/dist/auth.mjs +69 -72
- package/dist/auth.mjs.map +1 -1
- package/dist/clients.cjs +1 -0
- package/dist/clients.cjs.map +1 -1
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/package.json +3 -2
- package/src/auth/__tests__/useTwoFactorStatus.test.ts +2 -2
- package/src/auth/context/AccountsContext.tsx +15 -11
- package/src/auth/hooks/useAuthForm.ts +0 -1
- package/src/auth/hooks/useCfgRouter.ts +1 -4
- package/src/auth/hooks/useGithubAuth.ts +25 -3
- package/src/auth/hooks/useLocalStorage.ts +7 -30
- package/src/auth/hooks/useSessionStorage.ts +6 -29
- package/src/auth/hooks/useTwoFactorVerify.ts +5 -9
- package/src/auth/utils/analytics.ts +22 -2
- package/src/auth/utils/errors.ts +22 -11
- package/src/auth/utils/storage.ts +64 -0
package/dist/auth-server.cjs
CHANGED
package/dist/auth-server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/server.ts","../src/auth/middlewares/proxy.ts"],"sourcesContent":["/**\n * @djangocfg/api/auth/server\n *\n * Server-side authentication utilities.\n * Use this entry point in server components, API routes, and middleware.\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { proxyMiddleware } from '@djangocfg/api/auth/server';\n *\n * export function middleware(request: NextRequest) {\n * return proxyMiddleware(request);\n * }\n * ```\n */\n\n// Middlewares\nexport * from './middlewares';\n","import { NextRequest, NextResponse } from 'next/server';\n\n/**\n * Proxy middleware for media and API endpoints\n * Use this in your middleware.ts file\n */\nexport function proxyMiddleware(request: NextRequest) {\n const { pathname, search } = request.nextUrl;\n const apiUrl = process.env.NEXT_PUBLIC_API_URL;\n\n // Proxy /media/* - Images and static files\n if (pathname.startsWith('/media/')) {\n const targetUrl = `${apiUrl}${pathname}${search}`;\n return NextResponse.rewrite(targetUrl, { request: { headers: request.headers } });\n }\n\n // Proxy /api/* - API endpoints\n if (pathname.startsWith('/api/')) {\n const targetUrl = `${apiUrl}${pathname}${search}`;\n return NextResponse.rewrite(targetUrl, { request: { headers: request.headers } });\n }\n\n return NextResponse.next();\n}\n\n/**\n * Recommended matcher config for proxy middleware\n * Add this to your middleware.ts config\n */\nexport const proxyMiddlewareConfig = {\n matcher: ['/media/:path*', '/api/:path*'],\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/auth/server.ts","../src/auth/middlewares/proxy.ts"],"sourcesContent":["/**\n * @djangocfg/api/auth/server\n *\n * Server-side authentication utilities.\n * Use this entry point in server components, API routes, and middleware.\n *\n * @example\n * ```typescript\n * // middleware.ts\n * import { proxyMiddleware } from '@djangocfg/api/auth/server';\n *\n * export function middleware(request: NextRequest) {\n * return proxyMiddleware(request);\n * }\n * ```\n */\n\n// Middlewares\nexport * from './middlewares';\n","import { NextRequest, NextResponse } from 'next/server';\n\n/**\n * Proxy middleware for media and API endpoints\n * Use this in your middleware.ts file\n */\nexport function proxyMiddleware(request: NextRequest) {\n const { pathname, search } = request.nextUrl;\n const apiUrl = process.env.NEXT_PUBLIC_API_URL;\n\n // Proxy /media/* - Images and static files\n if (pathname.startsWith('/media/')) {\n const targetUrl = `${apiUrl}${pathname}${search}`;\n return NextResponse.rewrite(targetUrl, { request: { headers: request.headers } });\n }\n\n // Proxy /api/* - API endpoints\n if (pathname.startsWith('/api/')) {\n const targetUrl = `${apiUrl}${pathname}${search}`;\n return NextResponse.rewrite(targetUrl, { request: { headers: request.headers } });\n }\n\n return NextResponse.next();\n}\n\n/**\n * Recommended matcher config for proxy middleware\n * Add this to your middleware.ts config\n */\nexport const proxyMiddlewareConfig = {\n matcher: ['/media/:path*', '/api/:path*'],\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA0C;AAMnC,SAAS,gBAAgB,SAAsB;AACpD,QAAM,EAAE,UAAU,OAAO,IAAI,QAAQ;AACrC,QAAM,SAAS,QAAQ,IAAI;AAG3B,MAAI,SAAS,WAAW,SAAS,GAAG;AAClC,UAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM;AAC/C,WAAO,2BAAa,QAAQ,WAAW,EAAE,SAAS,EAAE,SAAS,QAAQ,QAAQ,EAAE,CAAC;AAAA,EAClF;AAGA,MAAI,SAAS,WAAW,OAAO,GAAG;AAChC,UAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM;AAC/C,WAAO,2BAAa,QAAQ,WAAW,EAAE,SAAS,EAAE,SAAS,QAAQ,QAAQ,EAAE,CAAC;AAAA,EAClF;AAEA,SAAO,2BAAa,KAAK;AAC3B;AAjBgB;AAuBT,IAAM,wBAAwB;AAAA,EACnC,SAAS,CAAC,iBAAiB,aAAa;AAC1C;","names":[]}
|
package/dist/auth.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
"use strict";
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -943,9 +944,6 @@ __name(withBasePath, "withBasePath");
|
|
|
943
944
|
function useCfgRouter() {
|
|
944
945
|
const router = (0, import_navigation.useRouter)();
|
|
945
946
|
const basePath = (0, import_react2.useMemo)(() => getBasePath(), []);
|
|
946
|
-
const isStaticBuild2 = (0, import_react2.useMemo)(() => {
|
|
947
|
-
return typeof process !== "undefined" && process.env.NEXT_PUBLIC_STATIC_BUILD === "true";
|
|
948
|
-
}, []);
|
|
949
947
|
const push = (0, import_react2.useCallback)((href, options) => {
|
|
950
948
|
if (basePath) {
|
|
951
949
|
window.location.href = withBasePath(href, basePath);
|
|
@@ -2542,6 +2540,33 @@ var Analytics = {
|
|
|
2542
2540
|
|
|
2543
2541
|
// src/auth/hooks/useSessionStorage.ts
|
|
2544
2542
|
var import_react7 = require("react");
|
|
2543
|
+
|
|
2544
|
+
// src/auth/utils/storage.ts
|
|
2545
|
+
var MAX_ITEM_KB = 1024;
|
|
2546
|
+
function isQuotaExceededError(error) {
|
|
2547
|
+
if (typeof error !== "object" || error === null) return false;
|
|
2548
|
+
const { name, code, message } = error;
|
|
2549
|
+
return name === "QuotaExceededError" || code === 22 || typeof message === "string" && message.includes("quota");
|
|
2550
|
+
}
|
|
2551
|
+
__name(isQuotaExceededError, "isQuotaExceededError");
|
|
2552
|
+
function isWithinSizeLimit(data, key) {
|
|
2553
|
+
try {
|
|
2554
|
+
const sizeInKB = new Blob([JSON.stringify(data)]).size / 1024;
|
|
2555
|
+
if (sizeInKB > MAX_ITEM_KB) {
|
|
2556
|
+
authLogger.warn(
|
|
2557
|
+
`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`
|
|
2558
|
+
);
|
|
2559
|
+
return false;
|
|
2560
|
+
}
|
|
2561
|
+
return true;
|
|
2562
|
+
} catch (error) {
|
|
2563
|
+
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
2564
|
+
return false;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
__name(isWithinSizeLimit, "isWithinSizeLimit");
|
|
2568
|
+
|
|
2569
|
+
// src/auth/hooks/useSessionStorage.ts
|
|
2545
2570
|
function useSessionStorage(key, initialValue) {
|
|
2546
2571
|
const [storedValue, setStoredValue] = (0, import_react7.useState)(() => {
|
|
2547
2572
|
if (typeof window === "undefined") {
|
|
@@ -2555,21 +2580,6 @@ function useSessionStorage(key, initialValue) {
|
|
|
2555
2580
|
return initialValue;
|
|
2556
2581
|
}
|
|
2557
2582
|
});
|
|
2558
|
-
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
2559
|
-
try {
|
|
2560
|
-
const jsonString = JSON.stringify(data);
|
|
2561
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
2562
|
-
const sizeInKB = sizeInBytes / 1024;
|
|
2563
|
-
if (sizeInKB > 1024) {
|
|
2564
|
-
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
2565
|
-
return false;
|
|
2566
|
-
}
|
|
2567
|
-
return true;
|
|
2568
|
-
} catch (error) {
|
|
2569
|
-
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
2570
|
-
return false;
|
|
2571
|
-
}
|
|
2572
|
-
}, "checkDataSize");
|
|
2573
2583
|
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
2574
2584
|
try {
|
|
2575
2585
|
const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
@@ -2606,7 +2616,7 @@ function useSessionStorage(key, initialValue) {
|
|
|
2606
2616
|
const setValue = /* @__PURE__ */ __name((value) => {
|
|
2607
2617
|
try {
|
|
2608
2618
|
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
2609
|
-
if (!
|
|
2619
|
+
if (!isWithinSizeLimit(valueToStore, key)) {
|
|
2610
2620
|
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
2611
2621
|
try {
|
|
2612
2622
|
window.sessionStorage.removeItem(key);
|
|
@@ -2622,7 +2632,7 @@ function useSessionStorage(key, initialValue) {
|
|
|
2622
2632
|
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
|
|
2623
2633
|
window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
2624
2634
|
} catch (storageError) {
|
|
2625
|
-
if (storageError
|
|
2635
|
+
if (isQuotaExceededError(storageError)) {
|
|
2626
2636
|
authLogger.warn("sessionStorage quota exceeded, clearing old data...");
|
|
2627
2637
|
clearOldData();
|
|
2628
2638
|
try {
|
|
@@ -2658,7 +2668,7 @@ function useSessionStorage(key, initialValue) {
|
|
|
2658
2668
|
window.sessionStorage.removeItem(key);
|
|
2659
2669
|
window.sessionStorage.removeItem(`${key}_timestamp`);
|
|
2660
2670
|
} catch (removeError) {
|
|
2661
|
-
if (removeError
|
|
2671
|
+
if (isQuotaExceededError(removeError)) {
|
|
2662
2672
|
authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
|
|
2663
2673
|
clearOldData();
|
|
2664
2674
|
try {
|
|
@@ -2933,7 +2943,6 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
2933
2943
|
const {
|
|
2934
2944
|
identifier,
|
|
2935
2945
|
otp,
|
|
2936
|
-
isLoading,
|
|
2937
2946
|
acceptedTerms,
|
|
2938
2947
|
marketingConsent,
|
|
2939
2948
|
rememberMe,
|
|
@@ -3285,7 +3294,9 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3285
3294
|
if (response.user?.id) {
|
|
3286
3295
|
Analytics.setUser(String(response.user.id));
|
|
3287
3296
|
}
|
|
3288
|
-
|
|
3297
|
+
if (response.user) {
|
|
3298
|
+
onSuccess?.(response.user, response.is_new_user || false);
|
|
3299
|
+
}
|
|
3289
3300
|
if (!skipRedirect) {
|
|
3290
3301
|
const finalRedirectUrl = redirectUrl || "/private";
|
|
3291
3302
|
router.hardPush(finalRedirectUrl);
|
|
@@ -3518,21 +3529,6 @@ function useLocalStorage(key, initialValue) {
|
|
|
3518
3529
|
return initialValue;
|
|
3519
3530
|
}
|
|
3520
3531
|
});
|
|
3521
|
-
const checkDataSize = /* @__PURE__ */ __name((data) => {
|
|
3522
|
-
try {
|
|
3523
|
-
const jsonString = JSON.stringify(data);
|
|
3524
|
-
const sizeInBytes = new Blob([jsonString]).size;
|
|
3525
|
-
const sizeInKB = sizeInBytes / 1024;
|
|
3526
|
-
if (sizeInKB > 1024) {
|
|
3527
|
-
authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
|
|
3528
|
-
return false;
|
|
3529
|
-
}
|
|
3530
|
-
return true;
|
|
3531
|
-
} catch (error) {
|
|
3532
|
-
authLogger.error(`Error checking data size for key "${key}":`, error);
|
|
3533
|
-
return false;
|
|
3534
|
-
}
|
|
3535
|
-
}, "checkDataSize");
|
|
3536
3532
|
const clearOldData = /* @__PURE__ */ __name(() => {
|
|
3537
3533
|
try {
|
|
3538
3534
|
const keys = Object.keys(localStorage).filter((key2) => key2 && typeof key2 === "string");
|
|
@@ -3569,7 +3565,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
3569
3565
|
const setValue = /* @__PURE__ */ __name((value) => {
|
|
3570
3566
|
try {
|
|
3571
3567
|
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
3572
|
-
if (!
|
|
3568
|
+
if (!isWithinSizeLimit(valueToStore, key)) {
|
|
3573
3569
|
authLogger.warn(`Data size too large for key "${key}", removing key`);
|
|
3574
3570
|
try {
|
|
3575
3571
|
window.localStorage.removeItem(key);
|
|
@@ -3589,7 +3585,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
3589
3585
|
}
|
|
3590
3586
|
window.localStorage.setItem(`${key}_timestamp`, Date.now().toString());
|
|
3591
3587
|
} catch (storageError) {
|
|
3592
|
-
if (storageError
|
|
3588
|
+
if (isQuotaExceededError(storageError)) {
|
|
3593
3589
|
authLogger.warn("localStorage quota exceeded, clearing old data...");
|
|
3594
3590
|
clearOldData();
|
|
3595
3591
|
try {
|
|
@@ -3633,7 +3629,7 @@ function useLocalStorage(key, initialValue) {
|
|
|
3633
3629
|
window.localStorage.removeItem(key);
|
|
3634
3630
|
window.localStorage.removeItem(`${key}_timestamp`);
|
|
3635
3631
|
} catch (removeError) {
|
|
3636
|
-
if (removeError
|
|
3632
|
+
if (isQuotaExceededError(removeError)) {
|
|
3637
3633
|
authLogger.warn("localStorage quota exceeded during removal, clearing old data...");
|
|
3638
3634
|
clearOldData();
|
|
3639
3635
|
try {
|
|
@@ -4473,26 +4469,26 @@ function AccountsProvider({ children }) {
|
|
|
4473
4469
|
isLoadingRef.current = false;
|
|
4474
4470
|
}
|
|
4475
4471
|
}, []);
|
|
4476
|
-
const updateProfile =
|
|
4472
|
+
const updateProfile = (0, import_react15.useCallback)(async (data) => {
|
|
4477
4473
|
await triggerProfileUpdate({ body: data });
|
|
4478
4474
|
const user = await refreshProfile({ callerId: "updateProfile", force: true });
|
|
4479
4475
|
return user;
|
|
4480
|
-
},
|
|
4481
|
-
const partialUpdateProfile =
|
|
4476
|
+
}, [triggerProfileUpdate, refreshProfile]);
|
|
4477
|
+
const partialUpdateProfile = (0, import_react15.useCallback)(async (data) => {
|
|
4482
4478
|
await triggerProfilePartialUpdate({ body: data });
|
|
4483
4479
|
const user = await refreshProfile({ callerId: "partialUpdateProfile", force: true });
|
|
4484
4480
|
return user;
|
|
4485
|
-
},
|
|
4486
|
-
const uploadAvatar =
|
|
4481
|
+
}, [triggerProfilePartialUpdate, refreshProfile]);
|
|
4482
|
+
const uploadAvatar = (0, import_react15.useCallback)(async (avatar) => {
|
|
4487
4483
|
await triggerAvatar({ body: { avatar } });
|
|
4488
4484
|
const user = await refreshProfile({ callerId: "uploadAvatar", force: true });
|
|
4489
4485
|
return user;
|
|
4490
|
-
},
|
|
4491
|
-
const requestOTP =
|
|
4486
|
+
}, [triggerAvatar, refreshProfile]);
|
|
4487
|
+
const requestOTP = (0, import_react15.useCallback)(async (data) => {
|
|
4492
4488
|
const result = await triggerOtpRequest({ body: data });
|
|
4493
4489
|
return result;
|
|
4494
|
-
},
|
|
4495
|
-
const verifyOTP =
|
|
4490
|
+
}, [triggerOtpRequest]);
|
|
4491
|
+
const verifyOTP = (0, import_react15.useCallback)(async (data) => {
|
|
4496
4492
|
const result = await triggerOtpVerify({ body: data });
|
|
4497
4493
|
if (result.requires_2fa && result.session_id) {
|
|
4498
4494
|
authLogger.info("2FA required, session:", result.session_id);
|
|
@@ -4507,7 +4503,7 @@ function AccountsProvider({ children }) {
|
|
|
4507
4503
|
}
|
|
4508
4504
|
}
|
|
4509
4505
|
return result;
|
|
4510
|
-
},
|
|
4506
|
+
}, [triggerOtpVerify, refreshProfile]);
|
|
4511
4507
|
const logout = (0, import_react15.useCallback)(() => {
|
|
4512
4508
|
const refresh = auth.getRefreshToken();
|
|
4513
4509
|
if (refresh) {
|
|
@@ -4937,18 +4933,20 @@ var validateEmail = /* @__PURE__ */ __name((email) => {
|
|
|
4937
4933
|
}, "validateEmail");
|
|
4938
4934
|
|
|
4939
4935
|
// src/auth/utils/errors.ts
|
|
4936
|
+
var prop = /* @__PURE__ */ __name((value, key) => typeof value === "object" && value !== null ? value[key] : void 0, "prop");
|
|
4940
4937
|
var formatAuthError = /* @__PURE__ */ __name((error) => {
|
|
4941
4938
|
if (typeof error === "string") {
|
|
4942
4939
|
return error;
|
|
4943
4940
|
}
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4941
|
+
const candidates = [
|
|
4942
|
+
prop(error, "message"),
|
|
4943
|
+
prop(error, "detail"),
|
|
4944
|
+
prop(prop(prop(error, "response"), "data"), "detail")
|
|
4945
|
+
];
|
|
4946
|
+
for (const candidate of candidates) {
|
|
4947
|
+
if (typeof candidate === "string" && candidate) {
|
|
4948
|
+
return candidate;
|
|
4949
|
+
}
|
|
4952
4950
|
}
|
|
4953
4951
|
return "An unexpected error occurred";
|
|
4954
4952
|
}, "formatAuthError");
|