@checkstack/auth-frontend 0.5.17 → 0.5.19
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/CHANGELOG.md +42 -0
- package/package.json +6 -6
- package/src/components/ApplicationsTab.tsx +5 -6
- package/src/components/ChangePasswordPage.tsx +2 -1
- package/src/components/ForgotPasswordPage.tsx +1 -2
- package/src/components/LoginPage.tsx +5 -2
- package/src/components/OnboardingPage.tsx +2 -2
- package/src/components/RegisterPage.tsx +12 -18
- package/src/components/ResetPasswordPage.tsx +2 -2
- package/src/components/RolesTab.tsx +4 -3
- package/src/components/StrategiesTab.tsx +4 -3
- package/src/components/TeamAccessEditor.tsx +4 -3
- package/src/components/TeamsTab.tsx +8 -9
- package/src/components/UsersTab.tsx +4 -3
- package/src/index.tsx +3 -0
- package/src/lib/AuthAccessApi.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# @checkstack/auth-frontend
|
|
2
2
|
|
|
3
|
+
## 0.5.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [26d8bae]
|
|
8
|
+
- @checkstack/ui@1.3.0
|
|
9
|
+
|
|
10
|
+
## 0.5.18
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- d1a2796: Enforce stricter code quality standards and eliminate AI slop anti-patterns.
|
|
15
|
+
|
|
16
|
+
**New utility**
|
|
17
|
+
|
|
18
|
+
- `extractErrorMessage(error, fallback?)` in `@checkstack/common` for consistent error extraction
|
|
19
|
+
|
|
20
|
+
**ESLint rules**
|
|
21
|
+
|
|
22
|
+
- `react-hooks/rules-of-hooks` and `exhaustive-deps` for hook correctness
|
|
23
|
+
- `no-console` in frontend packages — forces `toast` over silent `console.error`
|
|
24
|
+
- `no-restricted-syntax` banning `instanceof Error` — forces `extractErrorMessage`
|
|
25
|
+
- Custom `no-eslint-disable-any` rule preventing `@typescript-eslint/no-explicit-any` circumvention
|
|
26
|
+
|
|
27
|
+
**Refactoring**
|
|
28
|
+
|
|
29
|
+
- Replace 141 `instanceof Error` boilerplate patterns across the codebase
|
|
30
|
+
- Replace swallowed `console.error` with user-visible `toast.error()` feedback
|
|
31
|
+
- Remove 15 redundant `as` type casts in IntegrationsPage and ProviderConnectionsPage
|
|
32
|
+
- Consolidate 3 identical callback handlers into `handleDialogClose`
|
|
33
|
+
- Fix conditional React hook call in `FormField.tsx`
|
|
34
|
+
- Fix unstable useMemo deps in `Dashboard.tsx`
|
|
35
|
+
- Replace `useEffect`→`setState` with derived `useMemo` in `RegisterPage.tsx`
|
|
36
|
+
- Rewrite `keystore.test.ts` with typed `DrizzleMockChain` (eliminating 7 `any` suppressions)
|
|
37
|
+
- Delete obvious comments in `encryption.ts` and Teams `provider.ts`
|
|
38
|
+
|
|
39
|
+
- Updated dependencies [d1a2796]
|
|
40
|
+
- @checkstack/common@0.6.5
|
|
41
|
+
- @checkstack/ui@1.2.1
|
|
42
|
+
- @checkstack/frontend-api@0.3.9
|
|
43
|
+
- @checkstack/auth-common@0.6.1
|
|
44
|
+
|
|
3
45
|
## 0.5.17
|
|
4
46
|
|
|
5
47
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/auth-frontend",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"checkstack": {
|
|
@@ -17,21 +17,21 @@
|
|
|
17
17
|
"test:e2e": "bunx playwright test"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@checkstack/frontend-api": "0.3.
|
|
21
|
-
"@checkstack/common": "0.6.
|
|
22
|
-
"@checkstack/ui": "1.1
|
|
20
|
+
"@checkstack/frontend-api": "0.3.9",
|
|
21
|
+
"@checkstack/common": "0.6.5",
|
|
22
|
+
"@checkstack/ui": "1.2.1",
|
|
23
23
|
"react": "^18.2.0",
|
|
24
24
|
"react-router-dom": "^6.22.0",
|
|
25
25
|
"lucide-react": "^0.344.0",
|
|
26
26
|
"better-auth": "^1.1.8",
|
|
27
|
-
"@checkstack/auth-common": "0.
|
|
27
|
+
"@checkstack/auth-common": "0.6.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"typescript": "^5.0.0",
|
|
31
31
|
"@types/react": "^18.2.0",
|
|
32
32
|
"@playwright/test": "^1.49.0",
|
|
33
33
|
"@checkstack/test-utils-frontend": "0.0.4",
|
|
34
|
-
"@checkstack/tsconfig": "0.0.
|
|
34
|
+
"@checkstack/tsconfig": "0.0.5",
|
|
35
35
|
"@checkstack/scripts": "0.1.2"
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -29,6 +29,7 @@ import { Plus, Trash2, RotateCcw, Copy } from "lucide-react";
|
|
|
29
29
|
import { usePluginClient } from "@checkstack/frontend-api";
|
|
30
30
|
import { AuthApi } from "@checkstack/auth-common";
|
|
31
31
|
import type { Role } from "../api";
|
|
32
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
32
33
|
|
|
33
34
|
export interface Application {
|
|
34
35
|
id: string;
|
|
@@ -89,7 +90,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
89
90
|
},
|
|
90
91
|
onError: (error) => {
|
|
91
92
|
toast.error(
|
|
92
|
-
error
|
|
93
|
+
extractErrorMessage(error, "Failed to create application"),
|
|
93
94
|
);
|
|
94
95
|
},
|
|
95
96
|
});
|
|
@@ -100,7 +101,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
100
101
|
},
|
|
101
102
|
onError: (error) => {
|
|
102
103
|
toast.error(
|
|
103
|
-
error
|
|
104
|
+
extractErrorMessage(error, "Failed to update application"),
|
|
104
105
|
);
|
|
105
106
|
},
|
|
106
107
|
});
|
|
@@ -113,7 +114,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
113
114
|
},
|
|
114
115
|
onError: (error) => {
|
|
115
116
|
toast.error(
|
|
116
|
-
error
|
|
117
|
+
extractErrorMessage(error, "Failed to delete application"),
|
|
117
118
|
);
|
|
118
119
|
},
|
|
119
120
|
});
|
|
@@ -130,9 +131,7 @@ export const ApplicationsTab: React.FC<ApplicationsTabProps> = ({
|
|
|
130
131
|
},
|
|
131
132
|
onError: (error) => {
|
|
132
133
|
toast.error(
|
|
133
|
-
error
|
|
134
|
-
? error.message
|
|
135
|
-
: "Failed to regenerate secret",
|
|
134
|
+
extractErrorMessage(error, "Failed to regenerate secret"),
|
|
136
135
|
);
|
|
137
136
|
},
|
|
138
137
|
});
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
Checkbox,
|
|
21
21
|
} from "@checkstack/ui";
|
|
22
22
|
import { getAuthClientLazy } from "../lib/auth-client";
|
|
23
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
23
24
|
|
|
24
25
|
export const ChangePasswordPage = () => {
|
|
25
26
|
const navigate = useNavigate();
|
|
@@ -84,7 +85,7 @@ export const ChangePasswordPage = () => {
|
|
|
84
85
|
}
|
|
85
86
|
} catch (error_) {
|
|
86
87
|
setError(
|
|
87
|
-
error_
|
|
88
|
+
extractErrorMessage(error_, "Failed to change password")
|
|
88
89
|
);
|
|
89
90
|
} finally {
|
|
90
91
|
setLoading(false);
|
|
@@ -31,9 +31,8 @@ export const ForgotPasswordPage = () => {
|
|
|
31
31
|
email,
|
|
32
32
|
redirectTo: "/auth/reset-password",
|
|
33
33
|
});
|
|
34
|
-
} catch
|
|
34
|
+
} catch {
|
|
35
35
|
// Silently handle errors to prevent timing attacks
|
|
36
|
-
console.error("Password reset request failed:", error);
|
|
37
36
|
} finally {
|
|
38
37
|
setLoading(false);
|
|
39
38
|
setSubmitted(true);
|
|
@@ -36,6 +36,8 @@ import {
|
|
|
36
36
|
InfoBannerTitle,
|
|
37
37
|
InfoBannerDescription,
|
|
38
38
|
} from "@checkstack/ui";
|
|
39
|
+
import { useToast } from "@checkstack/ui";
|
|
40
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
39
41
|
import { authApiRef, EnabledAuthStrategy } from "../api";
|
|
40
42
|
import { useEnabledStrategies } from "../hooks/useEnabledStrategies";
|
|
41
43
|
import { useAccessRules } from "../hooks/useAccessRules";
|
|
@@ -57,6 +59,7 @@ export const LoginPage = () => {
|
|
|
57
59
|
const authApi = useApi(authApiRef);
|
|
58
60
|
const authClient = usePluginClient(AuthApi);
|
|
59
61
|
const { strategies, loading: strategiesLoading } = useEnabledStrategies();
|
|
62
|
+
const toast = useToast();
|
|
60
63
|
|
|
61
64
|
// Query: Registration status
|
|
62
65
|
const { data: registrationData } = authClient.getRegistrationStatus.useQuery(
|
|
@@ -90,7 +93,7 @@ export const LoginPage = () => {
|
|
|
90
93
|
await authApi.signInWithSocial(strategy.id);
|
|
91
94
|
} catch (error) {
|
|
92
95
|
setError("Failed to initialize social login");
|
|
93
|
-
|
|
96
|
+
toast.error(extractErrorMessage(error, "Failed to initialize social login"));
|
|
94
97
|
}
|
|
95
98
|
return;
|
|
96
99
|
}
|
|
@@ -138,7 +141,7 @@ export const LoginPage = () => {
|
|
|
138
141
|
setError(data.error?.message || "Authentication failed");
|
|
139
142
|
}
|
|
140
143
|
} catch (error) {
|
|
141
|
-
|
|
144
|
+
toast.error(extractErrorMessage(error, "Social login failed"));
|
|
142
145
|
}
|
|
143
146
|
};
|
|
144
147
|
|
|
@@ -3,7 +3,7 @@ import { useNavigate } from "react-router-dom";
|
|
|
3
3
|
import { User, Lock, Mail, CheckCircle, AlertCircle } from "lucide-react";
|
|
4
4
|
import { usePluginClient } from "@checkstack/frontend-api";
|
|
5
5
|
import { AuthApi, authRoutes, passwordSchema } from "@checkstack/auth-common";
|
|
6
|
-
import { resolveRoute } from "@checkstack/common";
|
|
6
|
+
import { resolveRoute, extractErrorMessage} from "@checkstack/common";
|
|
7
7
|
import {
|
|
8
8
|
Button,
|
|
9
9
|
Input,
|
|
@@ -111,7 +111,7 @@ export const OnboardingPage = () => {
|
|
|
111
111
|
}
|
|
112
112
|
} catch (error_) {
|
|
113
113
|
const message =
|
|
114
|
-
error_
|
|
114
|
+
extractErrorMessage(error_, "Failed to complete setup");
|
|
115
115
|
setError(message);
|
|
116
116
|
} finally {
|
|
117
117
|
setLoading(false);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, { useState,
|
|
1
|
+
import React, { useState, useMemo } from "react";
|
|
2
2
|
import { Link } from "react-router-dom";
|
|
3
3
|
import { AlertCircle } from "lucide-react";
|
|
4
4
|
import { useApi, usePluginClient } from "@checkstack/frontend-api";
|
|
5
5
|
import { authApiRef } from "../api";
|
|
6
6
|
import { AuthApi, authRoutes, passwordSchema } from "@checkstack/auth-common";
|
|
7
|
-
import { resolveRoute } from "@checkstack/common";
|
|
7
|
+
import { resolveRoute, extractErrorMessage } from "@checkstack/common";
|
|
8
8
|
import {
|
|
9
9
|
Button,
|
|
10
10
|
Input,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
InfoBannerContent,
|
|
21
21
|
InfoBannerTitle,
|
|
22
22
|
InfoBannerDescription,
|
|
23
|
+
useToast,
|
|
23
24
|
} from "@checkstack/ui";
|
|
24
25
|
import { useEnabledStrategies } from "../hooks/useEnabledStrategies";
|
|
25
26
|
import { SocialProviderButton } from "./SocialProviderButton";
|
|
@@ -30,25 +31,18 @@ export const RegisterPage = () => {
|
|
|
30
31
|
const [email, setEmail] = useState("");
|
|
31
32
|
const [password, setPassword] = useState("");
|
|
32
33
|
const [loading, setLoading] = useState(false);
|
|
33
|
-
const [validationErrors, setValidationErrors] = useState<string[]>([]);
|
|
34
34
|
|
|
35
35
|
const authApi = useApi(authApiRef);
|
|
36
36
|
const authClient = usePluginClient(AuthApi);
|
|
37
37
|
const { strategies, loading: strategiesLoading } = useEnabledStrategies();
|
|
38
38
|
const authBetterClient = getAuthClientLazy();
|
|
39
|
+
const toast = useToast();
|
|
39
40
|
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
if (password)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
setValidationErrors([]);
|
|
46
|
-
} else {
|
|
47
|
-
setValidationErrors(result.error.issues.map((issue) => issue.message));
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
setValidationErrors([]);
|
|
51
|
-
}
|
|
41
|
+
// Derive validation errors directly from password (no state/effect needed)
|
|
42
|
+
const validationErrors = useMemo(() => {
|
|
43
|
+
if (!password) return [];
|
|
44
|
+
const result = passwordSchema.safeParse(password);
|
|
45
|
+
return result.success ? [] : result.error.issues.map((issue) => issue.message);
|
|
52
46
|
}, [password]);
|
|
53
47
|
|
|
54
48
|
// Query: Registration status
|
|
@@ -73,13 +67,13 @@ export const RegisterPage = () => {
|
|
|
73
67
|
password,
|
|
74
68
|
});
|
|
75
69
|
if (res.error) {
|
|
76
|
-
|
|
70
|
+
toast.error(res.error.message ?? "Registration failed");
|
|
77
71
|
} else {
|
|
78
72
|
// Use full page navigation to ensure session state refreshes in navbar
|
|
79
73
|
globalThis.location.href = "/";
|
|
80
74
|
}
|
|
81
75
|
} catch (error) {
|
|
82
|
-
|
|
76
|
+
toast.error(extractErrorMessage(error, "Registration failed"));
|
|
83
77
|
} finally {
|
|
84
78
|
setLoading(false);
|
|
85
79
|
}
|
|
@@ -90,7 +84,7 @@ export const RegisterPage = () => {
|
|
|
90
84
|
await authApi.signInWithSocial(provider);
|
|
91
85
|
// Navigation will happen automatically after OAuth redirect
|
|
92
86
|
} catch (error) {
|
|
93
|
-
|
|
87
|
+
toast.error(extractErrorMessage(error, "Social registration failed"));
|
|
94
88
|
}
|
|
95
89
|
};
|
|
96
90
|
|
|
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
|
|
2
2
|
import { Link, useSearchParams, useNavigate } from "react-router-dom";
|
|
3
3
|
import { Lock, ArrowLeft, CheckCircle, AlertCircle } from "lucide-react";
|
|
4
4
|
import { authRoutes, passwordSchema } from "@checkstack/auth-common";
|
|
5
|
-
import { resolveRoute } from "@checkstack/common";
|
|
5
|
+
import { resolveRoute, extractErrorMessage} from "@checkstack/common";
|
|
6
6
|
import {
|
|
7
7
|
Button,
|
|
8
8
|
Input,
|
|
@@ -83,7 +83,7 @@ export const ResetPasswordPage = () => {
|
|
|
83
83
|
}
|
|
84
84
|
} catch (error_) {
|
|
85
85
|
setError(
|
|
86
|
-
error_
|
|
86
|
+
extractErrorMessage(error_, "Failed to reset password")
|
|
87
87
|
);
|
|
88
88
|
} finally {
|
|
89
89
|
setLoading(false);
|
|
@@ -21,6 +21,7 @@ import { usePluginClient } from "@checkstack/frontend-api";
|
|
|
21
21
|
import { AuthApi } from "@checkstack/auth-common";
|
|
22
22
|
import type { Role, AccessRuleEntry } from "../api";
|
|
23
23
|
import { RoleDialog } from "./RoleDialog";
|
|
24
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
24
25
|
|
|
25
26
|
export interface RolesTabProps {
|
|
26
27
|
roles: Role[];
|
|
@@ -58,7 +59,7 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
58
59
|
},
|
|
59
60
|
onError: (error) => {
|
|
60
61
|
toast.error(
|
|
61
|
-
error
|
|
62
|
+
extractErrorMessage(error, "Failed to create role"),
|
|
62
63
|
);
|
|
63
64
|
},
|
|
64
65
|
});
|
|
@@ -70,7 +71,7 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
70
71
|
},
|
|
71
72
|
onError: (error) => {
|
|
72
73
|
toast.error(
|
|
73
|
-
error
|
|
74
|
+
extractErrorMessage(error, "Failed to update role"),
|
|
74
75
|
);
|
|
75
76
|
},
|
|
76
77
|
});
|
|
@@ -83,7 +84,7 @@ export const RolesTab: React.FC<RolesTabProps> = ({
|
|
|
83
84
|
},
|
|
84
85
|
onError: (error) => {
|
|
85
86
|
toast.error(
|
|
86
|
-
error
|
|
87
|
+
extractErrorMessage(error, "Failed to delete role"),
|
|
87
88
|
);
|
|
88
89
|
},
|
|
89
90
|
});
|
|
@@ -19,6 +19,7 @@ import { usePluginClient } from "@checkstack/frontend-api";
|
|
|
19
19
|
import { AuthApi } from "@checkstack/auth-common";
|
|
20
20
|
import type { AuthStrategy } from "../api";
|
|
21
21
|
import { AuthStrategyCard } from "./AuthStrategyCard";
|
|
22
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
22
23
|
|
|
23
24
|
export interface StrategiesTabProps {
|
|
24
25
|
strategies: AuthStrategy[];
|
|
@@ -88,7 +89,7 @@ export const StrategiesTab: React.FC<StrategiesTabProps> = ({
|
|
|
88
89
|
},
|
|
89
90
|
onError: (error) => {
|
|
90
91
|
toast.error(
|
|
91
|
-
error
|
|
92
|
+
extractErrorMessage(error, "Failed to update strategy")
|
|
92
93
|
);
|
|
93
94
|
},
|
|
94
95
|
});
|
|
@@ -99,7 +100,7 @@ export const StrategiesTab: React.FC<StrategiesTabProps> = ({
|
|
|
99
100
|
},
|
|
100
101
|
onError: (error) => {
|
|
101
102
|
toast.error(
|
|
102
|
-
error
|
|
103
|
+
extractErrorMessage(error, "Failed to save settings")
|
|
103
104
|
);
|
|
104
105
|
},
|
|
105
106
|
});
|
|
@@ -112,7 +113,7 @@ export const StrategiesTab: React.FC<StrategiesTabProps> = ({
|
|
|
112
113
|
},
|
|
113
114
|
onError: (error) => {
|
|
114
115
|
toast.error(
|
|
115
|
-
error
|
|
116
|
+
extractErrorMessage(error, "Failed to reload auth")
|
|
116
117
|
);
|
|
117
118
|
setReloading(false);
|
|
118
119
|
},
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
accessApiRef,
|
|
34
34
|
} from "@checkstack/frontend-api";
|
|
35
35
|
import { AuthApi, authAccess } from "@checkstack/auth-common";
|
|
36
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
36
37
|
|
|
37
38
|
interface TeamAccess {
|
|
38
39
|
teamId: string;
|
|
@@ -121,7 +122,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
121
122
|
},
|
|
122
123
|
onError: (error) => {
|
|
123
124
|
toast.error(
|
|
124
|
-
error
|
|
125
|
+
extractErrorMessage(error, "Failed to update access"),
|
|
125
126
|
);
|
|
126
127
|
},
|
|
127
128
|
});
|
|
@@ -134,7 +135,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
134
135
|
},
|
|
135
136
|
onError: (error) => {
|
|
136
137
|
toast.error(
|
|
137
|
-
error
|
|
138
|
+
extractErrorMessage(error, "Failed to remove access"),
|
|
138
139
|
);
|
|
139
140
|
},
|
|
140
141
|
});
|
|
@@ -146,7 +147,7 @@ export const TeamAccessEditor: React.FC<TeamAccessEditorProps> = ({
|
|
|
146
147
|
},
|
|
147
148
|
onError: (error) => {
|
|
148
149
|
toast.error(
|
|
149
|
-
error
|
|
150
|
+
extractErrorMessage(error, "Failed to update settings"),
|
|
150
151
|
);
|
|
151
152
|
},
|
|
152
153
|
});
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
import { usePluginClient } from "@checkstack/frontend-api";
|
|
44
44
|
import { AuthApi } from "@checkstack/auth-common";
|
|
45
45
|
import type { AuthUser } from "../api";
|
|
46
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
46
47
|
|
|
47
48
|
interface Team {
|
|
48
49
|
id: string;
|
|
@@ -116,7 +117,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
116
117
|
},
|
|
117
118
|
onError: (error) => {
|
|
118
119
|
toast.error(
|
|
119
|
-
error
|
|
120
|
+
extractErrorMessage(error, "Failed to create team"),
|
|
120
121
|
);
|
|
121
122
|
},
|
|
122
123
|
});
|
|
@@ -130,7 +131,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
130
131
|
},
|
|
131
132
|
onError: (error) => {
|
|
132
133
|
toast.error(
|
|
133
|
-
error
|
|
134
|
+
extractErrorMessage(error, "Failed to update team"),
|
|
134
135
|
);
|
|
135
136
|
},
|
|
136
137
|
});
|
|
@@ -144,7 +145,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
144
145
|
},
|
|
145
146
|
onError: (error) => {
|
|
146
147
|
toast.error(
|
|
147
|
-
error
|
|
148
|
+
extractErrorMessage(error, "Failed to delete team"),
|
|
148
149
|
);
|
|
149
150
|
},
|
|
150
151
|
});
|
|
@@ -158,7 +159,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
158
159
|
},
|
|
159
160
|
onError: (error) => {
|
|
160
161
|
toast.error(
|
|
161
|
-
error
|
|
162
|
+
extractErrorMessage(error, "Failed to add member"),
|
|
162
163
|
);
|
|
163
164
|
},
|
|
164
165
|
});
|
|
@@ -171,7 +172,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
171
172
|
},
|
|
172
173
|
onError: (error) => {
|
|
173
174
|
toast.error(
|
|
174
|
-
error
|
|
175
|
+
extractErrorMessage(error, "Failed to remove member"),
|
|
175
176
|
);
|
|
176
177
|
},
|
|
177
178
|
});
|
|
@@ -183,7 +184,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
183
184
|
},
|
|
184
185
|
onError: (error) => {
|
|
185
186
|
toast.error(
|
|
186
|
-
error
|
|
187
|
+
extractErrorMessage(error, "Failed to promote to manager"),
|
|
187
188
|
);
|
|
188
189
|
},
|
|
189
190
|
});
|
|
@@ -195,9 +196,7 @@ export const TeamsTab: React.FC<TeamsTabProps> = ({
|
|
|
195
196
|
},
|
|
196
197
|
onError: (error) => {
|
|
197
198
|
toast.error(
|
|
198
|
-
error
|
|
199
|
-
? error.message
|
|
200
|
-
: "Failed to remove manager role",
|
|
199
|
+
extractErrorMessage(error, "Failed to remove manager role"),
|
|
201
200
|
);
|
|
202
201
|
},
|
|
203
202
|
});
|
|
@@ -23,6 +23,7 @@ import { usePluginClient } from "@checkstack/frontend-api";
|
|
|
23
23
|
import { AuthApi } from "@checkstack/auth-common";
|
|
24
24
|
import type { AuthUser, Role, AuthStrategy } from "../api";
|
|
25
25
|
import { CreateUserDialog } from "./CreateUserDialog";
|
|
26
|
+
import { extractErrorMessage } from "@checkstack/common";
|
|
26
27
|
|
|
27
28
|
export interface UsersTabProps {
|
|
28
29
|
users: (AuthUser & { roles: string[] })[];
|
|
@@ -66,7 +67,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
66
67
|
},
|
|
67
68
|
onError: (error) => {
|
|
68
69
|
toast.error(
|
|
69
|
-
error
|
|
70
|
+
extractErrorMessage(error, "Failed to delete user"),
|
|
70
71
|
);
|
|
71
72
|
},
|
|
72
73
|
});
|
|
@@ -77,7 +78,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
77
78
|
},
|
|
78
79
|
onError: (error) => {
|
|
79
80
|
toast.error(
|
|
80
|
-
error
|
|
81
|
+
extractErrorMessage(error, "Failed to update roles"),
|
|
81
82
|
);
|
|
82
83
|
},
|
|
83
84
|
});
|
|
@@ -89,7 +90,7 @@ export const UsersTab: React.FC<UsersTabProps> = ({
|
|
|
89
90
|
},
|
|
90
91
|
onError: (error) => {
|
|
91
92
|
toast.error(
|
|
92
|
-
error
|
|
93
|
+
extractErrorMessage(error, "Failed to create user"),
|
|
93
94
|
);
|
|
94
95
|
throw error;
|
|
95
96
|
},
|
package/src/index.tsx
CHANGED
|
@@ -108,6 +108,7 @@ class BetterAuthApi implements AuthApi {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
useSession() {
|
|
111
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- Class adapter delegates to hook; consumed as API, not a component
|
|
111
112
|
return useSessionContext();
|
|
112
113
|
}
|
|
113
114
|
}
|
|
@@ -178,6 +179,7 @@ export const authPlugin = createFrontendPlugin({
|
|
|
178
179
|
createSlotExtension(UserMenuItemsSlot, {
|
|
179
180
|
id: "auth.user-menu.settings",
|
|
180
181
|
component: ({ accessRules: userPerms }: UserMenuItemsContext) => {
|
|
182
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- Inline component used via createSlotExtension
|
|
181
183
|
const navigate = useNavigate();
|
|
182
184
|
const qualifiedId = `${pluginMetadata.pluginId}.${authAccess.strategies.id}`;
|
|
183
185
|
const canManage =
|
|
@@ -198,6 +200,7 @@ export const authPlugin = createFrontendPlugin({
|
|
|
198
200
|
createSlotExtension(UserMenuItemsSlot, {
|
|
199
201
|
id: "auth.user-menu.profile",
|
|
200
202
|
component: () => {
|
|
203
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- Inline component used via createSlotExtension
|
|
201
204
|
const navigate = useNavigate();
|
|
202
205
|
|
|
203
206
|
return (
|
package/src/lib/AuthAccessApi.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { AccessRule } from "@checkstack/common";
|
|
|
8
8
|
*/
|
|
9
9
|
export class AuthAccessApi implements AccessApi {
|
|
10
10
|
useAccess(accessRule: AccessRule): { loading: boolean; allowed: boolean } {
|
|
11
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- Class adapter delegates to hook; consumed as API, not a component
|
|
11
12
|
const { accessRules, loading } = useAccessRules();
|
|
12
13
|
|
|
13
14
|
if (loading) {
|