Removes the now-removed XL Vask Selvvask AI autopilot and MiniMax UI from the Superuser → Fakturaer → Periode → Selvvask surface. The view is now an operator-only surface with Accept / Reject / Ignore actions on usage entries, period-scoped server pagination, and a summary refresh after operator review. Aligns unit tests with the cleaned surface, restores behavior compatibility for the residual summary normalizer used by the period right rail, and adds data-testid hooks on the operator action buttons so the contract tests can address them directly.
223 lines
7.0 KiB
Vue
223 lines
7.0 KiB
Vue
<script>
|
|
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
|
import { parseError } from "@/components/request/HandleGlobalError.vue";
|
|
import { clearEdgeGatewayWorkspaceCache } from "@/services/edgeGateways.js";
|
|
import {
|
|
DatabaseSystemObject,
|
|
RedisSystemObject,
|
|
MinioSystemObject,
|
|
} from "@/components/session/token/superUser/systemDatabase.vue";
|
|
import { Cron } from "@/components/session/token/superUser/cron.vue";
|
|
import { Economic } from "@/components/session/token/superUser/modules/Economic/Economic.vue";
|
|
import { reCAPTCHA } from "@/components/session/token/superUser/modules/reCAPTCHA/reCAPTCHA.vue";
|
|
import { Email } from "@/components/session/token/superUser/modules/Email/Email.vue";
|
|
import { Backups } from "@/components/session/token/superUser/modules/Backups/Backups.vue";
|
|
import { MotorAPI } from "@/components/session/token/superUser/modules/motorapi/MotorAPI.vue";
|
|
import { Stripe } from "@/components/session/token/superUser/modules/stripe/Stripe.vue";
|
|
import { FXRatesAPI } from "@/components/session/token/superUser/modules/fxratesapi/FXRatesAPI.vue";
|
|
import { WeatherAPI } from "@/components/session/token/superUser/modules/weatherapi/WeatherAPI.vue";
|
|
import { Workfeed } from "@/components/session/token/superUser/modules/workfeed/Workfeed.vue";
|
|
import { GatewayAPI } from "@/components/session/token/superUser/modules/gatewayapi/GatewayAPI.vue";
|
|
import { XLVask } from "@/components/session/token/superUser/modules/xlvask/XLVask.vue";
|
|
import { Entra } from "@/components/session/token/superUser/modules/entra/Entra.vue";
|
|
import { Limble } from "@/components/session/token/superUser/modules/limble/Limble.vue";
|
|
import { OcrSpace } from "@/components/session/token/superUser/modules/ocrSpace/OcrSpace.vue";
|
|
import { OpenAI } from "@/components/session/token/superUser/modules/openAI/OpenAI.vue";
|
|
import { LicensePlateRecognizer } from "@/components/session/token/superUser/modules/licensePlateRecognizer/LicensePlateRecognizer.vue";
|
|
import { VirkData } from "@/components/session/token/superUser/modules/virkdata/VirkData.vue";
|
|
import { Shelly } from "@/components/session/token/superUser/modules/shelly/Shelly.vue";
|
|
import { SelfServe } from "@/components/session/token/superUser/modules/selfserve/SelfServe.vue";
|
|
import { Bird } from "@/components/session/token/superUser/modules/bird/Bird.vue";
|
|
import { EdgeGateway } from "@/components/session/token/superUser/modules/edgegateway/EdgeGateway.vue";
|
|
import { Failover } from "@/components/session/token/superUser/modules/failover/Failover.vue";
|
|
import { Coolify } from "@/components/session/token/superUser/modules/coolify/Coolify.vue";
|
|
import { ReleaseManager } from "@/components/session/token/superUser/modules/releasemanager/ReleaseManager.vue";
|
|
import { Slack } from "@/components/session/token/superUser/modules/slack/Slack.vue";
|
|
|
|
let qrCodeModulePromise;
|
|
|
|
const loadQRCodeModule = async () => {
|
|
if (!qrCodeModulePromise) {
|
|
qrCodeModulePromise = import("qrcode");
|
|
}
|
|
|
|
return qrCodeModulePromise;
|
|
};
|
|
|
|
/**
|
|
* The superuser object
|
|
*/
|
|
export const SuperUserObject = {
|
|
system: {
|
|
get database() {
|
|
return DatabaseSystemObject;
|
|
},
|
|
get redis() {
|
|
return RedisSystemObject;
|
|
},
|
|
get minio() {
|
|
return MinioSystemObject;
|
|
},
|
|
},
|
|
modules: {
|
|
get economic() {
|
|
return Economic;
|
|
},
|
|
get reCAPTCHA() {
|
|
return reCAPTCHA;
|
|
},
|
|
get email() {
|
|
return Email;
|
|
},
|
|
get backups() {
|
|
return Backups;
|
|
},
|
|
get motorapi() {
|
|
return MotorAPI;
|
|
},
|
|
get stripe() {
|
|
return Stripe;
|
|
},
|
|
get fxratesapi() {
|
|
return FXRatesAPI;
|
|
},
|
|
get weatherapi() {
|
|
return WeatherAPI;
|
|
},
|
|
get workfeed() {
|
|
return Workfeed;
|
|
},
|
|
get gatewayapi() {
|
|
return GatewayAPI;
|
|
},
|
|
get xlvask() {
|
|
return XLVask;
|
|
},
|
|
get entra() {
|
|
return Entra;
|
|
},
|
|
get limble() {
|
|
return Limble;
|
|
},
|
|
get ocrspace() {
|
|
return OcrSpace;
|
|
},
|
|
get openai() {
|
|
return OpenAI;
|
|
},
|
|
get licenseplaterecognizer() {
|
|
return LicensePlateRecognizer;
|
|
},
|
|
get virkdata() {
|
|
return VirkData;
|
|
},
|
|
get shelly() {
|
|
return Shelly;
|
|
},
|
|
get selfserve() {
|
|
return SelfServe;
|
|
},
|
|
get bird() {
|
|
return Bird;
|
|
},
|
|
get edgegateway() {
|
|
return EdgeGateway;
|
|
},
|
|
get failover() {
|
|
return Failover;
|
|
},
|
|
get coolify() {
|
|
return Coolify;
|
|
},
|
|
get releasemanager() {
|
|
return ReleaseManager;
|
|
},
|
|
get slack() {
|
|
return Slack;
|
|
},
|
|
},
|
|
/** Intimidate a user */
|
|
intimidate: {
|
|
/**
|
|
* Get an impersonation (session) token for a user
|
|
* @param userId
|
|
* @returns {Promise<string>} The impersonation token
|
|
*/
|
|
getImpersonationToken: async (userId) => {
|
|
return await authenticatedRequest("/su/intimidate", "POST", { user_id: userId })
|
|
.then((response) => {
|
|
// Return the token
|
|
return response.data.data.token;
|
|
})
|
|
.catch((error) => {
|
|
parseError(error, "auth");
|
|
});
|
|
},
|
|
/**
|
|
* Intimidate a user
|
|
* @param userId
|
|
* @returns {Promise<void>}
|
|
*/
|
|
intimidateUser: async (userId) => {
|
|
return await authenticatedRequest("/su/intimidate", "POST", { user_id: userId })
|
|
.then((response) => {
|
|
// Save the current token, so we can restore it after the user has been intimidated
|
|
const currentToken = localStorage.getItem("token");
|
|
localStorage.setItem("superuser_token", currentToken);
|
|
// Set the token in the local storage
|
|
clearEdgeGatewayWorkspaceCache();
|
|
localStorage.setItem("token", response.data.data.token);
|
|
// Redirect the user to the dashboard
|
|
window.location = "/";
|
|
})
|
|
.catch((error) => {
|
|
parseError(error, "auth");
|
|
});
|
|
},
|
|
/**
|
|
* Can the current superuser intimidate another superuser?
|
|
* @returns {boolean}
|
|
*/
|
|
canImpersonateAdmin: () => {
|
|
// TODO: Implement this function
|
|
return true;
|
|
},
|
|
/**
|
|
* Show a QR code for logging in as a user
|
|
* @param link
|
|
* @returns {Promise<string>} The QR code URL
|
|
*/
|
|
showImpersonationQRCode: async (link) => {
|
|
const { toDataURL } = await loadQRCodeModule();
|
|
return {
|
|
value: await toDataURL(link),
|
|
};
|
|
},
|
|
/**
|
|
* Go back from intimidating a user
|
|
*/
|
|
goBack: () => {
|
|
// Get the superuser token
|
|
const superuserToken = localStorage.getItem("superuser_token");
|
|
// Set the token in the local storage
|
|
clearEdgeGatewayWorkspaceCache();
|
|
localStorage.setItem("token", superuserToken);
|
|
// Clear the superuser token
|
|
localStorage.removeItem("superuser_token");
|
|
// Redirect the user to the dashboard
|
|
window.location = "/";
|
|
},
|
|
/**
|
|
* Check if the superuser is currently intimidating a user
|
|
* @returns {boolean}
|
|
*/
|
|
isIntimidated: () => {
|
|
return localStorage.getItem("superuser_token") !== null;
|
|
},
|
|
},
|
|
get cron() {
|
|
return Cron;
|
|
},
|
|
};
|
|
</script>
|