aboutsummaryrefslogtreecommitdiff
path: root/front-end/src/views/Login
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-01-30 15:23:06 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2024-01-30 15:23:06 -0500
commit5abc489b9954111d66d1385aa62a3ea962fa0a55 (patch)
treeb1715e5c5e6316f33e3e33fb55397d93200ab518 /front-end/src/views/Login
parente4dc63ded324c6e9678603296953bb1f7dea7569 (diff)
merge upstream. Add dynamic client-side support for optional oauth2 and social login methods
Diffstat (limited to 'front-end/src/views/Login')
-rw-r--r--front-end/src/views/Login/components/Social.vue36
-rw-r--r--front-end/src/views/Login/components/UserPass.vue7
-rw-r--r--front-end/src/views/Login/index.vue75
-rw-r--r--front-end/src/views/Login/pki/index.vue70
-rw-r--r--front-end/src/views/Login/social/[type].vue90
5 files changed, 140 insertions, 138 deletions
diff --git a/front-end/src/views/Login/components/Social.vue b/front-end/src/views/Login/components/Social.vue
index 4d22074..7e92d99 100644
--- a/front-end/src/views/Login/components/Social.vue
+++ b/front-end/src/views/Login/components/Social.vue
@@ -1,19 +1,3 @@
-<template>
- <div class="flex flex-col gap-3">
- <div v-for="method in methods" :key="method.Id" class="">
- <button
- type="submit"
- class="btn social-button"
- :disabled="waiting"
- @click.prevent="submitLogin(method)"
- >
- <fa-icon :icon="getIcon(method)" size="xl" />
- Login with {{ capitalize(method.Id) }}
- </button>
- </div>
- </div>
-</template>
-
<script setup lang="ts">
import { shallowRef } from 'vue'
import { apiCall, useWait, type OAuthMethod } from '@vnuge/vnlib.browser'
@@ -43,4 +27,22 @@ const getIcon = (method: OAuthMethod): string[] => {
//Load methods once the fetch completes
store.socialOauth().then(m => methods.value = m.methods);
-</script> \ No newline at end of file
+</script>
+
+<template>
+
+ <div class="flex flex-col gap-3">
+ <div v-for="method in methods" :key="method.Id" class="">
+ <button
+ type="submit"
+ class="btn social-button"
+ :disabled="waiting"
+ @click.prevent="submitLogin(method)"
+ >
+ <fa-icon :icon="getIcon(method)" size="xl" />
+ Login with {{ capitalize(method.Id) }}
+ </button>
+ </div>
+ </div>
+
+</template>
diff --git a/front-end/src/views/Login/components/UserPass.vue b/front-end/src/views/Login/components/UserPass.vue
index 442abb1..bc9d8d1 100644
--- a/front-end/src/views/Login/components/UserPass.vue
+++ b/front-end/src/views/Login/components/UserPass.vue
@@ -55,14 +55,15 @@
</template>
<script setup lang="ts">
-import { ref, shallowRef, reactive, defineAsyncComponent, type Ref } from 'vue'
+import { ref, shallowRef, reactive, defineAsyncComponent, Ref } from 'vue'
import { useTimeoutFn, set } from '@vueuse/core'
import { useVuelidate } from '@vuelidate/core'
import { isEqual } from 'lodash-es'
import { required, maxLength, minLength, email, helpers } from '@vuelidate/validators'
import {
useVuelidateWrapper, useMfaLogin, totpMfaProcessor, IMfaFlowContinuiation, MfaMethod,
- apiCall, useMessage, useWait, debugLog, WebMessage
+ apiCall, useMessage, useWait, debugLog, WebMessage,
+ type VuelidateInstance
} from '@vnuge/vnlib.browser'
const Totp = defineAsyncComponent(() => import('./Totp.vue'))
@@ -97,7 +98,7 @@ const rules = {
}
const v$ = useVuelidate(rules, vState)
-const { validate } = useVuelidateWrapper(v$);
+const { validate } = useVuelidateWrapper(v$ as Ref<VuelidateInstance>);
const SubmitLogin = async () => {
diff --git a/front-end/src/views/Login/index.vue b/front-end/src/views/Login/index.vue
index 6a55aeb..476ebf4 100644
--- a/front-end/src/views/Login/index.vue
+++ b/front-end/src/views/Login/index.vue
@@ -1,3 +1,38 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import { apiCall, useWait } from '@vnuge/vnlib.browser'
+import { isNil } from 'lodash-es'
+import { useStore } from '../../store'
+import { storeToRefs } from 'pinia'
+import UserPass from './components/UserPass.vue'
+import Social from './components/Social.vue'
+
+const store = useStore();
+const { loggedIn } = storeToRefs(store)
+const pkiEnabled = computed(() => !isNil(store.pki?.pkiAuth))
+
+store.setPageTitle('Login')
+
+const { waiting } = useWait()
+
+const submitLogout = async () => {
+ //Submit logout request
+ await apiCall(async ({ toaster }) => {
+ const { logout } = await store.socialOauth()
+ // Attempt to logout
+ await logout()
+ // Push a new toast message
+ toaster.general.success({
+ id: 'logout-success',
+ title: 'Success',
+ text: 'You have been logged out',
+ duration: 5000
+ })
+ })
+}
+
+</script>
+
<template>
<div id="login-template" class="app-component-entry">
<div class="login-container">
@@ -25,7 +60,7 @@
<Social />
<!-- pki button, forward to the pki route -->
- <div v-if="pkiEnabled" class="mt-3">
+ <div v-if="pkiEnabled" class="mt-4">
<router-link to="/login/pki">
<button type="submit" class="btn red social-button" :disabled="waiting">
<fa-icon :icon="['fa','certificate']" size="xl" />
@@ -39,44 +74,6 @@
</div>
</template>
-<script setup lang="ts">
-import { } from 'vue'
-import { apiCall, useWait } from '@vnuge/vnlib.browser'
-import { isNil } from 'lodash-es'
-import { useStore } from '../../store'
-import { storeToRefs } from 'pinia'
-import UserPass from './components/UserPass.vue'
-import Social from './components/Social.vue'
-
-//pki enabled flag from env
-const pkiEnabled = !isNil(import.meta.env.VITE_PKI_ENABLED);
-
-const store = useStore();
-const { loggedIn } = storeToRefs(store)
-
-store.setPageTitle('Login')
-
-const { waiting } = useWait()
-
-const submitLogout = async () => {
- //Submit logout request
- await apiCall(async ({ toaster }) => {
- // Attempt to logout
- const { logout } = await store.socialOauth()
- await logout()
-
- // Push a new toast message
- toaster.general.success({
- id: 'logout-success',
- title: 'Success',
- text: 'You have been logged out',
- duration: 5000
- })
- })
-}
-
-</script>
-
<style lang="scss">
#login-template {
.login-container{
diff --git a/front-end/src/views/Login/pki/index.vue b/front-end/src/views/Login/pki/index.vue
index 585942a..8edd063 100644
--- a/front-end/src/views/Login/pki/index.vue
+++ b/front-end/src/views/Login/pki/index.vue
@@ -1,3 +1,38 @@
+<script setup lang="ts">
+import { isEmpty } from 'lodash-es';
+import { apiCall, debugLog, useMessage } from '@vnuge/vnlib.browser';
+import { ref } from 'vue'
+import { decodeJwt } from 'jose'
+import { useRouter } from 'vue-router';
+import { useStore } from '../../../store';
+
+const { setMessage } = useMessage()
+const { push } = useRouter()
+const store = useStore()
+
+const otp = ref('')
+
+const submit = () => {
+
+ apiCall(async () => {
+ if (isEmpty(otp.value)) {
+ setMessage('Please enter your OTP')
+ return
+ }
+
+ //try to decode the jwt to confirm its form is valid
+ const jwt = decodeJwt(otp.value)
+ debugLog(jwt)
+
+ await store.pki!.pkiAuth.login(otp.value)
+
+ //Go back to login page
+ push({ name: 'Login' })
+ })
+}
+
+</script>
+
<template>
<div id="pki-login-template" class="app-component-entry">
<div class="container max-w-lg mx-auto mt-6 lg:mt-20">
@@ -30,38 +65,3 @@
</div>
</div>
</template>
-
-<script setup lang="ts">
-import { isEmpty } from 'lodash-es';
-import { apiCall, debugLog, useMessage } from '@vnuge/vnlib.browser';
-import { ref } from 'vue'
-import { decodeJwt } from 'jose'
-import { useRouter } from 'vue-router';
-import { useStore } from '../../../store';
-
-const { setMessage } = useMessage()
-const { push } = useRouter()
-const store = useStore()
-
-const otp = ref('')
-
-const submit = () =>{
-
- apiCall(async () =>{
- if(isEmpty(otp.value)){
- setMessage('Please enter your OTP')
- return
- }
-
- //try to decode the jwt to confirm its form is valid
- const jwt = decodeJwt(otp.value)
- debugLog(jwt)
-
- await store.pkiAuth.login(otp.value)
-
- //Go back to login page
- push({ name: 'Login' })
- })
-}
-
-</script> \ No newline at end of file
diff --git a/front-end/src/views/Login/social/[type].vue b/front-end/src/views/Login/social/[type].vue
index 51da94f..f011f9c 100644
--- a/front-end/src/views/Login/social/[type].vue
+++ b/front-end/src/views/Login/social/[type].vue
@@ -1,35 +1,3 @@
-<template>
- <div id="social-login-template" class="app-component-entry">
- <div class="container flex flex-col m-auto my-16">
- <div id="social-final-template" class="flex justify-center">
- <div class="entry-container">
- <h3>Finalizing login</h3>
- <div class="mt-6 mb-4">
- <div v-if="message?.length > 0" class="text-lg text-red-500 dark:text-rose-500">
- <p>{{ message }}</p>
- <div class="flex justify-center mt-5">
- <router-link to="/login">
- <button type="submit" class="btn primary" :disabled="waiting">
- <fa-icon icon="sign-in-alt" />
- Try again
- </button>
- </router-link>
- </div>
- </div>
- <div v-else>
- <div class="flex justify-center">
- <div class="m-auto">
- <fa-icon class="animate-spin" icon="spinner" size="2x"/>
- </div>
- </div>
- <p>Please wait while we log you in.</p>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
-</template>
<script setup lang="ts">
import { defer } from 'lodash-es'
@@ -62,19 +30,20 @@ tryOnMounted(() => defer(() => {
//try to complete an oauth login
apiCall(async ({ toaster }) => {
- try{
- //Complete the login
- const { completeLogin } = await store.socialOauth();
- await completeLogin()
-
- toaster.general.success({
- title:'Login Successful',
- text: 'You have successfully logged in.'
- })
-
- router.push({ name: 'Login' })
+ try {
+ const { completeLogin } = await store.socialOauth();
+
+ //Complete the login
+ await completeLogin();
+
+ toaster.general.success({
+ title: 'Login Successful',
+ text: 'You have successfully logged in.'
+ })
+
+ router.push({ name: 'Login' })
}
- catch(err: any){
+ catch (err: any) {
set(message, err.message)
}
})
@@ -82,6 +51,39 @@ tryOnMounted(() => defer(() => {
</script>
+<template>
+ <div id="social-login-template" class="app-component-entry">
+ <div class="container flex flex-col m-auto my-16">
+ <div id="social-final-template" class="flex justify-center">
+ <div class="entry-container">
+ <h3>Finalizing login</h3>
+ <div class="mt-6 mb-4">
+ <div v-if="message?.length > 0" class="text-lg text-red-500 dark:text-rose-500">
+ <p>{{ message }}</p>
+ <div class="flex justify-center mt-5">
+ <router-link to="/login">
+ <button type="submit" class="btn primary" :disabled="waiting">
+ <fa-icon icon="sign-in-alt" />
+ Try again
+ </button>
+ </router-link>
+ </div>
+ </div>
+ <div v-else>
+ <div class="flex justify-center">
+ <div class="m-auto">
+ <fa-icon class="animate-spin" icon="spinner" size="2x"/>
+ </div>
+ </div>
+ <p>Please wait while we log you in.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
<style lang="scss">
#social-login-template{