Basic auth working
This commit is contained in:
@@ -98,7 +98,7 @@ module.exports = configure(function (/* ctx */) {
|
||||
// directives: [],
|
||||
|
||||
// Quasar plugins
|
||||
plugins: [],
|
||||
plugins: ['LocalStorage', 'SessionStorage'],
|
||||
},
|
||||
|
||||
// animations: 'all', // --- includes all animations
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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