Let testers sign in: an opt-in password form on the login page
The login page offered only a magic link, and the devstack's Supabase cannot send email: POST /auth/v1/otp for an existing user answers 500 "Error sending magic link email". So nobody could sign in through the page at all; the e2e browser run only got in by calling the Supabase client directly. NUXT_PUBLIC_PASSWORD_LOGIN=true now shows a password form beside the magic-link one. It is off by default and the form says it is testing only, so a build for real users never shows it unless someone sets the flag on purpose. Verified against the static build (nuxt generate, 5 routes, 524 KB): in real Chrome the SPA loads, the form signs in, the app leaves /login and the header shows the signed-in user, with no uncaught page errors. Also: the Nitro build leaves apps/web/dist as a symlink to the output, and the `dist/` ignore rule matches only directories, so it showed up as untracked. The rule is now `dist`.
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.nuxt/
|
.nuxt/
|
||||||
.output/
|
.output/
|
||||||
dist/
|
dist
|
||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ export default defineNuxtConfig({
|
|||||||
// wrong address. Keep these in step with that default.
|
// wrong address. Keep these in step with that default.
|
||||||
apiBase: process.env.NUXT_PUBLIC_API_BASE || "http://localhost:3000",
|
apiBase: process.env.NUXT_PUBLIC_API_BASE || "http://localhost:3000",
|
||||||
wsBase: process.env.NUXT_PUBLIC_WS_BASE || "ws://localhost:3000",
|
wsBase: process.env.NUXT_PUBLIC_WS_BASE || "ws://localhost:3000",
|
||||||
|
// Shows a password form on the login page. Off unless asked for: the
|
||||||
|
// real sign-in is a magic link, but that needs the Supabase project to
|
||||||
|
// send email, and the devstack's does not (`POST /auth/v1/otp` answers
|
||||||
|
// 500 "Error sending magic link email"), which left no way to sign in
|
||||||
|
// at all. A build meant for real users must not set this.
|
||||||
|
passwordLogin: process.env.NUXT_PUBLIC_PASSWORD_LOGIN === "true",
|
||||||
// There is deliberately no go2rtcStreamBase here any more. A camera
|
// There is deliberately no go2rtcStreamBase here any more. A camera
|
||||||
// stream lives on a gateway inside a particular farm's network, each
|
// stream lives on a gateway inside a particular farm's network, each
|
||||||
// farm has its own, and the gateway tells the backend its address when
|
// farm has its own, and the gateway tells the backend its address when
|
||||||
|
|||||||
@@ -3,6 +3,22 @@ const email = ref("");
|
|||||||
const sent = ref(false);
|
const sent = ref(false);
|
||||||
const error = ref<string | null>(null);
|
const error = ref<string | null>(null);
|
||||||
const client = useSupabaseClient();
|
const client = useSupabaseClient();
|
||||||
|
const passwordLogin = useRuntimeConfig().public.passwordLogin;
|
||||||
|
const password = ref("");
|
||||||
|
|
||||||
|
async function signInWithPassword() {
|
||||||
|
error.value = null;
|
||||||
|
const { error: authError } = await client.auth.signInWithPassword({
|
||||||
|
email: email.value,
|
||||||
|
password: password.value,
|
||||||
|
});
|
||||||
|
if (authError) {
|
||||||
|
error.value = authError.message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The Supabase module redirects away from /login once a session exists.
|
||||||
|
await navigateTo("/");
|
||||||
|
}
|
||||||
|
|
||||||
async function sendMagicLink() {
|
async function sendMagicLink() {
|
||||||
error.value = null;
|
error.value = null;
|
||||||
@@ -23,6 +39,12 @@ async function sendMagicLink() {
|
|||||||
<button type="submit">Send magic link</button>
|
<button type="submit">Send magic link</button>
|
||||||
</form>
|
</form>
|
||||||
<p v-else>Check your inbox for a sign-in link.</p>
|
<p v-else>Check your inbox for a sign-in link.</p>
|
||||||
|
<form v-if="passwordLogin" class="login__password" @submit.prevent="signInWithPassword">
|
||||||
|
<p class="login__hint">Password sign-in is enabled for this build (testing only).</p>
|
||||||
|
<input v-model="email" type="email" placeholder="you@farm.com" required />
|
||||||
|
<input v-model="password" type="password" placeholder="password" required autocomplete="current-password" />
|
||||||
|
<button type="submit">Sign in</button>
|
||||||
|
</form>
|
||||||
<p v-if="error" class="login__error">{{ error }}</p>
|
<p v-if="error" class="login__error">{{ error }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -36,6 +58,17 @@ async function sendMagicLink() {
|
|||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login__password {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login__hint {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
.login__error {
|
.login__error {
|
||||||
color: #f2604c;
|
color: #f2604c;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user