@eventcatalog/core 2.42.10 → 2.43.1
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/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/catalog-to-astro-content-directory.js +2 -2
- package/dist/{chunk-QVBE3VN4.js → chunk-A6LT34RD.js} +1 -1
- package/dist/{chunk-HDG7YSFG.js → chunk-LUUBKWYP.js} +8 -0
- package/dist/{chunk-ZG2E6QCK.js → chunk-QYZZIYJW.js} +1 -1
- package/dist/{chunk-K7RD2O76.js → chunk-ZV5T7TKQ.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.auth.cjs +18 -0
- package/dist/eventcatalog.auth.d.cts +20 -0
- package/dist/eventcatalog.auth.d.ts +20 -0
- package/dist/eventcatalog.auth.js +0 -0
- package/dist/eventcatalog.cjs +50 -23
- package/dist/eventcatalog.js +29 -8
- package/dist/features.cjs +9 -0
- package/dist/features.d.cts +2 -1
- package/dist/features.d.ts +2 -1
- package/dist/features.js +3 -1
- package/dist/watcher.js +1 -1
- package/eventcatalog/astro.config.mjs +7 -3
- package/eventcatalog/auth.config.ts +156 -0
- package/eventcatalog/src/components/Header.astro +125 -25
- package/eventcatalog/src/middleware.ts +62 -0
- package/eventcatalog/src/pages/auth/error.astro +55 -0
- package/eventcatalog/src/pages/auth/login.astro +267 -0
- package/eventcatalog/src/pages/directory/[type]/_index.data.ts +63 -0
- package/eventcatalog/src/pages/directory/[type]/index.astro +6 -23
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +62 -0
- package/eventcatalog/src/pages/discover/[type]/index.astro +7 -24
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +62 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +5 -37
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/_[filename].data.ts +98 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +68 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +5 -25
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +6 -25
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +6 -35
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/_[filename].data.ts +99 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/index.astro +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/language/_index.data.ts +40 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/{language.astro → language/index.astro} +6 -20
- package/eventcatalog/src/pages/docs/custom/[...path]/_index.data.ts +49 -0
- package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +5 -11
- package/eventcatalog/src/pages/docs/teams/[id]/_index.data.ts +46 -0
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +6 -10
- package/eventcatalog/src/pages/docs/users/[id]/_index.data.ts +46 -0
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +5 -9
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +99 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +5 -29
- package/eventcatalog/src/utils/feature.ts +10 -0
- package/eventcatalog/src/utils/page-loaders/hybrid-page.ts +68 -0
- package/eventcatalog/tsconfig.json +2 -1
- package/package.json +3 -1
- package/dist/{chunk-SLEMYHTU.js → chunk-SFA7F3CQ.js} +3 -3
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { defineConfig } from 'auth-astro';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import GitHub from '@auth/core/providers/github';
|
|
4
|
+
import Okta from '@auth/core/providers/okta';
|
|
5
|
+
import type { Account, Profile, User, Session } from '@auth/core/types';
|
|
6
|
+
import { isAuthEnabled, isSSR } from '@utils/feature';
|
|
7
|
+
import Google from '@auth/core/providers/google';
|
|
8
|
+
import Auth0 from '@auth/core/providers/auth0';
|
|
9
|
+
|
|
10
|
+
// Need to try and read the eventcatalog.auth.js file and get the auth providers from there
|
|
11
|
+
const catalogDirectory = process.env.PROJECT_DIR || process.cwd();
|
|
12
|
+
|
|
13
|
+
const getAuthProviders = async () => {
|
|
14
|
+
try {
|
|
15
|
+
const config = await import(/* @vite-ignore */ join(catalogDirectory, 'eventcatalog.auth.js'));
|
|
16
|
+
const authConfig = config.default;
|
|
17
|
+
|
|
18
|
+
const providers = [];
|
|
19
|
+
|
|
20
|
+
// GitHub provider
|
|
21
|
+
if (authConfig.providers?.github) {
|
|
22
|
+
const githubConfig = authConfig.providers.github;
|
|
23
|
+
providers.push(
|
|
24
|
+
GitHub({
|
|
25
|
+
clientId: githubConfig.clientId,
|
|
26
|
+
clientSecret: githubConfig.clientSecret,
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
console.log('✅ GitHub provider configured');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Google provider
|
|
33
|
+
if (authConfig.providers?.google) {
|
|
34
|
+
const googleConfig = authConfig.providers.google;
|
|
35
|
+
providers.push(
|
|
36
|
+
Google({
|
|
37
|
+
clientId: googleConfig.clientId,
|
|
38
|
+
clientSecret: googleConfig.clientSecret,
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
console.log('✅ Google provider configured');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Okta provider
|
|
45
|
+
if (authConfig.providers?.okta) {
|
|
46
|
+
const oktaConfig = authConfig.providers.okta;
|
|
47
|
+
providers.push(
|
|
48
|
+
Okta({
|
|
49
|
+
clientId: oktaConfig.clientId,
|
|
50
|
+
clientSecret: oktaConfig.clientSecret,
|
|
51
|
+
issuer: oktaConfig.issuer,
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
console.log('✅ Okta provider configured');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Auth0 provider
|
|
58
|
+
if (authConfig.providers?.auth0) {
|
|
59
|
+
const auth0Config = authConfig.providers.auth0;
|
|
60
|
+
providers.push(
|
|
61
|
+
Auth0({
|
|
62
|
+
clientId: auth0Config.clientId,
|
|
63
|
+
clientSecret: auth0Config.clientSecret,
|
|
64
|
+
issuer: auth0Config.issuer,
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
console.log('✅ Auth0 provider configured');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (providers.length === 0) {
|
|
71
|
+
console.warn('⚠️ No auth providers configured');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return providers;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.log('No eventcatalog.auth.js found or error loading config:', (error as Error).message);
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const getAuthConfig = async () => {
|
|
82
|
+
// If auth is disabled or we are not in SSR, return an empty config
|
|
83
|
+
if (!isAuthEnabled() || !isSSR()) {
|
|
84
|
+
return {
|
|
85
|
+
providers: [],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const config = await import(/* @vite-ignore */ join(catalogDirectory, 'eventcatalog.auth.js'));
|
|
90
|
+
const authConfig = config.default;
|
|
91
|
+
|
|
92
|
+
// If custom auth config is specified (Enterprise feature)
|
|
93
|
+
if (authConfig?.customAuthConfig) {
|
|
94
|
+
console.log('🚀 Loading custom auth configuration:', authConfig.customAuthConfig);
|
|
95
|
+
try {
|
|
96
|
+
const customConfig = await import(/* @vite-ignore */ join(catalogDirectory, authConfig.customAuthConfig));
|
|
97
|
+
return customConfig.default;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error('❌ Failed to load custom auth config:', error);
|
|
100
|
+
// Fall back to managed config
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Return managed auth config
|
|
105
|
+
const providers = await getAuthProviders();
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
providers,
|
|
109
|
+
callbacks: {
|
|
110
|
+
async signIn({ user, account, profile }: { user: User; account: Account | null; profile?: Profile }) {
|
|
111
|
+
// Just allow everyone who can authenticate with the provider
|
|
112
|
+
return true;
|
|
113
|
+
},
|
|
114
|
+
async session({ session, token }: { session: Session; token: any }) {
|
|
115
|
+
// Add provider info to session
|
|
116
|
+
if (token?.provider) {
|
|
117
|
+
(session.user as any).provider = token.provider;
|
|
118
|
+
}
|
|
119
|
+
if (token?.login) {
|
|
120
|
+
(session.user as any).username = token.login;
|
|
121
|
+
}
|
|
122
|
+
return session;
|
|
123
|
+
},
|
|
124
|
+
async jwt({ token, account, profile }: { token: any; account: Account | null; profile?: Profile }) {
|
|
125
|
+
// Persist provider info in JWT
|
|
126
|
+
if (account && profile) {
|
|
127
|
+
token.provider = account.provider;
|
|
128
|
+
token.login = (profile as any).login || (profile as any).preferred_username;
|
|
129
|
+
}
|
|
130
|
+
return token;
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
pages: {
|
|
134
|
+
signIn: '/auth/login',
|
|
135
|
+
error: '/auth/error',
|
|
136
|
+
},
|
|
137
|
+
session: {
|
|
138
|
+
strategy: 'jwt' as const,
|
|
139
|
+
maxAge: authConfig?.session?.maxAge || 30 * 24 * 60 * 60, // 30 days default
|
|
140
|
+
},
|
|
141
|
+
debug: authConfig?.debug || false,
|
|
142
|
+
};
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.log(
|
|
145
|
+
'No auth config found, auth disabled. If you want to use auth, create a eventcatalog.auth.js file in your project directory.'
|
|
146
|
+
);
|
|
147
|
+
return {
|
|
148
|
+
providers: [],
|
|
149
|
+
pages: {
|
|
150
|
+
signIn: '/auth/disabled',
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export default defineConfig(await getAuthConfig());
|
|
@@ -3,6 +3,13 @@ import catalog from '@utils/eventcatalog-config/catalog';
|
|
|
3
3
|
import Search from '@components/Search.astro';
|
|
4
4
|
import { buildUrl } from '@utils/url-builder';
|
|
5
5
|
import { showEventCatalogBranding, showCustomBranding } from '@utils/feature';
|
|
6
|
+
import { getSession } from 'auth-astro/server';
|
|
7
|
+
import { isAuthEnabled, isSSR } from '@utils/feature';
|
|
8
|
+
|
|
9
|
+
let session = null;
|
|
10
|
+
if (isAuthEnabled()) {
|
|
11
|
+
session = await getSession(Astro.request);
|
|
12
|
+
}
|
|
6
13
|
|
|
7
14
|
const logo = {
|
|
8
15
|
src: ('/' + (catalog?.logo?.src || 'logo.png')).replace(/^\/+/, '/'),
|
|
@@ -27,35 +34,94 @@ const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalo
|
|
|
27
34
|
</div>
|
|
28
35
|
|
|
29
36
|
<div class="hidden lg:block flex-grow w-6/12 px-10">
|
|
30
|
-
|
|
37
|
+
<!-- Page find only works on static builds, disable for SSR builds for now -->
|
|
38
|
+
{!isSSR() && <Search />}
|
|
31
39
|
</div>
|
|
32
40
|
|
|
33
41
|
<div class="hidden md:block w-3/12">
|
|
34
42
|
{
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
43
|
+
session ? (
|
|
44
|
+
<div class="flex justify-end pr-2">
|
|
45
|
+
<div class="relative">
|
|
46
|
+
<button
|
|
47
|
+
id="profile-menu-button"
|
|
48
|
+
type="button"
|
|
49
|
+
class="flex items-center focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded-full"
|
|
50
|
+
aria-expanded="false"
|
|
51
|
+
aria-haspopup="true"
|
|
52
|
+
>
|
|
53
|
+
{session.user?.image && !session.user?.image?.includes('googleusercontent.com') ? (
|
|
54
|
+
<img
|
|
55
|
+
src={session.user.image}
|
|
56
|
+
alt={session.user?.name || 'User'}
|
|
57
|
+
class="h-8 w-8 rounded-full border-2 border-gray-200 hover:border-gray-300 transition-colors"
|
|
58
|
+
/>
|
|
59
|
+
) : (
|
|
60
|
+
<div class="h-8 w-8 rounded-full border-2 border-gray-200 hover:border-gray-300 transition-colors bg-gray-100 flex items-center justify-center text-sm font-medium text-gray-600">
|
|
61
|
+
{session.user?.name
|
|
62
|
+
? session.user.name
|
|
63
|
+
.split(' ')
|
|
64
|
+
.map((n) => n[0])
|
|
65
|
+
.join('')
|
|
66
|
+
.substring(0, 2)
|
|
67
|
+
.toUpperCase()
|
|
68
|
+
: 'U'}
|
|
69
|
+
</div>
|
|
70
|
+
)}
|
|
71
|
+
</button>
|
|
72
|
+
<div
|
|
73
|
+
id="profile-dropdown"
|
|
74
|
+
class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-50 border border-gray-100"
|
|
75
|
+
>
|
|
76
|
+
<div class="px-4 py-2 text-sm text-gray-700 border-b border-gray-100">
|
|
77
|
+
<div class="font-medium">{session.user?.name || 'User'}</div>
|
|
78
|
+
{session.user?.email && <div class="text-gray-500">{session.user.email}</div>}
|
|
79
|
+
</div>
|
|
80
|
+
<button
|
|
81
|
+
id="signout-btn"
|
|
82
|
+
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors"
|
|
83
|
+
>
|
|
84
|
+
Sign out
|
|
85
|
+
</button>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
) : (
|
|
90
|
+
<>
|
|
91
|
+
<div class="flex items-center space-x-4 justify-end pr-2">
|
|
92
|
+
{isAuthEnabled() && (
|
|
93
|
+
<button
|
|
94
|
+
id="okta-signin-btn"
|
|
95
|
+
class="bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium px-4 py-2 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
96
|
+
>
|
|
97
|
+
Sign In
|
|
98
|
+
</button>
|
|
99
|
+
)}
|
|
100
|
+
{showEventCatalogBranding() && (
|
|
101
|
+
<ul class="flex space-x-8">
|
|
102
|
+
<li>
|
|
103
|
+
<a href="https://discord.com/invite/3rjaZMmrAm">
|
|
104
|
+
<img src={buildUrl('/icons/discord.svg', true)} class="h-7 w-7" />
|
|
105
|
+
</a>
|
|
106
|
+
</li>
|
|
107
|
+
<li>
|
|
108
|
+
<a href="https://github.com/event-catalog/eventcatalog">
|
|
109
|
+
<img src={buildUrl('/icons/github.svg', true)} class="h-7 w-7" />
|
|
110
|
+
</a>
|
|
111
|
+
</li>
|
|
112
|
+
</ul>
|
|
113
|
+
)}
|
|
114
|
+
{showCustomBranding() && !showEventCatalogBranding() && (
|
|
115
|
+
<ul class="flex space-x-8">
|
|
116
|
+
<li>
|
|
117
|
+
<a href={repositoryUrl} class="text-gray-500 hover:text-gray-600 focus:outline-none focus:text-gray-600">
|
|
118
|
+
<img src={buildUrl('/icons/github.svg', true)} class="h-7 w-7" />
|
|
119
|
+
</a>
|
|
120
|
+
</li>
|
|
121
|
+
</ul>
|
|
122
|
+
)}
|
|
123
|
+
</div>
|
|
124
|
+
</>
|
|
59
125
|
)
|
|
60
126
|
}
|
|
61
127
|
</div>
|
|
@@ -100,12 +166,46 @@ const repositoryUrl = catalog?.repositoryUrl || 'https://github.com/event-catalo
|
|
|
100
166
|
<script>
|
|
101
167
|
const menuToggle = document.getElementById('menu-toggle');
|
|
102
168
|
const mobileMenu = document.getElementById('mobile-menu');
|
|
169
|
+
import { signOut } from 'auth-astro/client';
|
|
103
170
|
|
|
104
171
|
if (menuToggle && mobileMenu) {
|
|
105
172
|
menuToggle.addEventListener('click', () => {
|
|
106
173
|
mobileMenu.classList.toggle('hidden');
|
|
107
174
|
});
|
|
108
175
|
}
|
|
176
|
+
|
|
177
|
+
// Profile dropdown functionality
|
|
178
|
+
const profileButton = document.getElementById('profile-menu-button');
|
|
179
|
+
const profileDropdown = document.getElementById('profile-dropdown');
|
|
180
|
+
|
|
181
|
+
if (profileButton && profileDropdown) {
|
|
182
|
+
profileButton.addEventListener('click', (e) => {
|
|
183
|
+
e.stopPropagation();
|
|
184
|
+
profileDropdown.classList.toggle('hidden');
|
|
185
|
+
profileButton.setAttribute('aria-expanded', !profileDropdown.classList.contains('hidden') ? 'true' : 'false');
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Close dropdown when clicking outside
|
|
189
|
+
document.addEventListener('click', (e) => {
|
|
190
|
+
if (!profileButton.contains(e.target as Node) && !profileDropdown.contains(e.target as Node)) {
|
|
191
|
+
profileDropdown.classList.add('hidden');
|
|
192
|
+
profileButton.setAttribute('aria-expanded', 'false');
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Close dropdown on escape key
|
|
197
|
+
document.addEventListener('keydown', (e) => {
|
|
198
|
+
if (e.key === 'Escape' && !profileDropdown.classList.contains('hidden')) {
|
|
199
|
+
profileDropdown.classList.add('hidden');
|
|
200
|
+
profileButton.setAttribute('aria-expanded', 'false');
|
|
201
|
+
profileButton.focus();
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
document.getElementById('signout-btn')?.addEventListener('click', async () => {
|
|
206
|
+
await signOut();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
109
209
|
</script>
|
|
110
210
|
|
|
111
211
|
<style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/middleware.ts
|
|
2
|
+
import type { MiddlewareHandler } from 'astro';
|
|
3
|
+
import { getSession } from 'auth-astro/server';
|
|
4
|
+
import { isAuthEnabled } from '@utils/feature';
|
|
5
|
+
|
|
6
|
+
export const onRequest: MiddlewareHandler = async (context, next) => {
|
|
7
|
+
const { request, redirect, locals } = context;
|
|
8
|
+
const url = new URL(request.url);
|
|
9
|
+
const pathname = url.pathname;
|
|
10
|
+
|
|
11
|
+
// If auth is disabled and we are on an auth route, redirect to home
|
|
12
|
+
if (!isAuthEnabled() && pathname.includes('/auth')) {
|
|
13
|
+
return redirect('/');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Auth is disabled, skip auth check
|
|
17
|
+
if (!isAuthEnabled()) {
|
|
18
|
+
return next();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Skip system/browser requests
|
|
22
|
+
const systemRoutes = ['/.well-known/', '/favicon.ico', '/robots.txt', '/sitemap.xml', '/_astro/', '/__astro'];
|
|
23
|
+
|
|
24
|
+
// Skip auth check for these routes
|
|
25
|
+
const publicRoutes = ['/auth/login', '/auth/signout', '/auth/error', '/api/auth'];
|
|
26
|
+
|
|
27
|
+
// Skip static files, system routes, and browser requests
|
|
28
|
+
if (
|
|
29
|
+
pathname.startsWith('/_') ||
|
|
30
|
+
systemRoutes.some((route) => pathname.startsWith(route)) ||
|
|
31
|
+
pathname.startsWith('/.well-known/')
|
|
32
|
+
) {
|
|
33
|
+
return next();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Skip public routes
|
|
37
|
+
if (publicRoutes.some((route) => pathname.startsWith(route))) {
|
|
38
|
+
return next();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Check if user is logged in
|
|
43
|
+
const session = await getSession(request);
|
|
44
|
+
|
|
45
|
+
if (!session) {
|
|
46
|
+
const callbackUrl = encodeURIComponent(pathname + url.search);
|
|
47
|
+
return redirect(`/auth/login?callbackUrl=${callbackUrl}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Add session to locals for pages to use
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
locals.session = session;
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
locals.user = session.user;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error('Session error:', error);
|
|
57
|
+
const callbackUrl = encodeURIComponent(pathname + url.search);
|
|
58
|
+
return redirect(`/auth/login?callbackUrl=${callbackUrl}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return next();
|
|
62
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/pages/auth/error.astro
|
|
3
|
+
|
|
4
|
+
const { searchParams } = new URL(Astro.request.url);
|
|
5
|
+
const error = searchParams.get('error');
|
|
6
|
+
|
|
7
|
+
const errorMessages = {
|
|
8
|
+
Configuration: 'There is a problem with the server configuration.',
|
|
9
|
+
AccessDenied: 'You do not have permission to access this resource.',
|
|
10
|
+
Verification: 'The verification token has expired or has already been used.',
|
|
11
|
+
Default: 'An error occurred during authentication.',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const errorMessage = errorMessages[error] || errorMessages.Default;
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<main title="Authentication Error - EventCatalog">
|
|
19
|
+
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
|
20
|
+
<div class="max-w-md w-full space-y-8 text-center">
|
|
21
|
+
<div>
|
|
22
|
+
<svg class="mx-auto h-12 w-12 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
23
|
+
<path
|
|
24
|
+
stroke-linecap="round"
|
|
25
|
+
stroke-linejoin="round"
|
|
26
|
+
stroke-width="2"
|
|
27
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
28
|
+
></path>
|
|
29
|
+
</svg>
|
|
30
|
+
<h2 class="mt-6 text-3xl font-bold text-gray-900">Authentication Error</h2>
|
|
31
|
+
<p class="mt-2 text-sm text-gray-600">
|
|
32
|
+
{errorMessage}
|
|
33
|
+
</p>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="space-y-4">
|
|
37
|
+
<a
|
|
38
|
+
href="/auth/login"
|
|
39
|
+
class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
40
|
+
>
|
|
41
|
+
Try Again
|
|
42
|
+
</a>
|
|
43
|
+
|
|
44
|
+
<a
|
|
45
|
+
href="/"
|
|
46
|
+
class="w-full flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
47
|
+
>
|
|
48
|
+
Back to Home
|
|
49
|
+
</a>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
{error && <div class="mt-8 text-xs text-gray-400">Error code: {error}</div>}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</main>
|