mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
hook up SSE for UI android sse (#26656)
For #26207 add server side event setup for the UI when turning on android MDM. - [ ] Manual QA must be performed in the three main OSs, macOS, Windows and Linux.
This commit is contained in:
parent
973fe46c5e
commit
44f2858769
3 changed files with 106 additions and 8 deletions
|
|
@ -1,4 +1,10 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import React, {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { InjectedRouter } from "react-router";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
|
|
@ -21,17 +27,68 @@ import TurnOffAndroidMdmModal from "./components/TurnOffAndroidMdmModal";
|
|||
|
||||
const baseClass = "android-mdm-page";
|
||||
|
||||
const TurnOnAndroidMdm = () => {
|
||||
const POPUP_WIDTH = 885;
|
||||
const POPUP_HEIGHT = 600;
|
||||
|
||||
interface ITurnOnAndroidMdmProps {
|
||||
router: InjectedRouter;
|
||||
}
|
||||
|
||||
const TurnOnAndroidMdm = ({ router }: ITurnOnAndroidMdmProps) => {
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
|
||||
// TODO: figure out issue with aborting the SSE fetch when the window is closed
|
||||
const newWindow = useRef<Window | null>(null);
|
||||
|
||||
const [fetchingSignupUrl, setFetchingSignupUrl] = useState(false);
|
||||
const [setupSse, setSetupSse] = useState(false);
|
||||
|
||||
const handleSSE = useCallback(
|
||||
async (abortController: AbortController) => {
|
||||
try {
|
||||
await mdmAndroidAPI.startSSE(abortController.signal);
|
||||
abortController.abort();
|
||||
renderFlash("success", "Android MDM turned on successfully.", {
|
||||
persistOnPageChange: true,
|
||||
});
|
||||
setSetupSse(false);
|
||||
router.push(PATHS.ADMIN_INTEGRATIONS_MDM);
|
||||
} catch {
|
||||
renderFlash("error", "Couldn't turn on Android MDM. Please try again.");
|
||||
setSetupSse(false);
|
||||
}
|
||||
},
|
||||
[renderFlash, router]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const abortController = new AbortController();
|
||||
|
||||
if (setupSse) {
|
||||
handleSSE(abortController);
|
||||
|
||||
return () => {
|
||||
abortController.abort();
|
||||
};
|
||||
}
|
||||
}, [setupSse, router, renderFlash, handleSSE]);
|
||||
|
||||
const onConnectMdm = async () => {
|
||||
setFetchingSignupUrl(true);
|
||||
try {
|
||||
const res = await mdmAndroidAPI.getSignupUrl();
|
||||
|
||||
// TODO: set up SSE for successful android mdm turned on here.
|
||||
window.open(res.android_enterprise_signup_url, "_blank");
|
||||
// Calculate the center position
|
||||
const left = window.screenX + (window.innerWidth - POPUP_WIDTH) / 2;
|
||||
const top = window.screenY + (window.innerHeight - POPUP_HEIGHT) / 2;
|
||||
|
||||
// TODO: figure out issue with aborting the SSE fetch when the window is closed
|
||||
newWindow.current = window.open(
|
||||
res.android_enterprise_signup_url,
|
||||
"_blank",
|
||||
`width=${POPUP_WIDTH},height=${POPUP_HEIGHT},top=${top},left=${left}`
|
||||
);
|
||||
setSetupSse(true);
|
||||
} catch (e) {
|
||||
renderFlash("error", "Couldn't connect. Please try again");
|
||||
}
|
||||
|
|
@ -112,9 +169,6 @@ interface IAndroidMdmPageProps {
|
|||
|
||||
const AndroidMdmPage = ({ router }: IAndroidMdmPageProps) => {
|
||||
const { isAndroidMdmEnabledAndConfigured } = useContext(AppContext);
|
||||
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
|
||||
const [showTurnOffMdmModal, setShowTurnOffMdmModal] = useState(false);
|
||||
|
||||
return (
|
||||
|
|
@ -128,7 +182,7 @@ const AndroidMdmPage = ({ router }: IAndroidMdmPageProps) => {
|
|||
|
||||
<div className={`${baseClass}__content`}>
|
||||
{!isAndroidMdmEnabledAndConfigured ? (
|
||||
<TurnOnAndroidMdm />
|
||||
<TurnOnAndroidMdm router={router} />
|
||||
) : (
|
||||
<TurnOffAndroidMdm
|
||||
onClickTurnOff={() => setShowTurnOffMdmModal(true)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import sendRequest from "services";
|
||||
import endpoints from "utilities/endpoints";
|
||||
import { authToken } from "utilities/local";
|
||||
|
||||
interface IGetAndroidSignupUrlResponse {
|
||||
android_enterprise_signup_url: string;
|
||||
|
|
@ -24,4 +25,46 @@ export default {
|
|||
const { MDM_ANDROID_ENTERPRISE } = endpoints;
|
||||
return sendRequest("DELETE", MDM_ANDROID_ENTERPRISE);
|
||||
},
|
||||
|
||||
/**
|
||||
* This function starts a Server-Sent Events connection with the fleet server
|
||||
* to get messages about a successful Android mdm connection. We have to use
|
||||
* fetch here because the EventSource API does not support setting headers,
|
||||
* which we need to authenticate the request.
|
||||
*/
|
||||
startSSE: (abortSignal: AbortSignal): Promise<void> => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const response = await fetch(endpoints.MDM_ANDROID_SSE_URL, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken()}`,
|
||||
},
|
||||
signal: abortSignal,
|
||||
});
|
||||
|
||||
const reader = response?.body?.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
while (true) {
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const { done, value } = await reader?.read();
|
||||
if (done) break;
|
||||
const text = decoder.decode(value);
|
||||
if (text === "Android Enterprise successfully connected") {
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if ((error as Error).name === "AbortError") {
|
||||
// we want to ignore abort errors
|
||||
console.error("SSE Fetch aborted");
|
||||
} else {
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ export default {
|
|||
|
||||
MDM_ANDROID_ENTERPRISE: `/${API_VERSION}/fleet/android_enterprise`,
|
||||
MDM_ANDROID_SIGNUP_URL: `/${API_VERSION}/fleet/android_enterprise/signup_url`,
|
||||
MDM_ANDROID_SSE_URL: `/api/${API_VERSION}/fleet/android_enterprise/signup_sse`,
|
||||
|
||||
// apple mdm endpoints
|
||||
MDM_APPLE: `/${API_VERSION}/fleet/mdm/apple`,
|
||||
|
|
|
|||
Loading…
Reference in a new issue