feat: (auth) switch to OTP code via e-mail
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m24s
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m24s
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
<div class="col text-h6">Log in</div>
|
<div class="col text-h6">Log in</div>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-form>
|
<q-form @keydown.enter.prevent="doTokenLogin">
|
||||||
<q-card-section class="q-gutter-md">
|
<q-card-section class="q-gutter-md">
|
||||||
<q-input
|
<q-input
|
||||||
v-model="email"
|
v-model="email"
|
||||||
@@ -23,28 +23,21 @@
|
|||||||
color="darkblue"
|
color="darkblue"
|
||||||
filled></q-input>
|
filled></q-input>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="password"
|
v-if="userId"
|
||||||
label="Password"
|
v-model="token"
|
||||||
type="password"
|
label="6-digit code"
|
||||||
|
type="number"
|
||||||
color="darkblue"
|
color="darkblue"
|
||||||
filled></q-input>
|
filled></q-input>
|
||||||
<q-card-actions>
|
|
||||||
<q-space />
|
|
||||||
<q-btn
|
|
||||||
type="button"
|
|
||||||
@click="doLogin"
|
|
||||||
label="Login"
|
|
||||||
color="primary"></q-btn>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-form>
|
</q-form>
|
||||||
<q-card-section class="q-pa-none">
|
<q-card-section class="q-pa-none">
|
||||||
<div class="row justify-center q-ma-sm">
|
<div class="row justify-center q-ma-sm">
|
||||||
<q-btn
|
<q-btn
|
||||||
type="button"
|
type="button"
|
||||||
:to="{ name: 'signup' }"
|
@click="doTokenLogin"
|
||||||
color="primary"
|
color="primary"
|
||||||
label="SignUp with E-mail"
|
label="Login with E-mail"
|
||||||
style="width: 300px" />
|
style="width: 300px" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-center q-ma-sm">
|
<div class="row justify-center q-ma-sm">
|
||||||
@@ -84,16 +77,75 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { login } from 'boot/appwrite';
|
|
||||||
import GoogleOauthComponent from 'src/components/GoogleOauthComponent.vue';
|
import GoogleOauthComponent from 'src/components/GoogleOauthComponent.vue';
|
||||||
import DiscordOauthComponent from 'src/components/DiscordOauthComponent.vue';
|
import DiscordOauthComponent from 'src/components/DiscordOauthComponent.vue';
|
||||||
|
import { Dialog, Notify } from 'quasar';
|
||||||
|
import { useAuthStore } from 'src/stores/auth';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { AppwriteException } from 'appwrite';
|
||||||
|
|
||||||
const email = ref('');
|
const email = ref('');
|
||||||
const password = ref('');
|
const token = ref('');
|
||||||
|
const userId = ref();
|
||||||
|
|
||||||
console.log('version:' + process.env.VUE_APP_VERSION);
|
console.log('version:' + process.env.VUE_APP_VERSION);
|
||||||
|
|
||||||
const doLogin = async () => {
|
const doTokenLogin = async () => {
|
||||||
login(email.value, password.value);
|
const authStore = useAuthStore();
|
||||||
|
if (!userId.value) {
|
||||||
|
try {
|
||||||
|
const sessionToken = await authStore.createTokenSession(email.value);
|
||||||
|
userId.value = sessionToken.userId;
|
||||||
|
Dialog.create({ message: 'Check your e-mail for your login code.' });
|
||||||
|
} catch (e) {
|
||||||
|
Dialog.create({
|
||||||
|
message: 'An error occurred. Please ask for help in Discord',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const notification = Notify.create({
|
||||||
|
type: 'primary',
|
||||||
|
position: 'top',
|
||||||
|
spinner: true,
|
||||||
|
message: 'Logging you in...',
|
||||||
|
timeout: 8000,
|
||||||
|
group: false,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await authStore.tokenLogin(userId.value, token.value);
|
||||||
|
notification({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Logged in!',
|
||||||
|
timeout: 2000,
|
||||||
|
spinner: false,
|
||||||
|
icon: 'check_circle',
|
||||||
|
});
|
||||||
|
useRouter().replace({ name: 'index' });
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof AppwriteException) {
|
||||||
|
if (error.type === 'user_session_already_exists') {
|
||||||
|
useRouter().replace({ name: 'index' });
|
||||||
|
notification({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Already Logged in!',
|
||||||
|
timeout: 2000,
|
||||||
|
spinner: false,
|
||||||
|
icon: 'check_circle',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Dialog.create({
|
||||||
|
title: 'Login Error!',
|
||||||
|
message: error.message,
|
||||||
|
persistent: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
notification({
|
||||||
|
type: 'negative',
|
||||||
|
message: 'Login failed.',
|
||||||
|
timeout: 2000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ export default route(function (/* { store, ssrContext } */) {
|
|||||||
return next('/login');
|
return next('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (to.name === 'login' && currentUser) {
|
||||||
|
return next('/');
|
||||||
|
}
|
||||||
|
|
||||||
if (requiredRoles) {
|
if (requiredRoles) {
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return next('/login');
|
return next('/login');
|
||||||
|
|||||||
@@ -45,22 +45,31 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
await init();
|
await init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createTokenSession(email: string) {
|
||||||
|
return await account.createEmailToken(ID.unique(), email);
|
||||||
|
}
|
||||||
|
|
||||||
async function googleLogin() {
|
async function googleLogin() {
|
||||||
account.createOAuth2Session(
|
await account.createOAuth2Session(
|
||||||
OAuthProvider.Google,
|
OAuthProvider.Google,
|
||||||
'https://oys.undock.ca',
|
'https://oys.undock.ca',
|
||||||
'https://oys.undock.ca/login'
|
'https://oys.undock.ca/login'
|
||||||
);
|
);
|
||||||
currentUser.value = await account.get();
|
await init();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function discordLogin() {
|
async function discordLogin() {
|
||||||
account.createOAuth2Session(
|
await account.createOAuth2Session(
|
||||||
OAuthProvider.Discord,
|
OAuthProvider.Discord,
|
||||||
'https://oys.undock.ca',
|
'https://oys.undock.ca',
|
||||||
'https://oys.undock.ca/login'
|
'https://oys.undock.ca/login'
|
||||||
);
|
);
|
||||||
currentUser.value = await account.get();
|
await init();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tokenLogin(userId: string, token: string) {
|
||||||
|
await account.createSession(userId, token);
|
||||||
|
await init();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserNameById(id: string | undefined | null): string {
|
function getUserNameById(id: string | undefined | null): string {
|
||||||
@@ -102,6 +111,8 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
login,
|
login,
|
||||||
googleLogin,
|
googleLogin,
|
||||||
discordLogin,
|
discordLogin,
|
||||||
|
createTokenSession,
|
||||||
|
tokenLogin,
|
||||||
logout,
|
logout,
|
||||||
init,
|
init,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user