Basic auth working

This commit is contained in:
2023-11-06 22:55:15 -05:00
parent edde4e79fd
commit 4a43b5813d
9 changed files with 138 additions and 99 deletions

View File

@@ -98,7 +98,7 @@ module.exports = configure(function (/* ctx */) {
// directives: [],
// Quasar plugins
plugins: [],
plugins: ['LocalStorage', 'SessionStorage'],
},
// animations: 'all', // --- includes all animations

View File

@@ -1,23 +1,22 @@
import { boot } from 'quasar/wrappers';
import { Client, Account } from 'appwrite';
import { Client, Account, ID } from 'appwrite';
export const client = new Client();
const client = new Client();
client
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('653ef6f76baf06d68034');
client.subscribe('account', (response) => {
console.log(response);
});
const account = new Account(client);
export const account = new Account(client);
// // TODO: Auto-logout on session deletion / expiry
// if (user.value) {
// client.subscribe('account', (response) => {
// console.log(response);
// });
// }
export default boot(({ app, urlPath, redirect }) => {
// Redirect to login page if unauthenticated.
try {
const current = await account.get();
} catch (err) {
redirect('/Login');
}
});
// export default boot(({ app, urlPath, redirect }) => {
// });
export { client, account };

View File

@@ -12,6 +12,8 @@
/>
<q-toolbar-title> OYS Borrow a Boat </q-toolbar-title>
<div v-if="loggedInUser">Logged in as: {{ loggedInUser.name }}</div>
<q-btn flat round dense icon="logout" @click="logout" />
</q-toolbar>
</q-header>
@@ -20,7 +22,7 @@
<q-item-label header> Essential Links </q-item-label>
<EssentialLink
v-for="link in essentialLinks"
v-for="link in linksList"
:key="link.title"
v-bind="link"
/>
@@ -33,9 +35,12 @@
</q-layout>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script setup lang="ts">
import EssentialLink from 'components/EssentialLink.vue';
import { account } from 'boot/appwrite';
import type { Models } from 'appwrite';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
const linksList = [
{
@@ -46,23 +51,22 @@ const linksList = [
},
];
export default defineComponent({
name: 'MainLayout',
const leftDrawerOpen = ref(false);
components: {
EssentialLink,
},
const loggedInUser = ref<Models.User<Models.Preferences> | null>();
setup() {
const leftDrawerOpen = ref(false);
const router = useRouter();
return {
essentialLinks: linksList,
leftDrawerOpen,
toggleLeftDrawer() {
leftDrawerOpen.value = !leftDrawerOpen.value;
},
};
},
account.get().then((result) => {
loggedInUser.value = result;
});
async function logout() {
await account.deleteSession('current');
router.push({ name: 'login' });
}
function toggleLeftDrawer() {
leftDrawerOpen.value = !leftDrawerOpen.value;
}
</script>

View File

@@ -12,20 +12,13 @@
<div class="text-center q-pt-sm">
<div class="col text-h6">Log in</div>
</div>
<q-card-section>
<q-card-section v-if="errorMessage">
<div class="alert-box">
<strong>Error!</strong>
<br />
{{ errorMessage }}
</div>
</q-card-section>
<p>
{{
loggedInUser
? `Logged in as ${loggedInUser.name}`
: 'Not logged in'
}}
</p>
</q-card-section>
<q-card-section>
<q-form class="q-gutter-md">
@@ -93,44 +86,29 @@ strong {
}
</style>
<script lang="ts">
import { account } from 'src/boot/appwrite';
import { defineComponent } from 'vue';
<script setup lang="ts">
import { AppwriteException } from 'appwrite';
import { ref } from 'vue';
import { account } from 'boot/appwrite';
import { useRouter } from 'vue-router';
export default defineComponent({
defineOptions({
name: 'LoginPage',
setup() {
const loggedInUser = ref(null);
const email = ref('');
const password = ref('');
const current = this.$appwrite_account.get();
current.then(
function (response) {
console.log(response);
},
function (error) {
console.log(error);
}
);
const login = async (email, password) => {
await this.$appwrite_account.createEmailSession(email, password);
loggedInUser.value = await this.$appwrite_account.get();
if (loggedInUser.value.error) {
}
// TODO: Add error handling for failed login.
// TODO: Add forwarding for successful login.
};
return {
email,
password,
login,
};
},
});
const email = ref('');
const password = ref('');
const errorMessage = ref('');
const router = useRouter();
function login(email: string, password: string) {
account
.createEmailSession(email, password)
.then(() => {
router.push({ name: 'index' });
})
.catch((reason: AppwriteException) => {
errorMessage.value = reason.message;
});
}
</script>

View File

@@ -7,6 +7,7 @@ import {
} from 'vue-router';
import routes from './routes';
import { account } from 'boot/appwrite';
/*
* If not building with SSR mode, you can
@@ -20,7 +21,9 @@ import routes from './routes';
export default route(function (/* { store, ssrContext } */) {
const createHistory = process.env.SERVER
? createMemoryHistory
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory);
: process.env.VUE_ROUTER_MODE === 'history'
? createWebHistory
: createWebHashHistory;
const Router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }),
@@ -32,5 +35,25 @@ export default route(function (/* { store, ssrContext } */) {
history: createHistory(process.env.VUE_ROUTER_BASE),
});
const accountRoutes = ['login', 'register'];
Router.beforeEach(async (to, from, next) => {
const name = to.name as string;
try {
const session = await account.getSession('current');
to.meta.session = session;
if (accountRoutes.includes(name)) {
return next({ name: 'index' });
}
} catch {
if (!accountRoutes.includes(name)) {
return next({ name: 'login' });
}
}
next();
});
return Router;
});

View File

@@ -4,12 +4,24 @@ const routes: RouteRecordRaw[] = [
{
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/IndexPage.vue') }],
name: 'index',
children: [
{
path: '',
component: () => import('pages/IndexPage.vue'),
},
],
},
{
path: '/Login',
path: '/login',
component: () => import('pages/LoginPage.vue'),
name: 'login',
},
// {
// path: '/register',
// component: () => import('pages/RegisterPage.vue'),
// name: 'register'
// },
// Always leave this as last one,
// but you can also remove it
{

View File

@@ -1,19 +0,0 @@
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0
}),
getters: {
doubleCount (state) {
return state.counter * 2;
}
},
actions: {
increment () {
this.counter++;
}
}
});

32
src/stores/index.ts Normal file
View File

@@ -0,0 +1,32 @@
import { store } from 'quasar/wrappers';
import { createPinia } from 'pinia';
import { Router } from 'vue-router';
/*
* When adding new properties to stores, you should also
* extend the `PiniaCustomProperties` interface.
* @see https://pinia.vuejs.org/core-concepts/plugins.html#typing-new-store-properties
*/
declare module 'pinia' {
export interface PiniaCustomProperties {
readonly router: Router;
}
}
/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/
export default store((/* { ssrContext } */) => {
const pinia = createPinia();
// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)
return pinia;
});

10
src/stores/store-flag.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/* eslint-disable */
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
import "quasar/dist/types/feature-flag";
declare module "quasar/dist/types/feature-flag" {
interface QuasarFeatureFlags {
store: true;
}
}