@checkmate-monitor/auth-frontend 0.1.0

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.
@@ -0,0 +1,5 @@
1
+ import { createPlaywrightConfig } from "@checkmate-monitor/test-utils-frontend/playwright";
2
+
3
+ export default createPlaywrightConfig({
4
+ baseURL: "http://localhost:5173",
5
+ });
package/src/api.ts ADDED
@@ -0,0 +1,77 @@
1
+ import { createApiRef } from "@checkmate-monitor/frontend-api";
2
+
3
+ // Types for better-auth entities
4
+ export interface AuthUser {
5
+ id: string;
6
+ email: string;
7
+ name?: string;
8
+ image?: string;
9
+ }
10
+
11
+ export interface AuthSession {
12
+ session: {
13
+ id: string;
14
+ userId: string;
15
+ token: string;
16
+ expiresAt: Date;
17
+ };
18
+ user: AuthUser;
19
+ }
20
+
21
+ export interface Role {
22
+ id: string;
23
+ name: string;
24
+ description?: string | null;
25
+ isSystem?: boolean;
26
+ isAssignable?: boolean; // False for anonymous role - not assignable to users
27
+ permissions?: string[];
28
+ }
29
+
30
+ export interface Permission {
31
+ id: string;
32
+ description?: string;
33
+ }
34
+
35
+ export interface AuthStrategy {
36
+ id: string;
37
+ displayName: string;
38
+ description?: string;
39
+ icon?: string; // Lucide icon name
40
+ enabled: boolean;
41
+ configVersion: number;
42
+ configSchema: Record<string, unknown>; // JSON Schema
43
+ config?: Record<string, unknown>;
44
+ adminInstructions?: string; // Markdown instructions for admins
45
+ }
46
+
47
+ export interface EnabledAuthStrategy {
48
+ id: string;
49
+ displayName: string;
50
+ description?: string;
51
+ type: "credential" | "social";
52
+ icon?: string; // Lucide icon name
53
+ requiresManualRegistration: boolean;
54
+ }
55
+
56
+ /**
57
+ * AuthApi provides better-auth client methods for authentication.
58
+ * For RPC calls (including getEnabledStrategies, user/role/strategy management), use:
59
+ * const authClient = rpcApiRef.forPlugin<AuthClient>("auth");
60
+ */
61
+ export interface AuthApi {
62
+ // Better-auth methods (not RPC)
63
+ signIn(
64
+ email: string,
65
+ password: string
66
+ ): Promise<{ data?: AuthSession; error?: Error }>;
67
+ signInWithSocial(provider: string): Promise<void>;
68
+ signOut(): Promise<void>;
69
+ getSession(): Promise<{ data?: AuthSession; error?: Error }>;
70
+ useSession(): {
71
+ data?: AuthSession;
72
+ isPending: boolean;
73
+ error?: Error;
74
+ };
75
+ }
76
+
77
+ export const authApiRef = createApiRef<AuthApi>("auth.api");
@@ -0,0 +1,94 @@
1
+ import { Link, useSearchParams } from "react-router-dom";
2
+ import { AlertCircle, Home, LogIn } from "lucide-react";
3
+ import { authRoutes } from "@checkmate-monitor/auth-common";
4
+ import { resolveRoute } from "@checkmate-monitor/common";
5
+ import {
6
+ Button,
7
+ Card,
8
+ CardHeader,
9
+ CardTitle,
10
+ CardDescription,
11
+ CardContent,
12
+ CardFooter,
13
+ Alert,
14
+ AlertIcon,
15
+ AlertContent,
16
+ AlertTitle,
17
+ AlertDescription,
18
+ } from "@checkmate-monitor/ui";
19
+
20
+ /**
21
+ * Map technical error messages to user-friendly ones
22
+ */
23
+ const getErrorMessage = (error: string | undefined): string => {
24
+ if (!error) {
25
+ return "An unexpected error occurred during authentication.";
26
+ }
27
+
28
+ // Registration disabled error
29
+ if (error.includes("Registration is currently disabled")) {
30
+ return "Registration is currently disabled. Please contact an administrator if you need access.";
31
+ }
32
+
33
+ // User denied authorization
34
+ if (error.includes("access_denied") || error.includes("user_denied")) {
35
+ return "Authorization was cancelled. Please try again if you wish to sign in.";
36
+ }
37
+
38
+ // Generic OAuth errors
39
+ if (error.includes("UNKNOWN") || error.includes("unknown")) {
40
+ return "An unexpected error occurred. Please try again or contact support if the problem persists.";
41
+ }
42
+
43
+ // Return the error as-is if it seems user-friendly
44
+ return error;
45
+ };
46
+
47
+ export const AuthErrorPage = () => {
48
+ const [searchParams] = useSearchParams();
49
+ const errorParam = searchParams.get("error");
50
+
51
+ // better-auth encodes error messages using underscores for spaces
52
+ // Decode by replacing underscores with spaces
53
+ const decodedError = errorParam?.replaceAll("_", " ") ?? undefined;
54
+
55
+ const errorMessage = getErrorMessage(decodedError);
56
+
57
+ return (
58
+ <div className="min-h-[80vh] flex items-center justify-center">
59
+ <Card className="w-full max-w-md">
60
+ <CardHeader className="flex flex-col space-y-1 items-center">
61
+ <CardTitle>Authentication Error</CardTitle>
62
+ <CardDescription>
63
+ We encountered a problem during sign-in
64
+ </CardDescription>
65
+ </CardHeader>
66
+ <CardContent>
67
+ <Alert variant="error">
68
+ <AlertIcon>
69
+ <AlertCircle className="h-4 w-4" />
70
+ </AlertIcon>
71
+ <AlertContent>
72
+ <AlertTitle>Sign-in Failed</AlertTitle>
73
+ <AlertDescription>{errorMessage}</AlertDescription>
74
+ </AlertContent>
75
+ </Alert>
76
+ </CardContent>
77
+ <CardFooter className="flex gap-2 justify-center">
78
+ <Link to={resolveRoute(authRoutes.routes.login)}>
79
+ <Button variant="primary">
80
+ <LogIn className="mr-2 h-4 w-4" />
81
+ Try Again
82
+ </Button>
83
+ </Link>
84
+ <Link to="/">
85
+ <Button variant="outline">
86
+ <Home className="mr-2 h-4 w-4" />
87
+ Go Home
88
+ </Button>
89
+ </Link>
90
+ </CardFooter>
91
+ </Card>
92
+ </div>
93
+ );
94
+ };