Skip to main content

mcp_airlock/
templates.rs

1//! Default pages shown in the browser after the login callback. Override them
2//! with `--template-dir`; `{{ISSUER_NAME}}`, `{{RESOURCE_NAME}}` and (failure
3//! only) `{{ERROR_MESSAGE}}` are replaced with HTML-escaped values.
4
5/// Page shown after a successful login.
6pub const DEFAULT_SUCCESS_HTML: &str = r#"<!DOCTYPE html>
7<html lang="en">
8<head>
9    <meta charset="UTF-8">
10    <meta name="viewport" content="width=device-width, initial-scale=1.0">
11    <title>Authentication Successful</title>
12    <style>
13        body {
14            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
15            background-color: #f4f7f9;
16            display: flex;
17            justify-content: center;
18            align-items: center;
19            height: 100vh;
20            margin: 0;
21        }
22        .container {
23            background-color: #ffffff;
24            padding: 2.5rem;
25            border-radius: 12px;
26            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);
27            text-align: center;
28            max-width: 400px;
29            width: 90%;
30        }
31        .icon {
32            background-color: #e6f4ea;
33            color: #34a853;
34            width: 64px;
35            height: 64px;
36            border-radius: 50%;
37            display: flex;
38            justify-content: center;
39            align-items: center;
40            margin: 0 auto 1.5rem;
41        }
42        h1 {
43            color: #202124;
44            font-size: 1.5rem;
45            margin-bottom: 1rem;
46        }
47        p {
48            color: #5f6368;
49            line-height: 1.5;
50            margin-bottom: 1.5rem;
51        }
52        .close-hint {
53            font-size: 0.875rem;
54            color: #9aa0a6;
55        }
56        .context-info {
57            background-color: #f9fafb;
58            border: 1px solid #e5e7eb;
59            border-radius: 8px;
60            padding: 1rem;
61            margin-bottom: 1.5rem;
62            text-align: left;
63            font-size: 0.875rem;
64        }
65        .context-item {
66            margin-bottom: 0.5rem;
67            color: #374151;
68        }
69        .context-item:last-child {
70            margin-bottom: 0;
71        }
72        .context-label {
73            font-weight: 600;
74            color: #111827;
75            display: inline-block;
76            width: 80px;
77        }
78    </style>
79</head>
80<body>
81    <div class="container">
82        <div class="icon">
83            <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
84                <polyline points="20 6 9 17 4 12"></polyline>
85            </svg>
86        </div>
87        <h1>Authentication Successful</h1>
88        <p>You have successfully authenticated with <strong>mcp-airlock</strong>. You can now close this tab and return to your application.</p>
89        
90        <div class="context-info">
91            <div class="context-item">
92                <span class="context-label">Resource:</span> {{RESOURCE_NAME}}
93            </div>
94            <div class="context-item">
95                <span class="context-label">Identity:</span> {{ISSUER_NAME}}
96            </div>
97        </div>
98
99        <div class="close-hint">This tab can be safely closed.</div>
100    </div>
101</body>
102</html>
103"#;
104
105/// Page shown when the login callback fails.
106pub const DEFAULT_FAILURE_HTML: &str = r#"<!DOCTYPE html>
107<html lang="en">
108<head>
109    <meta charset="UTF-8">
110    <meta name="viewport" content="width=device-width, initial-scale=1.0">
111    <title>Authentication Failed</title>
112    <style>
113        body {
114            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
115            background-color: #fdf2f2;
116            display: flex;
117            justify-content: center;
118            align-items: center;
119            height: 100vh;
120            margin: 0;
121        }
122        .container {
123            background-color: #ffffff;
124            padding: 2.5rem;
125            border-radius: 12px;
126            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);
127            text-align: center;
128            max-width: 400px;
129            width: 90%;
130            border-top: 4px solid #f05252;
131        }
132        .icon {
133            background-color: #fde8e8;
134            color: #f05252;
135            width: 64px;
136            height: 64px;
137            border-radius: 50%;
138            display: flex;
139            justify-content: center;
140            align-items: center;
141            margin: 0 auto 1.5rem;
142        }
143        h1 {
144            color: #202124;
145            font-size: 1.5rem;
146            margin-bottom: 1rem;
147        }
148        p {
149            color: #5f6368;
150            line-height: 1.5;
151            margin-bottom: 1.5rem;
152        }
153        .context-info {
154            background-color: #f9fafb;
155            border: 1px solid #e5e7eb;
156            border-radius: 8px;
157            padding: 1rem;
158            margin-bottom: 1.5rem;
159            text-align: left;
160            font-size: 0.875rem;
161        }
162        .context-item {
163            margin-bottom: 0.5rem;
164            color: #374151;
165        }
166        .context-item:last-child {
167            margin-bottom: 0;
168        }
169        .context-label {
170            font-weight: 600;
171            color: #111827;
172            display: inline-block;
173            width: 80px;
174        }
175        .error-box {
176            background-color: #fef2f2;
177            border: 1px solid #fee2e2;
178            border-radius: 6px;
179            padding: 0.75rem;
180            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
181            font-size: 0.8125rem;
182            color: #991b1b;
183            text-align: left;
184            word-break: break-all;
185            margin-bottom: 1.5rem;
186        }
187        .retry-hint {
188            font-size: 0.875rem;
189            color: #9aa0a6;
190        }
191    </style>
192</head>
193<body>
194    <div class="container">
195        <div class="icon">
196            <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
197                <line x1="18" y1="6" x2="6" y2="18"></line>
198                <line x1="6" y1="6" x2="18" y2="18"></line>
199            </svg>
200        </div>
201        <h1>Authentication Failed</h1>
202        <p>Something went wrong during the authentication process.</p>
203
204        <div class="context-info">
205            <div class="context-item">
206                <span class="context-label">Resource:</span> {{RESOURCE_NAME}}
207            </div>
208            <div class="context-item">
209                <span class="context-label">Identity:</span> {{ISSUER_NAME}}
210            </div>
211        </div>
212
213        <div class="error-box">
214            {{ERROR_MESSAGE}}
215        </div>
216        <div class="retry-hint">Please try running the command again in your application.</div>
217    </div>
218</body>
219</html>
220"#;