Validation disabling waring, and script links to Intune portal

This commit is contained in:
Oliver Kieselbach
2026-03-05 12:22:24 +01:00
parent e9eadac135
commit 4e005e3f52
3 changed files with 99 additions and 27 deletions
@@ -1,5 +1,7 @@
"use client";
import { useState } from "react";
interface AutopilotValidationSectionProps {
validateAutopilotDevice: boolean;
setValidateAutopilotDevice: (value: boolean) => void;
@@ -20,6 +22,40 @@ export default function AutopilotValidationSection({
onBeginConsent,
}: AutopilotValidationSectionProps) {
const anyValidationEnabled = validateAutopilotDevice || validateCorporateIdentifier;
const [disableConfirm, setDisableConfirm] = useState<'autopilot' | 'corporate' | null>(null);
const handleToggleAutopilot = () => {
if (validateAutopilotDevice) {
setDisableConfirm('autopilot');
} else {
if (validateCorporateIdentifier) {
setValidateAutopilotDevice(true);
} else {
onBeginConsent('autopilot');
}
}
};
const handleToggleCorporate = () => {
if (validateCorporateIdentifier) {
setDisableConfirm('corporate');
} else {
if (validateAutopilotDevice) {
setValidateCorporateIdentifier(true);
} else {
onBeginConsent('corporate');
}
}
};
const confirmDisable = () => {
if (disableConfirm === 'autopilot') {
setValidateAutopilotDevice(false);
} else if (disableConfirm === 'corporate') {
setValidateCorporateIdentifier(false);
}
setDisableConfirm(null);
};
return (
<div className="bg-white rounded-lg shadow">
@@ -50,18 +86,7 @@ export default function AutopilotValidationSection({
</p>
</div>
<button
onClick={() => {
if (validateAutopilotDevice) {
setValidateAutopilotDevice(false);
} else {
// If corporate identifier is already on, consent exists — just enable
if (validateCorporateIdentifier) {
setValidateAutopilotDevice(true);
} else {
onBeginConsent('autopilot');
}
}
}}
onClick={handleToggleAutopilot}
disabled={saving || autopilotConsentInProgress}
className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors disabled:opacity-60 disabled:cursor-not-allowed ${validateAutopilotDevice ? 'bg-emerald-500' : 'bg-gray-300'}`}
>
@@ -82,18 +107,7 @@ export default function AutopilotValidationSection({
</p>
</div>
<button
onClick={() => {
if (validateCorporateIdentifier) {
setValidateCorporateIdentifier(false);
} else {
// If autopilot is already on, consent exists — just enable
if (validateAutopilotDevice) {
setValidateCorporateIdentifier(true);
} else {
onBeginConsent('corporate');
}
}
}}
onClick={handleToggleCorporate}
disabled={saving || autopilotConsentInProgress}
className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors disabled:opacity-60 disabled:cursor-not-allowed ${validateCorporateIdentifier ? 'bg-emerald-500' : 'bg-gray-300'}`}
>
@@ -115,6 +129,56 @@ export default function AutopilotValidationSection({
</div>
)}
</div>
{/* Disable Validation Confirmation Dialog */}
{disableConfirm && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg shadow-xl max-w-md w-full p-6">
<div className="flex items-center space-x-3 mb-4">
<div className="w-12 h-12 bg-amber-100 rounded-full flex items-center justify-center flex-shrink-0">
<svg className="w-6 h-6 text-amber-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div>
<h3 className="text-lg font-bold text-gray-900">Disable Validation</h3>
<p className="text-sm text-amber-600 font-medium">
{disableConfirm === 'autopilot' ? 'Autopilot Device Validation' : 'Corporate Identifier Validation'}
</p>
</div>
</div>
<p className="text-sm text-gray-700 mb-2">
Are you sure you want to disable this validation?
</p>
{disableConfirm === 'autopilot' && !validateCorporateIdentifier && (
<div className="bg-red-50 border border-red-200 rounded-lg p-3 mb-4 text-sm text-red-800">
This is the last active validation. Disabling it will cause the backend to <strong>reject all agent requests</strong> for this tenant.
</div>
)}
{disableConfirm === 'corporate' && !validateAutopilotDevice && (
<div className="bg-red-50 border border-red-200 rounded-lg p-3 mb-4 text-sm text-red-800">
This is the last active validation. Disabling it will cause the backend to <strong>reject all agent requests</strong> for this tenant.
</div>
)}
<div className="flex space-x-3 mt-4">
<button
onClick={() => setDisableConfirm(null)}
className="flex-1 px-4 py-2 border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50 transition-colors"
>
Cancel
</button>
<button
onClick={confirmDisable}
className="flex-1 px-4 py-2 bg-amber-600 text-white rounded-md hover:bg-amber-700 transition-colors"
>
Disable
</button>
</div>
</div>
</div>
)}
</div>
);
}
@@ -135,6 +135,13 @@ export default function ScriptExecutions({ events, showScriptOutput }: ScriptExe
);
}
function getIntuneScriptUrl(policyId: string, scriptType: string): string {
if (scriptType === "remediation") {
return `https://intune.microsoft.com/#view/Microsoft_Intune_Enrollment/UXAnalyticsScriptMenu/~/overview/id/${policyId}`;
}
return `https://intune.microsoft.com/#view/Microsoft_Intune_DeviceSettings/ConfigureWMPolicyMenuBlade/~/overview/policyId/${policyId}/policyType/0`;
}
function ScriptItemRow({ item, showScriptOutput }: { item: ScriptItem; showScriptOutput?: boolean }) {
const [showDetails, setShowDetails] = useState(false);
@@ -143,6 +150,7 @@ function ScriptItemRow({ item, showScriptOutput }: { item: ScriptItem; showScrip
: "bg-green-50 border border-green-200";
const shortId = item.policyId.length >= 8 ? item.policyId.substring(0, 8) : item.policyId;
const intuneUrl = getIntuneScriptUrl(item.policyId, item.scriptType);
// Build label: "Platform Script" or "Remediation Detection" / "Remediation"
let label: string;
@@ -178,7 +186,7 @@ function ScriptItemRow({ item, showScriptOutput }: { item: ScriptItem; showScrip
</svg>
)}
<span className="text-sm font-medium text-gray-900 truncate">{label}</span>
<span className="text-xs font-mono text-gray-500">{shortId}…</span>
<a href={intuneUrl} target="_blank" rel="noopener noreferrer" className="text-xs font-mono text-blue-600 hover:text-blue-800 hover:underline" title="Open in Intune portal">{shortId}…</a>
<span className={`text-xs px-2 py-0.5 rounded-full font-medium ${
item.scriptType === "remediation"
? "bg-amber-100 text-amber-700"
@@ -212,7 +220,7 @@ function ScriptItemRow({ item, showScriptOutput }: { item: ScriptItem; showScrip
<div className="mt-3 space-y-2">
{/* Metadata */}
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-600">
<span><span className="font-medium text-gray-700">Policy ID:</span> <span className="font-mono">{item.policyId}</span></span>
<span><span className="font-medium text-gray-700">Policy ID:</span> <a href={intuneUrl} target="_blank" rel="noopener noreferrer" className="font-mono text-blue-600 hover:text-blue-800 hover:underline">{item.policyId}</a></span>
{item.runContext && <span><span className="font-medium text-gray-700">Context:</span> {item.runContext}</span>}
{item.exitCode != null && <span><span className="font-medium text-gray-700">Exit Code:</span> <span className="font-mono">{item.exitCode}</span></span>}
{item.result && <span><span className="font-medium text-gray-700">Result:</span> {item.result}</span>}
File diff suppressed because one or more lines are too long