Add oidc-provider with MongoDB adapter so ghostguild.org can act as the identity provider for the self-hosted Outline wiki. Members authenticate via the existing magic-link flow, with automatic SSO when an active session exists. Includes interaction routes, well-known discovery endpoint, and login page.
96 lines
3 KiB
Vue
96 lines
3 KiB
Vue
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: false,
|
|
});
|
|
|
|
const route = useRoute();
|
|
const uid = route.query.uid as string;
|
|
|
|
const email = ref("");
|
|
const sent = ref(false);
|
|
const loading = ref(false);
|
|
const error = ref("");
|
|
|
|
async function sendMagicLink() {
|
|
if (!email.value || !uid) return;
|
|
loading.value = true;
|
|
error.value = "";
|
|
|
|
try {
|
|
await $fetch("/oidc/interaction/login", {
|
|
method: "POST",
|
|
body: { email: email.value, uid },
|
|
});
|
|
sent.value = true;
|
|
} catch (e: any) {
|
|
error.value = e?.data?.statusMessage || "Something went wrong. Please try again.";
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="min-h-screen flex items-center justify-center bg-gray-50 px-4">
|
|
<div class="w-full max-w-sm">
|
|
<div class="bg-white rounded-lg shadow-md p-8">
|
|
<div class="text-center mb-6">
|
|
<h1 class="text-2xl font-bold text-gray-900">Ghost Guild Wiki</h1>
|
|
<p class="mt-2 text-sm text-gray-600">
|
|
Sign in with your Ghost Guild account
|
|
</p>
|
|
</div>
|
|
|
|
<template v-if="!sent">
|
|
<form @submit.prevent="sendMagicLink" class="space-y-4">
|
|
<div>
|
|
<label for="email" class="block text-sm font-medium text-gray-700 mb-1">
|
|
Email address
|
|
</label>
|
|
<input
|
|
id="email"
|
|
v-model="email"
|
|
type="email"
|
|
required
|
|
placeholder="you@example.com"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
|
:disabled="loading"
|
|
/>
|
|
</div>
|
|
|
|
<p v-if="error" class="text-sm text-red-600">{{ error }}</p>
|
|
|
|
<button
|
|
type="submit"
|
|
:disabled="loading || !email"
|
|
class="w-full py-2 px-4 bg-blue-600 text-white text-sm font-medium rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
>
|
|
{{ loading ? "Sending..." : "Send magic link" }}
|
|
</button>
|
|
</form>
|
|
|
|
<p class="mt-4 text-xs text-center text-gray-500">
|
|
We'll send a sign-in link to your email.
|
|
</p>
|
|
</template>
|
|
|
|
<template v-else>
|
|
<div class="text-center space-y-3">
|
|
<div class="text-4xl">✉️</div>
|
|
<h2 class="text-lg font-semibold text-gray-900">Check your email</h2>
|
|
<p class="text-sm text-gray-600">
|
|
We sent a sign-in link to <strong>{{ email }}</strong>.
|
|
Click the link in the email to continue.
|
|
</p>
|
|
<button
|
|
@click="sent = false; email = '';"
|
|
class="mt-4 text-sm text-blue-600 hover:text-blue-800"
|
|
>
|
|
Use a different email
|
|
</button>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|