Merge pull request #90 from copenhagentruckwash/propose-fix-for-product-catalog-vulnerability

Restrict vehicle type product edits to superusers
This commit is contained in:
Jeppe B
2026-06-01 23:35:14 +02:00
committed by GitHub
2 changed files with 22 additions and 1 deletions
@@ -483,6 +483,9 @@ const graphStats = computed(() => {
});
const permissions = computed(() => graphPayload.value?.permissions || {});
const canEditVehicleTypeProduct = computed(() =>
Boolean(permissions.value.can_edit) && SessionUser.canAccessSuperUser()
);
const destructiveGatewayActions = new Set(["rotate_credentials", "uninstall"]);
const canManageGateways = computed(() => Boolean(permissions.value.can_manage_gateways));
const canRunGatewayDestructiveActions = computed(() =>
@@ -4687,6 +4690,11 @@ const deleteSelected = async () => {
};
const saveVehicleTypeProduct = async () => {
if (!canEditVehicleTypeProduct.value) {
toast.error("Only superusers can update vehicle type product catalog fields.");
return;
}
const id = parseNullableInt(
inspectorForm.value.id || selectedRaw.value.product || selectedRaw.value.product_id || selectedRaw.value.id
);
@@ -8054,7 +8062,7 @@ onBeforeUnmount(() => {
/>
<span>Wash product</span>
</label>
<button class="button is-primary" type="submit" :disabled="!permissions.can_edit">
<button class="button is-primary" type="submit" :disabled="!canEditVehicleTypeProduct">
<span class="icon"><i class="fas fa-floppy-disk"></i></span>
<span>Save vehicle type</span>
</button>
@@ -35,14 +35,27 @@ describe("self-serve studio managed inspector", () => {
expect(source).toContain("const normalizeVehicleTypeForm = (raw = {}) => {");
expect(source).toContain("const saveVehicleTypeProduct = async () => {");
expect(source).toContain("if (!canEditVehicleTypeProduct.value) {");
expect(source).toContain('await requestPut("/products", {');
expect(source).toContain('data-testid="studio-vehicle-type-form"');
expect(source).toContain('data-testid="studio-vehicle-type-name"');
expect(source).toContain(':disabled="!canEditVehicleTypeProduct"');
expect(source).toContain("const normalizeMachineTypeForm = (raw = {}) => {");
expect(source).toContain("const saveMachineType = async () => {");
expect(source).toContain('await requestPut("/department/selfserve/machine-types", {');
});
it("requires superuser access before saving vehicle type product catalog fields", () => {
const source = studioSource();
expect(source).toContain("const canEditVehicleTypeProduct = computed(() =>");
expect(source).toContain("Boolean(permissions.value.can_edit) && SessionUser.canAccessSuperUser()");
expect(source.indexOf("if (!canEditVehicleTypeProduct.value) {")).toBeLessThan(
source.indexOf('await requestPut("/products", {')
);
expect(source).toContain("Only superusers can update vehicle type product catalog fields.");
});
it("manages virtual hardware from selected gateway and relay binding nodes", () => {
const source = studioSource();