@@ -22,8 +22,8 @@ | |||
<RouterLink to="/admin/dashboard" class="button is-primary"> | |||
Admin | |||
</RouterLink> | |||
<RouterLink to="/register" class="button is-white"> | |||
Register | |||
<RouterLink to="/logout" class="button is-white"> | |||
Log out | |||
</RouterLink> | |||
</div> | |||
</div> | |||
@@ -5,19 +5,15 @@ import { | |||
} from 'vue-router'; | |||
import RegisterView from '@/views/RegisterView.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 FundView from '@/views/FundView.vue'; | |||
import AddFundView from '@/views/AddFundView.vue'; | |||
import hasPermission from '@/lib/auth'; | |||
import AdminView from '@/views/AdminView.vue'; | |||
import ModifyQueueView from '@/views/ModifyQueueView.vue'; | |||
import AdminDashboardView from '@/views/AdminDashboardView.vue'; | |||
import { usersExist } from '@/api/composed'; | |||
import ModifyUserView from '@/views/ModifyUserView.vue'; | |||
import LogoutView from '@/views/LogoutView.vue'; | |||
const routes: Array<RouteRecordRaw> = [ | |||
{ | |||
@@ -39,17 +35,9 @@ const routes: Array<RouteRecordRaw> = [ | |||
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', | |||
@@ -126,6 +114,11 @@ const routes: Array<RouteRecordRaw> = [ | |||
title: 'Administrator', | |||
}, | |||
}, | |||
{ | |||
path: '/:pathMatch(.*)*', | |||
name: 'wildcard', | |||
redirect: '/', | |||
}, | |||
]; | |||
const router = createRouter({ | |||
@@ -136,16 +129,7 @@ const router = createRouter({ | |||
router.beforeEach(async (to, from, next) => { | |||
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; |
@@ -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> | |||
<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> | |||
</template> | |||
@@ -49,8 +57,12 @@ import jwtDecode from 'jwt-decode'; | |||
import store from '@/store'; | |||
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>({ | |||
username: '', | |||