Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions apps/teams-test-app/src/components/IntuneAPIs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { intune } from '@microsoft/teams-js';
import React, { ReactElement } from 'react';

import { ApiWithoutInput, ApiWithTextInput } from './utils';
import { ModuleWrapper } from './utils/ModuleWrapper';

const CheckIntuneCapability = (): React.ReactElement =>
ApiWithoutInput({
name: 'checkIntuneCapability',
title: 'Check Intune Capability',
onClick: async () => `Intune module ${intune.isSupported() ? 'is' : 'is not'} supported`,
});

const IsSaveToLocationAllowed = (): React.ReactElement =>
ApiWithTextInput<string>({
name: 'isSaveToLocationAllowed',
title: 'Is Save To Location Allowed',
onClick: async (input) => {
const location = input as intune.SaveLocation;
const result = await intune.isSaveToLocationAllowed(location);
return `Save to ${input}: ${result ? 'Allowed' : 'Not Allowed'}`;
},
defaultInput: JSON.stringify(intune.SaveLocation.LOCAL),
});

const IsOpenFromLocationAllowed = (): React.ReactElement =>
ApiWithTextInput<string>({
name: 'isOpenFromLocationAllowed',
title: 'Is Open From Location Allowed',
onClick: async (input) => {
const location = input as intune.OpenLocation;
const result = await intune.isOpenFromLocationAllowed(location);
return `Open from ${input}: ${result ? 'Allowed' : 'Not Allowed'}`;
},
defaultInput: JSON.stringify(intune.OpenLocation.LOCAL),
});

const IntuneAPIs = (): ReactElement => (
<ModuleWrapper title="Intune">
<CheckIntuneCapability />
<IsSaveToLocationAllowed />
<IsOpenFromLocationAllowed />
</ModuleWrapper>
);

