"Add ReturnToOwnAccount.vue for managing superuser token redirection, enhance permissions handling with virtual permissions support, and update NavigationMenuItemsGlobal.vue with new link for account return"

This commit is contained in:
Jeppe Bundgaard
2025-11-05 10:18:48 +01:00
parent d6c5c03e85
commit 719cb85012
5 changed files with 106 additions and 14 deletions
@@ -19,11 +19,11 @@ const addChildrenIfApplicable = (item: NavigationItemProps) => {
if (item.type === 'link' && item.permissions) {
// Check if the user has at least one of the required permissions
for (const perm of item.permissions) {
if (hasPermission(perm)) {
return [item];
if (!hasPermission(perm)) {
return [];
}
}
return []; // User lacks required permissions
return [item]; // User lacks required permissions
}
}
@@ -50,6 +50,12 @@ const items = computed<NavigationItemProps[]>(() => [
type: 'link',
permissions: ['superuser'],
}) || [],
...addChildrenIfApplicable({
label: 'Return to own account →',
to: `/auth/return`,
type: 'link',
permissions: ['user', 'has_superuser_token'],
}) || [],
...addChildrenIfApplicable({
label: 'Sign out →',
to: `/logout`,
+25 -1
View File
@@ -1,6 +1,6 @@
<script>
import {authenticatedRequest} from "@/components/session/authenticatedRequest.vue";
import {ref} from "vue";
import {computed, ref, watch} from "vue";
import {parseError} from "@/components/request/HandleGlobalError.vue";
import {SuperUserObject} from "@/components/session/token/superUserObject.vue";
import {AdminUserObject} from "@/components/session/token/AdminUserObject.vue";
@@ -183,8 +183,32 @@ export const SessionUser = {
},
/** The user's permissions */
permissions: ref([]),
availableVirtualPermissions: [
'has_superuser_token',
],
virtualPermissions: computed(() => {
/** These permissions are NOT set by default for superusers, this should ONLY be used for superusers */
let virtualPermissions = [];
// Super user token
// Check if the user has a superuser token in the local storage
if (localStorage.getItem("superuser_token") !== null) {
// Validate the superuser token
if (localStorage.getItem("superuser_token") !== SessionUser.token.value) {
virtualPermissions.push('has_superuser_token');
}
}
return virtualPermissions;
}),
permissions_computed: computed(() => {
return [...SessionUser.permissions.value];
}),
hasPermission: (permission) => {
//console.log('Checking permission: ' + permission + ' - ' + hasPermission);
// Check if the permission is virtual
if (SessionUser.availableVirtualPermissions.values().toArray().includes(permission)) {
console.warn('Virtual permission detected: ' + permission);
return SessionUser.virtualPermissions.value.values().toArray().includes(permission);
}
return (SessionUser.permissions.value.includes(permission) || SessionUser.permissions.value.includes('superuser'));
},
/** Can access shortcuts */
@@ -34,14 +34,24 @@ export const Vehicles = {
creation: {
required: true,
},
options: async (only_that_allows_subscription = true, options = {isWash: null, addDefaultOption: true, restrictToCategory4: null, includeProductRaw: false}) => {
options: async (only_that_allows_subscription = true, options = {isWash: true, addDefaultOption: true, restrictToCategory4: null, includeProductRaw: false}) => {
// Get all the products, that has 'subscription_allowed' set to true
let products = await SessionUser.objects.products.get.all();
// If the options are set, filter the products based on the product flags
if (options.isWash !== null) {
products = products.filter((product) => product.is_wash === options.isWash);
let opt = {
isWash: null,
addDefaultOption: true,
restrictToCategory4: null,
includeProductRaw: false,
allowsSubscription: true,
...(options ? options : {}),
...(only_that_allows_subscription ? {allowsSubscription: true} : {}),
}
if (options.addDefaultOption !== false) {
console.warn("Getting products with options", opt);
// If the options are set, filter the products based on the product flags
if (opt.isWash !== null) {
products = products.filter((product) => product.is_wash === opt.isWash);
}
if (opt.addDefaultOption !== false) {
// Add a default option (0, unknown)
products.unshift({
id: 0,
@@ -49,16 +59,16 @@ export const Vehicles = {
});
}
// Filter the products based on the subscription_allowed flag and category
if (only_that_allows_subscription) {
products = products.filter((product) => product.subscription_allowed === true || product.id === 0);
if (opt.allowsSubscription !== null) {
products = products.filter((product) => product.subscription_allowed === opt.allowsSubscription);
}
if (options.restrictToCategory4 === null || options.restrictToCategory4 === true) {
if (opt.restrictToCategory4 === true) {
products = products.filter((product) => product.category === 4 || product.id === 0); // Only allow category 4 (car) and defaultValue
}
// Map the products to the options
// Map the products to the opt
return products.map((product) => {
return {
...options.includeProductRaw ? { product: product } : {},
...opt.includeProductRaw ? { product: product } : {},
id: parseInt(product.id),
name: product.name,
addons: product.addons,
+6
View File
@@ -123,6 +123,7 @@ import ConfigurationLicensePlateRecognizer from "@/views/dashboards/superUserDas
import ConfigurationVirkData from "@/views/dashboards/superUserDashboard/configuration/ConfigurationVirkData.vue";
import ConfigurationShelly from "@/views/dashboards/superUserDashboard/configuration/ConfigurationShelly.vue";
import MyBookingsBook from "@/views/dashboards/userDashboard/bookings/MyBookingsBook.vue";
import ReturnToOwnAccount from "@/views/auth/ReturnToOwnAccount.vue";
/**
* Meta data for routes
@@ -242,6 +243,11 @@ export const router = createRouter({
component: Register,
meta: { middleware: guestMiddleware }
},
{
name: 'returntoownaccount',
path: '/auth/return',
component: ReturnToOwnAccount,
},
{
name: 'adminlogin',
path: '/admin/login',
+46
View File
@@ -0,0 +1,46 @@
<script setup lang="ts">
import { onMounted, onUnmounted, ref, computed } from "vue";
import PageLoader from "@/components/global/PageLoader.vue";
const isProcessing = ref(false);
const hasToken = computed(() => localStorage.getItem("superuser_token") !== null);
const applyToken = (token: string) => {
isProcessing.value = true; // Start processing
localStorage.setItem("token", token);
localStorage.removeItem("superuser_token");
window.location.href = "/";
}
const applyTokenIfPresent = () => {
// Get the current URL
const token = localStorage.getItem("superuser_token");
if (token) {
// If a token is present, store it in localStorage
console.warn("Token found in localstorage:", token);
applyToken(token); // Apply the token (store and redirect)
} else {
console.warn("No token found in localstorage");
// Redirct to the default page
window.location.href = "/";
}
}
/** Mounting and Unmounting Logic **/
onMounted(() => {
applyTokenIfPresent();
});
onUnmounted(() => {
});
</script>
<template>
<div>
<PageLoader v-show="isProcessing" />
</div>
</template>
<style scoped>
</style>