<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #38630 ## Testing - [x] QA'd all new/changed functionality manually Screenshots below were taken with a **Team Technician** user. Same changes apply for a **Global Technician**. #### Controls > OS settings > Disk encryption - Shows table without controls below. - Shows empty state (doesn't allow to turn it on). <img width="1915" height="886" alt="Screenshot 2026-02-10 at 12 24 25 PM" src="https://github.com/user-attachments/assets/3f44d338-e728-4eb2-ad93-e30844201b52" /> <img width="1913" height="907" alt="Screenshot 2026-02-10 at 12 31 38 PM" src="https://github.com/user-attachments/assets/71706e9e-0540-4c25-b5c0-3f7ccff3ba5a" /> #### Controls > OS settings > Custom settings - Changed description to say **View configuration profiles that apply custom settings.** instead of **Create and upload configuration profiles to apply custom settings.**. - **Add profile** not shown within table header. - Trash can icon not shown when hovering over a row within the table. - **Add profile** card not shown on empty state. Instead, "No configuration profiles have been added." is shown. <img width="1911" height="729" alt="Screenshot 2026-02-10 at 12 24 39 PM" src="https://github.com/user-attachments/assets/aa68cbaf-4772-402d-9288-b4be2ddd3250" /> <img width="1912" height="650" alt="Screenshot 2026-02-10 at 12 28 48 PM" src="https://github.com/user-attachments/assets/6a186172-b01f-4314-bb50-4cb533e13bce" /> #### Controls > Scripts > Library - **Add script** not shown within table header. - No actions shown when hovering over a table row. - Can view script by clicking on a table row. - Removed **To run the script across multiple hosts, add a policy automation on the Policies page** line below **To run this script on a host, go to the Hosts page and select a host.**. - Updated copy to `To run this script on a host, go to the Hosts page and select a host. Then, click Actions > Run script.` <img width="1912" height="772" alt="Screenshot 2026-02-10 at 12 25 46 PM" src="https://github.com/user-attachments/assets/83fbc1ec-3a6e-4bb5-865e-b5e7faef1e37" /> <img width="1732" height="761" alt="Screenshot 2026-02-11 at 3 50 33 PM" src="https://github.com/user-attachments/assets/6dda97d7-fde2-4bcd-94b3-fa7368c65528" /> #### Labels Can add label and filter by label <img width="160" height="247" alt="Screenshot 2026-02-10 at 12 51 24 PM" src="https://github.com/user-attachments/assets/ed63b708-27f8-4363-9d4f-9a7b0bf82b21" /> <img width="1901" height="856" alt="Screenshot 2026-02-10 at 12 35 07 PM" src="https://github.com/user-attachments/assets/c2ef5e21-03ab-4955-a22f-cd6ca32f3179" /> <img width="1903" height="937" alt="Screenshot 2026-02-10 at 12 36 11 PM" src="https://github.com/user-attachments/assets/d9d9f3bc-4d71-4c4b-902a-455eec9e057c" /> Can edit/delete labels created by themselves. NOTE: my technician user ID is 37 - note that the **x** label belongs to a different user id, while the second label belongs to ID 37, therefore it can be edited and deleted. <img width="1915" height="1152" alt="Screenshot 2026-02-10 at 12 38 29 PM" src="https://github.com/user-attachments/assets/21f44c11-4e2d-456b-8547-90936b5d7602" /> <img width="1911" height="1154" alt="Screenshot 2026-02-10 at 12 38 42 PM" src="https://github.com/user-attachments/assets/f9f7ea30-11b2-4d2d-9d71-de7299e4b451" /> Can delete manual label from host https://github.com/user-attachments/assets/b64ba6dd-3f54-4dcd-9c57-7bede65122da #### Host details Can run scripts and view their results <img width="1908" height="472" alt="Screenshot 2026-02-10 at 12 52 33 PM" src="https://github.com/user-attachments/assets/d1e40339-ec52-47ff-bc53-c311498ffe80" /> <img width="1882" height="716" alt="Screenshot 2026-02-10 at 12 52 40 PM" src="https://github.com/user-attachments/assets/dd0c2ec3-8cb8-4835-9c6d-f731a7434637" /> <img width="1915" height="718" alt="Screenshot 2026-02-10 at 12 52 48 PM" src="https://github.com/user-attachments/assets/5e7a73e0-ac5b-4d38-b635-770f53dea9e3" /> <img width="1914" height="718" alt="Screenshot 2026-02-10 at 12 52 55 PM" src="https://github.com/user-attachments/assets/b199c796-66b1-46bc-b2b5-fd35e8aa7a7c" /> Can run query associated to host as a live query https://github.com/user-attachments/assets/7aea6f63-e443-4fa0-87dc-48bef84efa2f #### Software Doesn't show trash can icon on software installer card, just the download one. <img width="1423" height="838" alt="Screenshot 2026-02-10 at 1 33 53 PM" src="https://github.com/user-attachments/assets/3a55c226-0bba-43ac-8594-7b5ac0a3684a" /> Can install/uninstall software on a host. Note that **Add software** button is hidden (technicians can't add software). <img width="1378" height="277" alt="Screenshot 2026-02-10 at 3 08 55 PM" src="https://github.com/user-attachments/assets/bf413467-2071-48b6-b62b-f3a721b6057c" /> #### Queries - Can run inherited queries on all hosts https://github.com/user-attachments/assets/09f07e6b-a8c1-453e-81fd-4deb16005836 - Can run team queries on all hosts https://github.com/user-attachments/assets/18b62dea-e159-40ea-b0ed-1d96b6bd40e7 - Can't manage automations or add queries (buttons are not shown at the top-right corner) #### Policies Same as Queries https://github.com/user-attachments/assets/2c24514a-2ae0-47a6-b631-6f9e48fc7b9c #### Protected routes Tested that I can't access routes that have restricted functionality for this role, such as: - **/controls/os-updates**, **/controls/setup-experience** and **/controls/os-settings/certificates** => redirects to **/controls/os-settings** ✅ - **/controls/scripts/progress** => redirects to **/controls/scripts/library** ✅ - **/queries/new** and **/software/add/*** => renders access denied page ✅ --------- Co-authored-by: Lucas Manuel Rodriguez <lucas@fleetdm.com>
674 lines
20 KiB
TypeScript
674 lines
20 KiB
TypeScript
import React, { createContext, useReducer, useMemo, ReactNode } from "react";
|
|
|
|
import { IConfig, IUserSettings } from "interfaces/config";
|
|
import { IEnrollSecret } from "interfaces/enroll_secret";
|
|
import {
|
|
APP_CONTEXT_ALL_TEAMS_SUMMARY,
|
|
ITeamSummary,
|
|
APP_CONTEXT_NO_TEAM_SUMMARY,
|
|
APP_CONTEXT_NO_TEAM_ID,
|
|
} from "interfaces/team";
|
|
import { IUser } from "interfaces/user";
|
|
import permissions from "utilities/permissions";
|
|
import sort from "utilities/sort";
|
|
import { hasLicenseExpired, willExpireWithinXDays } from "utilities/helpers";
|
|
|
|
enum ACTIONS {
|
|
SET_AVAILABLE_TEAMS = "SET_AVAILABLE_TEAMS",
|
|
SET_USER_SETTINGS = "SET_USER_SETTINGS",
|
|
SET_CURRENT_USER = "SET_CURRENT_USER",
|
|
SET_CURRENT_TEAM = "SET_CURRENT_TEAM",
|
|
SET_CONFIG = "SET_CONFIG",
|
|
SET_ENROLL_SECRET = "SET_ENROLL_SECRET",
|
|
SET_ANDROID_ENTERPRISE_DELETED = "SET_ANDROID_ENTERPRISE_DELETED",
|
|
SET_ABM_EXPIRY = "SET_ABM_EXPIRY",
|
|
SET_APNS_EXPIRY = "SET_APNS_EXPIRY",
|
|
SET_VPP_EXPIRY = "SET_VPP_EXPIRY",
|
|
SET_SANDBOX_EXPIRY = "SET_SANDBOX_EXPIRY",
|
|
SET_NO_SANDBOX_HOSTS = "SET_NO_SANDBOX_HOSTS",
|
|
SET_FILTERED_HOSTS_PATH = "SET_FILTERED_HOSTS_PATH",
|
|
SET_FILTERED_SOFTWARE_PATH = "SET_FILTERED_SOFTWARE_PATH",
|
|
SET_FILTERED_QUERIES_PATH = "SET_FILTERED_QUERIES_PATH",
|
|
SET_FILTERED_POLICIES_PATH = "SET_FILTERED_POLICIES_PATH",
|
|
}
|
|
|
|
interface ISetAvailableTeamsAction {
|
|
type: ACTIONS.SET_AVAILABLE_TEAMS;
|
|
user: IUser | null;
|
|
availableTeams: ITeamSummary[];
|
|
}
|
|
|
|
interface ISetUserSettingsAction {
|
|
type: ACTIONS.SET_USER_SETTINGS;
|
|
userSettings: IUserSettings;
|
|
}
|
|
|
|
interface ISetConfigAction {
|
|
type: ACTIONS.SET_CONFIG;
|
|
config: IConfig;
|
|
}
|
|
|
|
interface ISetCurrentTeamAction {
|
|
type: ACTIONS.SET_CURRENT_TEAM;
|
|
currentTeam: ITeamSummary | undefined;
|
|
}
|
|
interface ISetCurrentUserAction {
|
|
type: ACTIONS.SET_CURRENT_USER;
|
|
currentUser: IUser;
|
|
}
|
|
interface ISetEnrollSecretAction {
|
|
type: ACTIONS.SET_ENROLL_SECRET;
|
|
enrollSecret: IEnrollSecret[];
|
|
}
|
|
|
|
interface ISetAndroidEnterpriseDeletedAction {
|
|
type: ACTIONS.SET_ANDROID_ENTERPRISE_DELETED;
|
|
isDeleted: boolean;
|
|
}
|
|
|
|
interface IAbmExpiry {
|
|
earliestExpiry: string;
|
|
needsAbmTermsRenewal: boolean;
|
|
}
|
|
|
|
interface ISetABMExpiryAction {
|
|
type: ACTIONS.SET_ABM_EXPIRY;
|
|
abmExpiry: IAbmExpiry;
|
|
}
|
|
|
|
interface ISetAPNsExpiryAction {
|
|
type: ACTIONS.SET_APNS_EXPIRY;
|
|
apnsExpiry: string;
|
|
}
|
|
|
|
interface ISetVppExpiryAction {
|
|
type: ACTIONS.SET_VPP_EXPIRY;
|
|
vppExpiry: string;
|
|
}
|
|
|
|
interface ISetSandboxExpiryAction {
|
|
type: ACTIONS.SET_SANDBOX_EXPIRY;
|
|
sandboxExpiry: string;
|
|
}
|
|
|
|
interface ISetNoSandboxHostsAction {
|
|
type: ACTIONS.SET_NO_SANDBOX_HOSTS;
|
|
noSandboxHosts: boolean;
|
|
}
|
|
|
|
interface ISetFilteredHostsPathAction {
|
|
type: ACTIONS.SET_FILTERED_HOSTS_PATH;
|
|
filteredHostsPath: string;
|
|
}
|
|
|
|
interface ISetFilteredSoftwarePathAction {
|
|
type: ACTIONS.SET_FILTERED_SOFTWARE_PATH;
|
|
filteredSoftwarePath: string;
|
|
}
|
|
|
|
interface ISetFilteredQueriesPathAction {
|
|
type: ACTIONS.SET_FILTERED_QUERIES_PATH;
|
|
filteredQueriesPath: string;
|
|
}
|
|
|
|
interface ISetFilteredPoliciesPathAction {
|
|
type: ACTIONS.SET_FILTERED_POLICIES_PATH;
|
|
filteredPoliciesPath: string;
|
|
}
|
|
|
|
type IAction =
|
|
| ISetAvailableTeamsAction
|
|
| ISetUserSettingsAction
|
|
| ISetConfigAction
|
|
| ISetCurrentTeamAction
|
|
| ISetCurrentUserAction
|
|
| ISetEnrollSecretAction
|
|
| ISetAndroidEnterpriseDeletedAction
|
|
| ISetABMExpiryAction
|
|
| ISetAPNsExpiryAction
|
|
| ISetVppExpiryAction
|
|
| ISetSandboxExpiryAction
|
|
| ISetNoSandboxHostsAction
|
|
| ISetFilteredHostsPathAction
|
|
| ISetFilteredSoftwarePathAction
|
|
| ISetFilteredQueriesPathAction
|
|
| ISetFilteredPoliciesPathAction;
|
|
|
|
type Props = {
|
|
children: ReactNode;
|
|
};
|
|
|
|
type InitialStateType = {
|
|
availableTeams?: ITeamSummary[];
|
|
userSettings?: IUserSettings;
|
|
config: IConfig | null;
|
|
currentUser: IUser | null;
|
|
currentTeam?: ITeamSummary;
|
|
enrollSecret: IEnrollSecret[] | null;
|
|
isPreviewMode?: boolean;
|
|
isSandboxMode?: boolean;
|
|
isFreeTier?: boolean;
|
|
isPremiumTier?: boolean;
|
|
isMacMdmEnabledAndConfigured?: boolean;
|
|
isWindowsMdmEnabledAndConfigured?: boolean;
|
|
isAndroidMdmEnabledAndConfigured?: boolean;
|
|
isGlobalAdmin?: boolean;
|
|
isGlobalMaintainer?: boolean;
|
|
isGlobalObserver?: boolean;
|
|
isOnGlobalTeam?: boolean;
|
|
isAnyTeamObserverPlus?: boolean;
|
|
isAnyTeamMaintainer?: boolean;
|
|
isAnyTeamMaintainerOrTeamAdmin?: boolean;
|
|
isTeamObserver?: boolean;
|
|
isTeamMaintainer?: boolean;
|
|
isTeamMaintainerOrTeamAdmin?: boolean;
|
|
isAnyTeamAdmin?: boolean;
|
|
isTeamAdmin?: boolean;
|
|
isTeamTechnician?: boolean;
|
|
isAnyTeamTechnician?: boolean;
|
|
isGlobalTechnician?: boolean;
|
|
isOnlyObserver?: boolean;
|
|
isObserverPlus?: boolean;
|
|
isNoAccess?: boolean;
|
|
isAnyMaintainerAdminObserverPlus?: boolean;
|
|
isAndroidEnterpriseDeleted: boolean;
|
|
isAppleBmExpired: boolean;
|
|
isApplePnsExpired: boolean;
|
|
isVppExpired: boolean;
|
|
needsAbmTermsRenewal: boolean;
|
|
willAppleBmExpire: boolean;
|
|
willApplePnsExpire: boolean;
|
|
willVppExpire: boolean;
|
|
abmExpiry?: IAbmExpiry;
|
|
apnsExpiry?: string;
|
|
vppExpiry?: string;
|
|
sandboxExpiry?: string;
|
|
noSandboxHosts?: boolean;
|
|
filteredHostsPath?: string;
|
|
filteredSoftwarePath?: string;
|
|
filteredQueriesPath?: string;
|
|
filteredPoliciesPath?: string;
|
|
isVppEnabled?: boolean;
|
|
setAvailableTeams: (
|
|
user: IUser | null,
|
|
availableTeams: ITeamSummary[]
|
|
) => void;
|
|
setUserSettings: (userSettings: IUserSettings) => void;
|
|
setCurrentUser: (user: IUser) => void;
|
|
setCurrentTeam: (team?: ITeamSummary) => void;
|
|
setConfig: (config: IConfig) => void;
|
|
setEnrollSecret: (enrollSecret: IEnrollSecret[]) => void;
|
|
setAndroidEnterpriseDeleted: (isDeleted: boolean) => void;
|
|
setAPNsExpiry: (apnsExpiry: string) => void;
|
|
setABMExpiry: (abmExpiry: IAbmExpiry) => void;
|
|
setVppExpiry: (vppExpiry: string) => void;
|
|
setSandboxExpiry: (sandboxExpiry: string) => void;
|
|
setNoSandboxHosts: (noSandboxHosts: boolean) => void;
|
|
setFilteredHostsPath: (filteredHostsPath: string) => void;
|
|
setFilteredSoftwarePath: (filteredSoftwarePath: string) => void;
|
|
setFilteredQueriesPath: (filteredQueriesPath: string) => void;
|
|
setFilteredPoliciesPath: (filteredPoliciesPath: string) => void;
|
|
};
|
|
|
|
export type IAppContext = InitialStateType;
|
|
|
|
export const initialState = {
|
|
availableTeams: undefined,
|
|
userSettings: undefined,
|
|
config: null,
|
|
currentUser: null,
|
|
currentTeam: undefined,
|
|
enrollSecret: null,
|
|
isPreviewMode: false,
|
|
isSandboxMode: false,
|
|
isFreeTier: undefined,
|
|
isPremiumTier: undefined,
|
|
isMacMdmEnabledAndConfigured: undefined,
|
|
isWindowsMdmEnabledAndConfigured: undefined,
|
|
isAndroidMdmEnabledAndConfigured: undefined,
|
|
isGlobalAdmin: undefined,
|
|
isGlobalMaintainer: undefined,
|
|
isGlobalObserver: undefined,
|
|
isOnGlobalTeam: undefined,
|
|
isAnyTeamObserverPlus: undefined,
|
|
isAnyTeamMaintainer: undefined,
|
|
isAnyTeamMaintainerOrTeamAdmin: undefined,
|
|
isTeamObserver: undefined,
|
|
isTeamMaintainer: undefined,
|
|
isTeamMaintainerOrTeamAdmin: undefined,
|
|
isAnyTeamAdmin: undefined,
|
|
isTeamAdmin: undefined,
|
|
isTeamTechnician: undefined,
|
|
isAnyTeamTechnician: undefined,
|
|
isGlobalTechnician: undefined,
|
|
isOnlyObserver: undefined,
|
|
isObserverPlus: undefined,
|
|
isNoAccess: undefined,
|
|
isAnyMaintainerAdminObserverPlus: undefined,
|
|
filteredHostsPath: undefined,
|
|
filteredSoftwarePath: undefined,
|
|
filteredQueriesPath: undefined,
|
|
filteredPoliciesPath: undefined,
|
|
isAndroidEnterpriseDeleted: false,
|
|
isAppleBmExpired: false,
|
|
isApplePnsExpired: false,
|
|
isVppExpired: false,
|
|
needsAbmTermsRenewal: false,
|
|
willAppleBmExpire: false,
|
|
willApplePnsExpire: false,
|
|
willVppExpire: false,
|
|
setAvailableTeams: () => null,
|
|
setUserSettings: () => null,
|
|
setCurrentUser: () => null,
|
|
setCurrentTeam: () => null,
|
|
setConfig: () => null,
|
|
setEnrollSecret: () => null,
|
|
setAndroidEnterpriseDeleted: () => null,
|
|
setAPNsExpiry: () => null,
|
|
setABMExpiry: () => null,
|
|
setVppExpiry: () => null,
|
|
setSandboxExpiry: () => null,
|
|
setNoSandboxHosts: () => null,
|
|
setFilteredHostsPath: () => null,
|
|
setFilteredSoftwarePath: () => null,
|
|
setFilteredQueriesPath: () => null,
|
|
setFilteredPoliciesPath: () => null,
|
|
};
|
|
|
|
const detectPreview = () => {
|
|
return window.location.origin === "http://localhost:1337";
|
|
};
|
|
|
|
// helper function - this is run every
|
|
// time currentUser, currentTeam, config, or teamId is changed
|
|
const setPermissions = (
|
|
user: IUser | null,
|
|
config: IConfig | null,
|
|
teamId = APP_CONTEXT_NO_TEAM_ID
|
|
) => {
|
|
if (!user || !config) {
|
|
return {};
|
|
}
|
|
|
|
if (teamId < APP_CONTEXT_NO_TEAM_ID) {
|
|
teamId = APP_CONTEXT_NO_TEAM_ID;
|
|
}
|
|
|
|
return {
|
|
isSandboxMode: permissions.isSandboxMode(config),
|
|
isFreeTier: permissions.isFreeTier(config),
|
|
isPremiumTier: permissions.isPremiumTier(config),
|
|
isMacMdmEnabledAndConfigured: permissions.isMacMdmEnabledAndConfigured(
|
|
config
|
|
),
|
|
isWindowsMdmEnabledAndConfigured: permissions.isWindowsMdmEnabledAndConfigured(
|
|
config
|
|
),
|
|
isAndroidMdmEnabledAndConfigured: permissions.isAndroidMdmEnabledAndConfigured(
|
|
config
|
|
),
|
|
isGlobalAdmin: permissions.isGlobalAdmin(user),
|
|
isGlobalMaintainer: permissions.isGlobalMaintainer(user),
|
|
isGlobalObserver: permissions.isGlobalObserver(user),
|
|
isGlobalTechnician: permissions.isGlobalTechnician(user),
|
|
isOnGlobalTeam: permissions.isOnGlobalTeam(user),
|
|
isAnyTeamObserverPlus: permissions.isAnyTeamObserverPlus(user),
|
|
isAnyTeamMaintainer: permissions.isAnyTeamMaintainer(user),
|
|
isAnyTeamMaintainerOrTeamAdmin: permissions.isAnyTeamMaintainerOrTeamAdmin(
|
|
user
|
|
),
|
|
isAnyTeamAdmin: permissions.isAnyTeamAdmin(user),
|
|
isTeamObserver: permissions.isTeamObserver(user, teamId),
|
|
isTeamMaintainer: permissions.isTeamMaintainer(user, teamId),
|
|
isTeamAdmin: permissions.isTeamAdmin(user, teamId),
|
|
isTeamTechnician: permissions.isTeamTechnician(user, teamId),
|
|
isAnyTeamTechnician: permissions.isAnyTeamTechnician(user),
|
|
isTeamMaintainerOrTeamAdmin: permissions.isTeamMaintainerOrTeamAdmin(
|
|
user,
|
|
teamId
|
|
),
|
|
isOnlyObserver: permissions.isOnlyObserver(user),
|
|
isObserverPlus: permissions.isObserverPlus(user, teamId),
|
|
isNoAccess: permissions.isNoAccess(user),
|
|
};
|
|
};
|
|
|
|
const reducer = (state: InitialStateType, action: IAction) => {
|
|
switch (action.type) {
|
|
case ACTIONS.SET_USER_SETTINGS: {
|
|
const { userSettings } = action;
|
|
return {
|
|
...state,
|
|
userSettings,
|
|
};
|
|
}
|
|
case ACTIONS.SET_AVAILABLE_TEAMS: {
|
|
const { user, availableTeams } = action;
|
|
|
|
let sortedTeams = availableTeams.sort(
|
|
(a: ITeamSummary, b: ITeamSummary) =>
|
|
sort.caseInsensitiveAsc(a.name, b.name)
|
|
);
|
|
sortedTeams = sortedTeams.filter(
|
|
(t) =>
|
|
t.name !== APP_CONTEXT_ALL_TEAMS_SUMMARY.name &&
|
|
t.name !== APP_CONTEXT_NO_TEAM_SUMMARY.name
|
|
);
|
|
if (user && permissions.isOnGlobalTeam(user)) {
|
|
sortedTeams.unshift(
|
|
APP_CONTEXT_ALL_TEAMS_SUMMARY,
|
|
APP_CONTEXT_NO_TEAM_SUMMARY
|
|
);
|
|
}
|
|
|
|
return {
|
|
...state,
|
|
availableTeams: sortedTeams,
|
|
};
|
|
}
|
|
case ACTIONS.SET_CURRENT_USER: {
|
|
const { currentUser } = action;
|
|
|
|
return {
|
|
...state,
|
|
currentUser,
|
|
...setPermissions(currentUser, state.config, state.currentTeam?.id),
|
|
};
|
|
}
|
|
case ACTIONS.SET_CURRENT_TEAM: {
|
|
const { currentTeam } = action;
|
|
return {
|
|
...state,
|
|
currentTeam,
|
|
...setPermissions(state.currentUser, state.config, currentTeam?.id),
|
|
};
|
|
}
|
|
case ACTIONS.SET_CONFIG: {
|
|
const { config } = action;
|
|
return {
|
|
...state,
|
|
config,
|
|
...setPermissions(state.currentUser, config, state.currentTeam?.id),
|
|
};
|
|
}
|
|
case ACTIONS.SET_ENROLL_SECRET: {
|
|
const { enrollSecret } = action;
|
|
return {
|
|
...state,
|
|
enrollSecret,
|
|
};
|
|
}
|
|
case ACTIONS.SET_ANDROID_ENTERPRISE_DELETED: {
|
|
const { isDeleted } = action;
|
|
return {
|
|
...state,
|
|
isAndroidEnterpriseDeleted: isDeleted,
|
|
};
|
|
}
|
|
case ACTIONS.SET_ABM_EXPIRY: {
|
|
const { abmExpiry } = action;
|
|
const { earliestExpiry, needsAbmTermsRenewal } = abmExpiry;
|
|
return {
|
|
...state,
|
|
abmExpiry,
|
|
isAppleBmExpired: hasLicenseExpired(earliestExpiry),
|
|
willAppleBmExpire: willExpireWithinXDays(earliestExpiry, 30),
|
|
needsAbmTermsRenewal,
|
|
};
|
|
}
|
|
case ACTIONS.SET_APNS_EXPIRY: {
|
|
const { apnsExpiry } = action;
|
|
return {
|
|
...state,
|
|
apnsExpiry,
|
|
isApplePnsExpired: hasLicenseExpired(apnsExpiry),
|
|
willApplePnsExpire: willExpireWithinXDays(apnsExpiry, 30),
|
|
};
|
|
}
|
|
case ACTIONS.SET_VPP_EXPIRY: {
|
|
const { vppExpiry } = action;
|
|
return {
|
|
...state,
|
|
vppExpiry,
|
|
isVppExpired: hasLicenseExpired(vppExpiry),
|
|
willVppExpire: willExpireWithinXDays(vppExpiry, 30),
|
|
};
|
|
}
|
|
case ACTIONS.SET_SANDBOX_EXPIRY: {
|
|
const { sandboxExpiry } = action;
|
|
return {
|
|
...state,
|
|
sandboxExpiry,
|
|
};
|
|
}
|
|
case ACTIONS.SET_NO_SANDBOX_HOSTS: {
|
|
const { noSandboxHosts } = action;
|
|
return {
|
|
...state,
|
|
noSandboxHosts,
|
|
};
|
|
}
|
|
case ACTIONS.SET_FILTERED_HOSTS_PATH: {
|
|
const { filteredHostsPath } = action;
|
|
return {
|
|
...state,
|
|
filteredHostsPath,
|
|
};
|
|
}
|
|
case ACTIONS.SET_FILTERED_SOFTWARE_PATH: {
|
|
const { filteredSoftwarePath } = action;
|
|
return {
|
|
...state,
|
|
filteredSoftwarePath,
|
|
};
|
|
}
|
|
case ACTIONS.SET_FILTERED_QUERIES_PATH: {
|
|
const { filteredQueriesPath } = action;
|
|
return {
|
|
...state,
|
|
filteredQueriesPath,
|
|
};
|
|
}
|
|
case ACTIONS.SET_FILTERED_POLICIES_PATH: {
|
|
const { filteredPoliciesPath } = action;
|
|
return {
|
|
...state,
|
|
filteredPoliciesPath,
|
|
};
|
|
}
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
export const AppContext = createContext<InitialStateType>(initialState);
|
|
|
|
const AppProvider = ({ children }: Props): JSX.Element => {
|
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
|
|
const value = useMemo(
|
|
() => ({
|
|
availableTeams: state.availableTeams,
|
|
userSettings: state.userSettings,
|
|
config: state.config,
|
|
currentUser: state.currentUser,
|
|
currentTeam: state.currentTeam,
|
|
enrollSecret: state.enrollSecret,
|
|
sandboxExpiry: state.sandboxExpiry,
|
|
abmExpiry: state.abmExpiry,
|
|
apnsExpiry: state.apnsExpiry,
|
|
vppExpiry: state.vppExpiry,
|
|
isAndroidEnterpriseDeleted: state.isAndroidEnterpriseDeleted,
|
|
isAppleBmExpired: state.isAppleBmExpired,
|
|
isApplePnsExpired: state.isApplePnsExpired,
|
|
isVppExpired: state.isVppExpired,
|
|
needsAbmTermsRenewal: state.needsAbmTermsRenewal,
|
|
willAppleBmExpire: state.willAppleBmExpire,
|
|
willApplePnsExpire: state.willApplePnsExpire,
|
|
willVppExpire: state.willVppExpire,
|
|
noSandboxHosts: state.noSandboxHosts,
|
|
filteredHostsPath: state.filteredHostsPath,
|
|
filteredSoftwarePath: state.filteredSoftwarePath,
|
|
filteredQueriesPath: state.filteredQueriesPath,
|
|
filteredPoliciesPath: state.filteredPoliciesPath,
|
|
isPreviewMode: detectPreview(),
|
|
isSandboxMode: state.isSandboxMode,
|
|
isFreeTier: state.isFreeTier,
|
|
isPremiumTier: state.isPremiumTier,
|
|
isMacMdmEnabledAndConfigured: state.isMacMdmEnabledAndConfigured,
|
|
isWindowsMdmEnabledAndConfigured: state.isWindowsMdmEnabledAndConfigured,
|
|
isAndroidMdmEnabledAndConfigured: state.isAndroidMdmEnabledAndConfigured,
|
|
isGlobalAdmin: state.isGlobalAdmin,
|
|
isGlobalMaintainer: state.isGlobalMaintainer,
|
|
isGlobalObserver: state.isGlobalObserver,
|
|
isOnGlobalTeam: state.isOnGlobalTeam,
|
|
isAnyTeamObserverPlus: state.isAnyTeamObserverPlus,
|
|
isAnyTeamMaintainer: state.isAnyTeamMaintainer,
|
|
isAnyTeamMaintainerOrTeamAdmin: state.isAnyTeamMaintainerOrTeamAdmin,
|
|
isTeamObserver: state.isTeamObserver,
|
|
isTeamMaintainer: state.isTeamMaintainer,
|
|
isTeamAdmin: state.isTeamAdmin,
|
|
isTeamTechnician: state.isTeamTechnician,
|
|
isAnyTeamTechnician: state.isAnyTeamTechnician,
|
|
isGlobalTechnician: state.isGlobalTechnician,
|
|
isTeamMaintainerOrTeamAdmin: state.isTeamMaintainerOrTeamAdmin,
|
|
isAnyTeamAdmin: state.isAnyTeamAdmin,
|
|
isOnlyObserver: state.isOnlyObserver,
|
|
isObserverPlus: state.isObserverPlus,
|
|
isNoAccess: state.isNoAccess,
|
|
isAnyMaintainerAdminObserverPlus:
|
|
state.isGlobalAdmin ||
|
|
state.isGlobalMaintainer ||
|
|
state.isAnyTeamAdmin ||
|
|
state.isAnyTeamMaintainer ||
|
|
state.isObserverPlus ||
|
|
state.isAnyTeamObserverPlus,
|
|
setAvailableTeams: (
|
|
user: IUser | null,
|
|
availableTeams: ITeamSummary[]
|
|
) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_AVAILABLE_TEAMS,
|
|
user,
|
|
availableTeams,
|
|
});
|
|
},
|
|
setUserSettings: (userSettings: IUserSettings) => {
|
|
dispatch({ type: ACTIONS.SET_USER_SETTINGS, userSettings });
|
|
},
|
|
setCurrentUser: (currentUser: IUser) => {
|
|
dispatch({ type: ACTIONS.SET_CURRENT_USER, currentUser });
|
|
},
|
|
setCurrentTeam: (currentTeam: ITeamSummary | undefined) => {
|
|
dispatch({ type: ACTIONS.SET_CURRENT_TEAM, currentTeam });
|
|
},
|
|
setConfig: (config: IConfig) => {
|
|
dispatch({ type: ACTIONS.SET_CONFIG, config });
|
|
},
|
|
setEnrollSecret: (enrollSecret: IEnrollSecret[]) => {
|
|
dispatch({ type: ACTIONS.SET_ENROLL_SECRET, enrollSecret });
|
|
},
|
|
setAndroidEnterpriseDeleted: (isDeleted: boolean) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_ANDROID_ENTERPRISE_DELETED,
|
|
isDeleted,
|
|
});
|
|
},
|
|
setABMExpiry: (abmExpiry: IAbmExpiry) => {
|
|
dispatch({ type: ACTIONS.SET_ABM_EXPIRY, abmExpiry });
|
|
},
|
|
setAPNsExpiry: (apnsExpiry: string) => {
|
|
dispatch({ type: ACTIONS.SET_APNS_EXPIRY, apnsExpiry });
|
|
},
|
|
setVppExpiry: (vppExpiry: string) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_VPP_EXPIRY,
|
|
vppExpiry,
|
|
});
|
|
},
|
|
setSandboxExpiry: (sandboxExpiry: string) => {
|
|
dispatch({ type: ACTIONS.SET_SANDBOX_EXPIRY, sandboxExpiry });
|
|
},
|
|
setNoSandboxHosts: (noSandboxHosts: boolean) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_NO_SANDBOX_HOSTS,
|
|
noSandboxHosts,
|
|
});
|
|
},
|
|
setFilteredHostsPath: (filteredHostsPath: string) => {
|
|
dispatch({ type: ACTIONS.SET_FILTERED_HOSTS_PATH, filteredHostsPath });
|
|
},
|
|
setFilteredSoftwarePath: (filteredSoftwarePath: string) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_FILTERED_SOFTWARE_PATH,
|
|
filteredSoftwarePath,
|
|
});
|
|
},
|
|
setFilteredQueriesPath: (filteredQueriesPath: string) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_FILTERED_QUERIES_PATH,
|
|
filteredQueriesPath,
|
|
});
|
|
},
|
|
setFilteredPoliciesPath: (filteredPoliciesPath: string) => {
|
|
dispatch({
|
|
type: ACTIONS.SET_FILTERED_POLICIES_PATH,
|
|
filteredPoliciesPath,
|
|
});
|
|
},
|
|
}),
|
|
[
|
|
state.abmExpiry,
|
|
state.apnsExpiry,
|
|
state.availableTeams,
|
|
state.userSettings,
|
|
state.config,
|
|
state.currentTeam,
|
|
state.currentUser,
|
|
state.enrollSecret,
|
|
state.filteredHostsPath,
|
|
state.filteredPoliciesPath,
|
|
state.filteredQueriesPath,
|
|
state.filteredSoftwarePath,
|
|
state.isAnyTeamAdmin,
|
|
state.isAnyTeamMaintainer,
|
|
state.isAnyTeamMaintainerOrTeamAdmin,
|
|
state.isAnyTeamObserverPlus,
|
|
state.isAndroidEnterpriseDeleted,
|
|
state.isAppleBmExpired,
|
|
state.isApplePnsExpired,
|
|
state.isFreeTier,
|
|
state.isGlobalAdmin,
|
|
state.isGlobalMaintainer,
|
|
state.isGlobalObserver,
|
|
state.isMacMdmEnabledAndConfigured,
|
|
state.isNoAccess,
|
|
state.isObserverPlus,
|
|
state.isOnGlobalTeam,
|
|
state.isOnlyObserver,
|
|
state.isPremiumTier,
|
|
state.isSandboxMode,
|
|
state.isTeamAdmin,
|
|
state.isTeamTechnician,
|
|
state.isAnyTeamTechnician,
|
|
state.isGlobalTechnician,
|
|
state.isTeamMaintainer,
|
|
state.isTeamMaintainerOrTeamAdmin,
|
|
state.isTeamObserver,
|
|
state.isVppExpired,
|
|
state.isWindowsMdmEnabledAndConfigured,
|
|
state.isAndroidMdmEnabledAndConfigured,
|
|
state.needsAbmTermsRenewal,
|
|
state.noSandboxHosts,
|
|
state.sandboxExpiry,
|
|
state.vppExpiry,
|
|
state.willAppleBmExpire,
|
|
state.willApplePnsExpire,
|
|
state.willVppExpire,
|
|
]
|
|
);
|
|
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
|
|
};
|
|
|
|
export default AppProvider;
|