export default IntuneAPIs;
2 changes: 2 additions & 0 deletions apps/teams-test-app/src/pages/TestApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import DialogUrlBotAPIs from '../components/DialogUrlBotAPIs';
import DialogUrlParentCommunicationAPIs from '../components/DialogUrlParentCommunicationAPIs';
import GeoLocationAPIs from '../components/GeoLocationAPIs';
import HostEntityTabAPIs from '../components/HostEntityTabAPIs';
import IntuneAPIs from '../components/IntuneAPIs';
import Links from '../components/Links';
import LocationAPIs from '../components/LocationAPIs';
import LogAPIs from '../components/LogsAPIs';
Expand Down Expand Up @@ -135,6 +136,7 @@ export const TestApp: React.FC = () => {
{ name: 'FullTrustAPIs', component: <FullTrustAPIs /> },
{ name: 'GeoLocationAPIs', component: <GeoLocationAPIs /> },
{ name: 'HostEntityTabAPIs', component: <HostEntityTabAPIs /> },
{ name: 'IntuneAPIs', component: <IntuneAPIs /> },
{ name: 'Links', component: <Links /> },
{ name: 'LocationAPIs', component: <LocationAPIs /> },
{ name: 'LogAPIs', component: <LogAPIs /> },
Expand Down
2 changes: 2 additions & 0 deletions packages/teams-js/src/internal/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ export const enum ApiName {
Interactive_GetNtpTime = 'interactive.getNtpTime',
Interactive_RegisterClientId = 'interactive.registerClientId',
Interactive_SetFluidContainerId = 'interactive.setFluidContainerId',
Intune_IsSaveToLocationAllowed = 'intune.isSaveToLocationAllowed',
Intune_IsOpenFromLocationAllowed = 'intune.isOpenFromLocationAllowed',
Location_GetLocation = 'location.getLocation',
Location_ShowLocation = 'location.showLocation',
Logs_Receive = 'log.receive',
Expand Down
1 change: 1 addition & 0 deletions packages/teams-js/src/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export {
} from './appWindow';
export * as menus from './menus';
export * as media from './media';
export * as intune from './intune';
export * as secondaryBrowser from './secondaryBrowser';
export * as location from './location';
export * as meeting from './meeting/meeting';
Expand Down
137 changes: 137 additions & 0 deletions packages/teams-js/src/public/intune.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Intune Mobile Application Management (MAM) policy APIs.
*
* These APIs allow MOS apps to query Intune MAM policy decisions
* for UX purposes (e.g., disabling a "Save" button when the policy
* disallows saving to a given location).
*
* Security note:
* - These APIs are NOT a security boundary.
* - All enforcement MUST happen in native HubSDK / host code paths.
* - Policy values can change while the app is running; consumers should
* call policy APIs immediately before executing the related action.
*
* @beta
* @module
*/

import { sendAndHandleSdkError } from '../internal/communication';
import { ensureInitialized } from '../internal/internalAPIs';
import { ApiName, ApiVersionNumber, getApiVersionTag } from '../internal/telemetry';
import { errorNotSupportedOnPlatform, FrameContexts } from './constants';
import { runtime } from './runtime';

/**
* v2 APIs telemetry file: All of APIs in this capability file should send out API version v2 ONLY
*/
const intuneTelemetryVersionNumber: ApiVersionNumber = ApiVersionNumber.V_2;

/**
* Locations to which organizational data may be saved.
* Equivalent to MAM SDK SaveLocation (Android) / IntuneMAMSaveLocation (iOS).
*/
export enum SaveLocation {
/** OneDrive for Business */
ONEDRIVE_FOR_BUSINESS = 'ONEDRIVE_FOR_BUSINESS',
/** SharePoint */
SHAREPOINT = 'SHAREPOINT',
/** Box */
BOX = 'BOX',
/** Dropbox */
DROPBOX = 'DROPBOX',
/** Google Drive */
GOOGLE_DRIVE = 'GOOGLE_DRIVE',
/** Local device storage */
LOCAL = 'LOCAL',
/** Account document storage */
ACCOUNT_DOCUMENT = 'ACCOUNT_DOCUMENT',
/** Device photo library */
PHOTO_LIBRARY = 'PHOTO_LIBRARY',
/** Other / unrecognized location */
OTHER = 'OTHER',
}

/**
* Locations from which data may be opened/imported into the app.
* Equivalent to MAM SDK OpenLocation (Android) / IntuneMAMOpenLocation (iOS).
*/
export enum OpenLocation {
/** OneDrive for Business */
ONEDRIVE_FOR_BUSINESS = 'ONEDRIVE_FOR_BUSINESS',
/** SharePoint */
SHAREPOINT = 'SHAREPOINT',
/** Device camera */
CAMERA = 'CAMERA',
/** Local device storage */
LOCAL = 'LOCAL',
/** Account document storage */
ACCOUNT_DOCUMENT = 'ACCOUNT_DOCUMENT',
/** Device photo library */
PHOTO_LIBRARY = 'PHOTO_LIBRARY',
/** Other / unrecognized location */
OTHER = 'OTHER',
}

/**
* Checks whether saving organizational data to the specified location
* is allowed by the current Intune MAM policy.
*
* This API is intended for app UX decisions only.
* Native enforcement MUST be performed by HubSDK / host.
*
* @param saveLocation - The target save location to check against policy.
* @returns true if saving to the location is allowed, false otherwise.
*
* @throws Error if {@linkcode app.initialize} has not successfully completed
*
* @beta
*/
export async function isSaveToLocationAllowed(saveLocation: SaveLocation): Promise<boolean> {
ensureInitialized(runtime, FrameContexts.content, FrameContexts.task);
if (!isSupported()) {
throw errorNotSupportedOnPlatform;
}
return sendAndHandleSdkError(
getApiVersionTag(intuneTelemetryVersionNumber, ApiName.Intune_IsSaveToLocationAllowed),
'intune.isSaveToLocationAllowed',
saveLocation,
);
}

/**
* Checks whether opening/importing data from the specified location
* is allowed by the current Intune MAM policy.
*
* This API is intended for app UX decisions only.
* Native enforcement MUST be performed by HubSDK / host.
*
* @param openLocation - The source location to check against policy.
* @returns true if opening from the location is allowed, false otherwise.
*
* @throws Error if {@linkcode app.initialize} has not successfully completed
*
* @beta
*/
export async function isOpenFromLocationAllowed(openLocation: OpenLocation): Promise<boolean> {
ensureInitialized(runtime, FrameContexts.content, FrameContexts.task);
if (!isSupported()) {
throw errorNotSupportedOnPlatform;
}
return sendAndHandleSdkError(
getApiVersionTag(intuneTelemetryVersionNumber, ApiName.Intune_IsOpenFromLocationAllowed),
'intune.isOpenFromLocationAllowed',
openLocation,
);
}

/**
* Checks if the Intune MAM capability is supported by the host.
* @returns boolean to represent whether the Intune capability is supported
*
* @throws Error if {@linkcode app.initialize} has not successfully completed
*
* @beta
*/
export function isSupported(): boolean {
return ensureInitialized(runtime) && runtime.supports.intune ? true : false;
}
4 changes: 4 additions & 0 deletions packages/teams-js/src/public/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ interface IRuntimeV1 extends IBaseRuntime {
readonly geoLocation?: {
readonly map?: {};
};
readonly intune?: {};
readonly location?: {};
readonly logs?: {};
readonly mail?: {};
Expand Down Expand Up @@ -107,6 +108,7 @@ interface IRuntimeV2 extends IBaseRuntime {
readonly map?: {};
};
readonly interactive?: {};
readonly intune?: {};
readonly secondaryBrowser?: {};
readonly location?: {};
readonly logs?: {};
Expand Down Expand Up @@ -174,6 +176,7 @@ interface IRuntimeV3 extends IBaseRuntime {
readonly map?: {};
};
readonly interactive?: {};
readonly intune?: {};
readonly secondaryBrowser?: {};
readonly location?: {};
readonly logs?: {};
Expand Down Expand Up @@ -266,6 +269,7 @@ interface IRuntimeV4 extends IBaseRuntime {
readonly tab?: {};
};
readonly interactive?: {};
readonly intune?: {};
readonly secondaryBrowser?: {};
readonly location?: {};
readonly logs?: {};
Expand Down
Loading
Loading