Basic auth working
This commit is contained in:
@@ -98,7 +98,7 @@ module.exports = configure(function (/* ctx */) {
|
|||||||
// directives: [],
|
// directives: [],
|
||||||
|
|
||||||
// Quasar plugins
|
// Quasar plugins
|
||||||
plugins: [],
|
plugins: ['LocalStorage', 'SessionStorage'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// animations: 'all', // --- includes all animations
|
// animations: 'all', // --- includes all animations
|
||||||
|
|||||||
@@ -1,23 +1,22 @@
|
|||||||
import { boot } from 'quasar/wrappers';
|
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
|
client
|
||||||
.setEndpoint('https://cloud.appwrite.io/v1')
|
.setEndpoint('https://cloud.appwrite.io/v1')
|
||||||
.setProject('653ef6f76baf06d68034');
|
.setProject('653ef6f76baf06d68034');
|
||||||
|
|
||||||
client.subscribe('account', (response) => {
|
const account = new Account(client);
|
||||||
console.log(response);
|
|
||||||
});
|
|
||||||
|
|
||||||
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 }) => {
|
// export default boot(({ app, urlPath, redirect }) => {
|
||||||
// Redirect to login page if unauthenticated.
|
// });
|
||||||
try {
|
|
||||||
const current = await account.get();
|
export { client, account };
|
||||||
} catch (err) {
|
|
||||||
redirect('/Login');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<q-toolbar-title> OYS Borrow a Boat </q-toolbar-title>
|
<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-toolbar>
|
||||||
</q-header>
|
</q-header>
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@
|
|||||||
<q-item-label header> Essential Links </q-item-label>
|
<q-item-label header> Essential Links </q-item-label>
|
||||||
|
|
||||||
<EssentialLink
|
<EssentialLink
|
||||||
v-for="link in essentialLinks"
|
v-for="link in linksList"
|
||||||
:key="link.title"
|
:key="link.title"
|
||||||
v-bind="link"
|
v-bind="link"
|
||||||
/>
|
/>
|
||||||
@@ -33,9 +35,12 @@
|
|||||||
</q-layout>
|
</q-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import EssentialLink from 'components/EssentialLink.vue';
|
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 = [
|
const linksList = [
|
||||||
{
|
{
|
||||||
@@ -46,23 +51,22 @@ const linksList = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default defineComponent({
|
const leftDrawerOpen = ref(false);
|
||||||
name: 'MainLayout',
|
|
||||||
|
|
||||||
components: {
|
const loggedInUser = ref<Models.User<Models.Preferences> | null>();
|
||||||
EssentialLink,
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
const router = useRouter();
|
||||||
const leftDrawerOpen = ref(false);
|
|
||||||
|
|
||||||
return {
|
account.get().then((result) => {
|
||||||
essentialLinks: linksList,
|
loggedInUser.value = result;
|
||||||
leftDrawerOpen,
|
|
||||||
toggleLeftDrawer() {
|
|
||||||
leftDrawerOpen.value = !leftDrawerOpen.value;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
await account.deleteSession('current');
|
||||||
|
router.push({ name: 'login' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleLeftDrawer() {
|
||||||
|
leftDrawerOpen.value = !leftDrawerOpen.value;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -12,20 +12,13 @@
|
|||||||
<div class="text-center q-pt-sm">
|
<div class="text-center q-pt-sm">
|
||||||
<div class="col text-h6">Log in</div>
|
<div class="col text-h6">Log in</div>
|
||||||
</div>
|
</div>
|
||||||
<q-card-section>
|
<q-card-section v-if="errorMessage">
|
||||||
<div class="alert-box">
|
<div class="alert-box">
|
||||||
<strong>Error!</strong>
|
<strong>Error!</strong>
|
||||||
<br />
|
<br />
|
||||||
{{ errorMessage }}
|
{{ errorMessage }}
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<p>
|
|
||||||
{{
|
|
||||||
loggedInUser
|
|
||||||
? `Logged in as ${loggedInUser.name}`
|
|
||||||
: 'Not logged in'
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-form class="q-gutter-md">
|
<q-form class="q-gutter-md">
|
||||||
@@ -93,44 +86,29 @@ strong {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { account } from 'src/boot/appwrite';
|
import { AppwriteException } from 'appwrite';
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { account } from 'boot/appwrite';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
export default defineComponent({
|
defineOptions({
|
||||||
name: 'LoginPage',
|
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>
|
</script>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from 'vue-router';
|
} from 'vue-router';
|
||||||
|
|
||||||
import routes from './routes';
|
import routes from './routes';
|
||||||
|
import { account } from 'boot/appwrite';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If not building with SSR mode, you can
|
* If not building with SSR mode, you can
|
||||||
@@ -20,7 +21,9 @@ import routes from './routes';
|
|||||||
export default route(function (/* { store, ssrContext } */) {
|
export default route(function (/* { store, ssrContext } */) {
|
||||||
const createHistory = process.env.SERVER
|
const createHistory = process.env.SERVER
|
||||||
? createMemoryHistory
|
? createMemoryHistory
|
||||||
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory);
|
: process.env.VUE_ROUTER_MODE === 'history'
|
||||||
|
? createWebHistory
|
||||||
|
: createWebHashHistory;
|
||||||
|
|
||||||
const Router = createRouter({
|
const Router = createRouter({
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||||
@@ -32,5 +35,25 @@ export default route(function (/* { store, ssrContext } */) {
|
|||||||
history: createHistory(process.env.VUE_ROUTER_BASE),
|
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;
|
return Router;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,12 +4,24 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => import('layouts/MainLayout.vue'),
|
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'),
|
component: () => import('pages/LoginPage.vue'),
|
||||||
|
name: 'login',
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// path: '/register',
|
||||||
|
// component: () => import('pages/RegisterPage.vue'),
|
||||||
|
// name: 'register'
|
||||||
|
// },
|
||||||
// Always leave this as last one,
|
// Always leave this as last one,
|
||||||
// but you can also remove it
|
// but you can also remove it
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
32
src/stores/index.ts
Normal 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
10
src/stores/store-flag.d.ts
vendored
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user