@@ -22,8 +22,8 @@ | |||||
<RouterLink to="/admin/dashboard" class="button is-primary"> | <RouterLink to="/admin/dashboard" class="button is-primary"> | ||||
Admin | Admin | ||||
</RouterLink> | </RouterLink> | ||||
<RouterLink to="/register" class="button is-white"> | |||||
Register | |||||
<RouterLink to="/logout" class="button is-white"> | |||||
Log out | |||||
</RouterLink> | </RouterLink> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -5,19 +5,15 @@ import { | |||||
} from 'vue-router'; | } from 'vue-router'; | ||||
import RegisterView from '@/views/RegisterView.vue'; | import RegisterView from '@/views/RegisterView.vue'; | ||||
import LoginView from '@/views/LoginView.vue'; | import LoginView from '@/views/LoginView.vue'; | ||||
import { | |||||
Privileges, | |||||
SuccessResponse, | |||||
} from '@/api/types'; | |||||
import { Privileges } from '@/api/types'; | |||||
import HomeView from '@/views/HomeView.vue'; | import HomeView from '@/views/HomeView.vue'; | ||||
import FundView from '@/views/FundView.vue'; | import FundView from '@/views/FundView.vue'; | ||||
import AddFundView from '@/views/AddFundView.vue'; | import AddFundView from '@/views/AddFundView.vue'; | ||||
import hasPermission from '@/lib/auth'; | |||||
import AdminView from '@/views/AdminView.vue'; | import AdminView from '@/views/AdminView.vue'; | ||||
import ModifyQueueView from '@/views/ModifyQueueView.vue'; | import ModifyQueueView from '@/views/ModifyQueueView.vue'; | ||||
import AdminDashboardView from '@/views/AdminDashboardView.vue'; | import AdminDashboardView from '@/views/AdminDashboardView.vue'; | ||||
import { usersExist } from '@/api/composed'; | |||||
import ModifyUserView from '@/views/ModifyUserView.vue'; | import ModifyUserView from '@/views/ModifyUserView.vue'; | ||||
import LogoutView from '@/views/LogoutView.vue'; | |||||
const routes: Array<RouteRecordRaw> = [ | const routes: Array<RouteRecordRaw> = [ | ||||
{ | { | ||||
@@ -39,17 +35,9 @@ const routes: Array<RouteRecordRaw> = [ | |||||
meta: { title: 'Login' }, | meta: { title: 'Login' }, | ||||
}, | }, | ||||
{ | { | ||||
path: '/register', | |||||
name: 'register', | |||||
component: RegisterView, | |||||
meta: { | |||||
requiredRights: Privileges.AdminPlus, | |||||
accessible: async () => { | |||||
const canProceed = await usersExist(); | |||||
return canProceed?.success; | |||||
}, | |||||
title: 'Register', | |||||
}, | |||||
path: '/logout', | |||||
name: 'logout', | |||||
component: LogoutView, | |||||
}, | }, | ||||
{ | { | ||||
path: '/admin', | path: '/admin', | ||||
@@ -126,6 +114,11 @@ const routes: Array<RouteRecordRaw> = [ | |||||
title: 'Administrator', | title: 'Administrator', | ||||
}, | }, | ||||
}, | }, | ||||
{ | |||||
path: '/:pathMatch(.*)*', | |||||
name: 'wildcard', | |||||
redirect: '/', | |||||
}, | |||||
]; | ]; | ||||
const router = createRouter({ | const router = createRouter({ | ||||
@@ -136,16 +129,7 @@ const router = createRouter({ | |||||
router.beforeEach(async (to, from, next) => { | router.beforeEach(async (to, from, next) => { | ||||
document.title = `Beignet - ${to.meta.title}`; | document.title = `Beignet - ${to.meta.title}`; | ||||
const requiredRights = to.meta.requiredRights as number | undefined; | |||||
const accessible = to.meta.accessible as (() => SuccessResponse) | undefined; | |||||
const allowed = requiredRights ? hasPermission(requiredRights) | |||||
|| (accessible && !accessible().success) : true; | |||||
if (allowed) { | |||||
next(); | |||||
} else { | |||||
next('/'); | |||||
} | |||||
return next(); | |||||
}); | }); | ||||
export default router; | export default router; |
@@ -0,0 +1,20 @@ | |||||
<template> | |||||
<div> | |||||
Logging out... | |||||
</div> | |||||
</template> | |||||
<script setup lang="ts"> | |||||
import { useRouter } from 'vue-router'; | |||||
import store from '@/store'; | |||||
store.commit('clearToken'); | |||||
window.sessionStorage.removeItem('jwt'); | |||||
const router = useRouter(); | |||||
router.push('/'); | |||||
</script> | |||||
<style scoped lang="stylus"> | |||||
</style> |
@@ -1,39 +1,47 @@ | |||||
<template> | <template> | ||||
<section class="section"> | <section class="section"> | ||||
<table> | |||||
<tr> | |||||
<th class="p-2"> | |||||
Username | |||||
</th> | |||||
<th class="p-2"> | |||||
Password | |||||
</th> | |||||
<th class="p-2"> | |||||
Privileges | |||||
</th> | |||||
</tr> | |||||
<tr v-for="user in users" :key="user.username"> | |||||
<td class="p-2">{{ user.username }}</td> | |||||
<td class="p-2"> | |||||
<template v-if="userData.username === user.username || userData.privileges < 2"> | |||||
<input type="password" | |||||
class="input is-small" :aria-label="`${user.username}'s Password`"> | |||||
</template> | |||||
<template v-else> | |||||
******** | |||||
</template> | |||||
</td> | |||||
<td class="p-2"> | |||||
<select class="select is-small" name="" id="" aria-label="User Privilege"> | |||||
<option :value="privilege" | |||||
:selected="getPrivilege(user.admin) === privilege" | |||||
v-for="(privilege, i) in Object.values(privileges)" :key="i"> | |||||
{{ privilege }} | |||||
</option> | |||||
</select> | |||||
</td> | |||||
</tr> | |||||
</table> | |||||
<template v-if="userData.privileges < 2"> | |||||
<table> | |||||
<tr> | |||||
<th class="p-2"> | |||||
Username | |||||
</th> | |||||
<th class="p-2"> | |||||
Password | |||||
</th> | |||||
<th class="p-2"> | |||||
Privileges | |||||
</th> | |||||
</tr> | |||||
<tr v-for="user in users" :key="user.username"> | |||||
<td class="p-2">{{ user.username }}</td> | |||||
<td class="p-2"> | |||||
<template v-if="userData.username === user.username || userData.privileges < 2"> | |||||
<input type="password" | |||||
class="input is-small" :aria-label="`${user.username}'s Password`"> | |||||
</template> | |||||
<template v-else> | |||||
******** | |||||
</template> | |||||
</td> | |||||
<td class="p-2"> | |||||
<div class="select is-small"> | |||||
<select name="" id="" aria-label="User Privilege"> | |||||
<option :value="privilege" | |||||
:selected="getPrivilege(user.admin) === privilege" | |||||
v-for="(privilege, i) in Object.values(privileges)" :key="i" | |||||
:disabled="userData.privileges >= 2"> | |||||
{{ privilege }} | |||||
</option> | |||||
</select> | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
</table> | |||||
</template> | |||||
<template v-else> | |||||
<p>You don't have permission to change users.</p> | |||||
</template> | |||||
</section> | </section> | ||||
</template> | </template> | ||||
@@ -49,8 +57,12 @@ import jwtDecode from 'jwt-decode'; | |||||
import store from '@/store'; | import store from '@/store'; | ||||
const users = ref<User[]>(); | const users = ref<User[]>(); | ||||
const resp = await getUsers(); | |||||
users.value = resp?.users; | |||||
try { | |||||
const resp = await getUsers(); | |||||
users.value = resp?.users; | |||||
} catch { | |||||
users.value = undefined; | |||||
} | |||||
const userData = ref<Claims>({ | const userData = ref<Claims>({ | ||||
username: '', | username: '', | ||||