ppapi integration for site provision
This commit is contained in:
Родитель
6cf4756759
Коммит
c9f6660c4a
|
@ -20,6 +20,9 @@ import { v4 as uuidv4 } from 'uuid';
|
|||
import { ITelemetry } from '../../OneDSLoggerTelemetry/telemetry/ITelemetry';
|
||||
import { orgChangeErrorEvent, orgChangeEvent } from '../../../client/OrgChangeNotifier';
|
||||
import { createSite } from './site-creation/PowerPagesCreateSite';
|
||||
import { ArtemisService } from '../../services/ArtemisService';
|
||||
import { ServiceEndpointCategory } from '../../services/Constants';
|
||||
import { PPAPIService } from '../../services/PPAPIService';
|
||||
|
||||
export class PowerPagesChatParticipant {
|
||||
private static instance: PowerPagesChatParticipant | null = null;
|
||||
|
@ -31,6 +34,7 @@ export class PowerPagesChatParticipant {
|
|||
private readonly _disposables: vscode.Disposable[] = [];
|
||||
private cachedEndpoint: IIntelligenceAPIEndpointInformation | null = null;
|
||||
private powerPagesAgentSessionId: string;
|
||||
private serviceEndpointStamp: ServiceEndpointCategory | undefined;
|
||||
|
||||
private orgID: string | undefined;
|
||||
private orgUrl: string | undefined;
|
||||
|
@ -145,6 +149,20 @@ export class PowerPagesChatParticipant {
|
|||
switch (request.command) {
|
||||
case 'create-site': {
|
||||
stream.progress('Generating a new Power Pages site...');
|
||||
|
||||
const artemisResponse = await ArtemisService.getArtemisResponse(this.orgID, this.telemetry, this.powerPagesAgentSessionId);
|
||||
|
||||
if (!artemisResponse) {
|
||||
stream.markdown('Failed to get the Artemis response. Please try again later.');
|
||||
return {
|
||||
metadata: {
|
||||
command: ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.serviceEndpointStamp = artemisResponse.stamp;
|
||||
|
||||
try {
|
||||
const result = await createSite(
|
||||
intelligenceAPIEndpointInfo.intelligenceEndpoint,
|
||||
|
@ -155,13 +173,29 @@ export class PowerPagesChatParticipant {
|
|||
stream,
|
||||
this.telemetry
|
||||
);
|
||||
stream.markdown(`Site created successfully with portal:`);
|
||||
console.log(result);
|
||||
return {
|
||||
metadata: {
|
||||
command: 'create-site',
|
||||
}
|
||||
};
|
||||
|
||||
if(!result) {
|
||||
stream.markdown('Failed to create the site. Please try again later.');
|
||||
return {
|
||||
metadata: {
|
||||
command: ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
await PPAPIService.createWebsite(this.serviceEndpointStamp, this.environmentID, this.orgID, result.siteName, 1033, result.websiteId, this.telemetry);
|
||||
|
||||
const websiteResponse = await PPAPIService.getWebsiteDetailsById(this.serviceEndpointStamp, this.environmentID, result.websiteId, this.telemetry);
|
||||
|
||||
if(websiteResponse) {
|
||||
stream.markdown(`Site created successfully with portal: ${websiteResponse.websiteUrl}`);
|
||||
return {
|
||||
metadata: {
|
||||
command: 'create-site',
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
stream.markdown('Failed to create the site. Please try again later.');
|
||||
return {
|
||||
|
@ -171,6 +205,7 @@ export class PowerPagesChatParticipant {
|
|||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
// case 'create-site': {
|
||||
// //TODO: Update the strings
|
||||
// stream.progress('Generating a new Power Pages site...');
|
||||
|
|
|
@ -8,56 +8,52 @@ import { COPILOT_UNAVAILABLE } from "../copilot/constants";
|
|||
import { ITelemetry } from "../OneDSLoggerTelemetry/telemetry/ITelemetry";
|
||||
import { sendTelemetryEvent } from "../copilot/telemetry/copilotTelemetry";
|
||||
import { CopilotArtemisFailureEvent, CopilotArtemisSuccessEvent } from "../copilot/telemetry/telemetryConstants";
|
||||
import { BAPServiceStamp as BAPAPIEndpointStamp } from "./Constants";
|
||||
import { IArtemisAPIOrgResponse, IArtemisServiceEndpointInformation, IIntelligenceAPIEndpointInformation } from "./Interfaces";
|
||||
import { ServiceEndpointCategory } from "./Constants";
|
||||
import { IArtemisAPIOrgResponse, IArtemisServiceEndpointInformation, IArtemisServiceResponse, IIntelligenceAPIEndpointInformation } from "./Interfaces";
|
||||
import { isCopilotDisabledInGeo, isCopilotSupportedInGeo } from "../copilot/utils/copilotUtil";
|
||||
import { BAPService } from "./BAPService";
|
||||
|
||||
export class ArtemisService {
|
||||
public static async getIntelligenceEndpoint(orgId: string, telemetry: ITelemetry, sessionID: string, environmentId: string): Promise<IIntelligenceAPIEndpointInformation> {
|
||||
|
||||
const artemisResponses = await ArtemisService.fetchArtemisResponse(orgId, telemetry, sessionID);
|
||||
const artemisResponse = await ArtemisService.getArtemisResponse(orgId, telemetry, sessionID);
|
||||
|
||||
if (artemisResponses === null || artemisResponses.length === 0) {
|
||||
if (artemisResponse === null) {
|
||||
return { intelligenceEndpoint: null, geoName: null, crossGeoDataMovementEnabledPPACFlag: false };
|
||||
}
|
||||
const { geoName, environment, clusterNumber } = artemisResponse.response as unknown as IArtemisAPIOrgResponse;
|
||||
sendTelemetryEvent(telemetry, { eventName: CopilotArtemisSuccessEvent, copilotSessionId: sessionID, geoName: String(geoName), orgId: orgId });
|
||||
|
||||
const artemisResponse = artemisResponses[0];
|
||||
if (artemisResponse !== null) {
|
||||
const { geoName, environment, clusterNumber } = artemisResponse.response as unknown as IArtemisAPIOrgResponse;
|
||||
const endpointStamp = artemisResponse.stamp;
|
||||
sendTelemetryEvent(telemetry, { eventName: CopilotArtemisSuccessEvent, copilotSessionId: sessionID, geoName: String(geoName), orgId: orgId });
|
||||
const crossGeoDataMovementEnabledPPACFlag = await BAPService.getCrossGeoCopilotDataMovementEnabledFlag(artemisResponse.stamp, telemetry, environmentId);
|
||||
|
||||
const crossGeoDataMovementEnabledPPACFlag = await BAPService.getCrossGeoCopilotDataMovementEnabledFlag(artemisResponse.stamp, telemetry, environmentId);
|
||||
|
||||
if (isCopilotDisabledInGeo().includes(geoName)) {
|
||||
return { intelligenceEndpoint: COPILOT_UNAVAILABLE, geoName: geoName, crossGeoDataMovementEnabledPPACFlag: crossGeoDataMovementEnabledPPACFlag };
|
||||
}
|
||||
else if (crossGeoDataMovementEnabledPPACFlag === true) {
|
||||
// Do nothing - we can make this call cross geo
|
||||
}
|
||||
else if (!isCopilotSupportedInGeo().includes(geoName)) {
|
||||
return { intelligenceEndpoint: COPILOT_UNAVAILABLE, geoName: geoName, crossGeoDataMovementEnabledPPACFlag: crossGeoDataMovementEnabledPPACFlag };
|
||||
}
|
||||
|
||||
const intelligenceEndpoint = `https://aibuildertextapiservice.${geoName}-${'il' + clusterNumber}.gateway.${environment}.island.powerapps.com/v1.0/${orgId}/appintelligence/chat`
|
||||
|
||||
return { intelligenceEndpoint: intelligenceEndpoint, geoName: geoName, crossGeoDataMovementEnabledPPACFlag: crossGeoDataMovementEnabledPPACFlag, endpointStamp: endpointStamp };
|
||||
if (isCopilotDisabledInGeo().includes(geoName)) {
|
||||
return { intelligenceEndpoint: COPILOT_UNAVAILABLE, geoName: geoName, crossGeoDataMovementEnabledPPACFlag: crossGeoDataMovementEnabledPPACFlag };
|
||||
}
|
||||
else if (crossGeoDataMovementEnabledPPACFlag === true) {
|
||||
// Do nothing - we can make this call cross geo
|
||||
}
|
||||
else if (!isCopilotSupportedInGeo().includes(geoName)) {
|
||||
return { intelligenceEndpoint: COPILOT_UNAVAILABLE, geoName: geoName, crossGeoDataMovementEnabledPPACFlag: crossGeoDataMovementEnabledPPACFlag };
|
||||
}
|
||||
|
||||
return { intelligenceEndpoint: null, geoName: null, crossGeoDataMovementEnabledPPACFlag: false };
|
||||
const intelligenceEndpoint = `https://aibuildertextapiservice.${geoName}-${'il' + clusterNumber}.gateway.${environment}.island.powerapps.com/v1.0/${orgId}/appintelligence/chat`
|
||||
|
||||
return { intelligenceEndpoint: intelligenceEndpoint, geoName: geoName, crossGeoDataMovementEnabledPPACFlag: crossGeoDataMovementEnabledPPACFlag };
|
||||
}
|
||||
|
||||
// Function to fetch Artemis response
|
||||
public static async fetchArtemisResponse(orgId: string, telemetry: ITelemetry, sessionID = '') {
|
||||
public static async getArtemisResponse(orgId: string, telemetry: ITelemetry, sessionID: string): Promise<IArtemisServiceResponse | null> {
|
||||
const endpointDetails = ArtemisService.convertGuidToUrls(orgId);
|
||||
const artemisResponses = await ArtemisService.fetchIslandInfo(endpointDetails, telemetry, sessionID);
|
||||
|
||||
const artemisResponse = await ArtemisService.fetchIslandInfo(endpointDetails, telemetry, sessionID);
|
||||
if (artemisResponses === null || artemisResponses.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return artemisResponse;
|
||||
return artemisResponses[0];
|
||||
}
|
||||
|
||||
static async fetchIslandInfo(endpointDetails: IArtemisServiceEndpointInformation[], telemetry: ITelemetry, sessionID: string) {
|
||||
static async fetchIslandInfo(endpointDetails: IArtemisServiceEndpointInformation[], telemetry: ITelemetry, sessionID: string): Promise<IArtemisServiceResponse[] | null> {
|
||||
|
||||
const requestInit: RequestInit = {
|
||||
method: 'GET',
|
||||
|
@ -71,7 +67,7 @@ export class ArtemisService {
|
|||
if (!response.ok) {
|
||||
throw new Error('Request failed');
|
||||
}
|
||||
return { stamp: endpointDetail.stamp, response: await response.json() };
|
||||
return { stamp: endpointDetail.stamp, response: await response.json() as IArtemisAPIOrgResponse };
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
|
@ -79,14 +75,13 @@ export class ArtemisService {
|
|||
|
||||
const results = await Promise.all(promises);
|
||||
const successfulResponses = results.filter(result => result !== null && result.response !== null);
|
||||
return successfulResponses;
|
||||
return successfulResponses as IArtemisServiceResponse[];
|
||||
} catch (error) {
|
||||
sendTelemetryEvent(telemetry, { eventName: CopilotArtemisFailureEvent, copilotSessionId: sessionID, error: error as Error })
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param orgId
|
||||
* @returns urls
|
||||
|
@ -110,13 +105,13 @@ export class ArtemisService {
|
|||
const dodUrl = `https://${domain}.${nonProdSegment}.organization.api.appsplatform.us/gateway/cluster?app-version=1`;
|
||||
|
||||
return [
|
||||
{ stamp: BAPAPIEndpointStamp.TEST, endpoint: tstUrl },
|
||||
{ stamp: BAPAPIEndpointStamp.PREPROD, endpoint: preprodUrl },
|
||||
{ stamp: BAPAPIEndpointStamp.PROD, endpoint: prodUrl },
|
||||
{ stamp: BAPAPIEndpointStamp.GCC, endpoint: gccUrl },
|
||||
{ stamp: BAPAPIEndpointStamp.HIGH, endpoint: highUrl },
|
||||
{ stamp: BAPAPIEndpointStamp.MOONCAKE, endpoint: mooncakeUrl },
|
||||
{ stamp: BAPAPIEndpointStamp.DOD, endpoint: dodUrl },
|
||||
{ stamp: ServiceEndpointCategory.TEST, endpoint: tstUrl },
|
||||
{ stamp: ServiceEndpointCategory.PREPROD, endpoint: preprodUrl },
|
||||
{ stamp: ServiceEndpointCategory.PROD, endpoint: prodUrl },
|
||||
{ stamp: ServiceEndpointCategory.GCC, endpoint: gccUrl },
|
||||
{ stamp: ServiceEndpointCategory.HIGH, endpoint: highUrl },
|
||||
{ stamp: ServiceEndpointCategory.MOONCAKE, endpoint: mooncakeUrl },
|
||||
{ stamp: ServiceEndpointCategory.DOD, endpoint: dodUrl },
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ import {
|
|||
VSCODE_EXTENSION_GRAPH_CLIENT_AUTHENTICATION_COMPLETED,
|
||||
VSCODE_EXTENSION_BAP_SERVICE_AUTHENTICATION_COMPLETED,
|
||||
VSCODE_EXTENSION_BAP_SERVICE_AUTHENTICATION_FAILED,
|
||||
VSCODE_EXTENSION_DECODE_JWT_TOKEN_FAILED
|
||||
VSCODE_EXTENSION_DECODE_JWT_TOKEN_FAILED,
|
||||
VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_FAILED,
|
||||
VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_COMPLETED
|
||||
} from "./TelemetryConstants";
|
||||
import { ERROR_CONSTANTS } from "../ErrorConstants";
|
||||
import { BAP_SERVICE_SCOPE_DEFAULT, INTELLIGENCE_SCOPE_DEFAULT, PROVIDER_ID, SCOPE_OPTION_CONTACTS_READ, SCOPE_OPTION_DEFAULT, SCOPE_OPTION_OFFLINE_ACCESS, SCOPE_OPTION_USERS_READ_BASIC_ALL } from "./Constants";
|
||||
|
@ -292,3 +294,57 @@ export function getOIDFromToken(token: string, telemetry: ITelemetry) {
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
export async function powerPlatformAPIAuthentication(
|
||||
telemetry: ITelemetry,
|
||||
ppapiEndpoint: string,
|
||||
firstTimeAuth = false
|
||||
): Promise<string> {
|
||||
let accessToken = "";
|
||||
try {
|
||||
//https://api.preprod.powerplatform.com/powerpages/environments/1538a5fc-6583-ef69-8a14-99808eaa981a/websites?api-version=2022-03-01-preview
|
||||
//get the endpoint till .com
|
||||
ppapiEndpoint = ppapiEndpoint.split("/powerpages")[0];
|
||||
const PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT = `${ppapiEndpoint}${SCOPE_OPTION_DEFAULT}`;
|
||||
let session = await vscode.authentication.getSession(
|
||||
PROVIDER_ID,
|
||||
[PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT],
|
||||
{ silent: true }
|
||||
);
|
||||
|
||||
if (!session) {
|
||||
session = await vscode.authentication.getSession(
|
||||
PROVIDER_ID,
|
||||
[PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT],
|
||||
{ createIfNone: true }
|
||||
);
|
||||
}
|
||||
|
||||
accessToken = session?.accessToken ?? "";
|
||||
if (!accessToken) {
|
||||
throw new Error(ERROR_CONSTANTS.NO_ACCESS_TOKEN);
|
||||
}
|
||||
|
||||
if (firstTimeAuth) {
|
||||
sendTelemetryEvent(telemetry, {
|
||||
eventName: VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_COMPLETED,
|
||||
userId:
|
||||
session?.account.id.split("/").pop() ??
|
||||
session?.account.id ??
|
||||
"",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorDialog(
|
||||
vscode.l10n.t(
|
||||
"Authorization Failed. Please run again to authorize it"
|
||||
),
|
||||
vscode.l10n.t("There was a permissions problem with the server")
|
||||
);
|
||||
sendTelemetryEvent(telemetry,
|
||||
{ eventName: VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_FAILED, errorMsg: (error as Error).message }
|
||||
)
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
import { ITelemetry } from "../OneDSLoggerTelemetry/telemetry/ITelemetry";
|
||||
import { bapServiceAuthentication, getCommonHeaders } from "./AuthenticationProvider";
|
||||
import { VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_COMPLETED, VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED } from "./TelemetryConstants";
|
||||
import { BAPServiceStamp, BAP_API_VERSION, BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL, BAP_SERVICE_ENDPOINT } from "./Constants";
|
||||
import { BAP_API_VERSION, BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL, BAP_SERVICE_ENDPOINT, ServiceEndpointCategory } from "./Constants";
|
||||
import { sendTelemetryEvent } from "../copilot/telemetry/copilotTelemetry";
|
||||
import { getBAPEndpoint } from "../utilities/Utils";
|
||||
|
||||
export class BAPService {
|
||||
public static async getCrossGeoCopilotDataMovementEnabledFlag(serviceEndpointStamp: BAPServiceStamp, telemetry: ITelemetry, environmentId: string): Promise<boolean> {
|
||||
public static async getCrossGeoCopilotDataMovementEnabledFlag(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry, environmentId: string): Promise<boolean> {
|
||||
|
||||
try {
|
||||
const accessToken = await bapServiceAuthentication(telemetry, true);
|
||||
|
@ -34,7 +34,7 @@ export class BAPService {
|
|||
return false;
|
||||
}
|
||||
|
||||
static async getBAPCopilotCrossGeoFlagEndpoint(serviceEndpointStamp: BAPServiceStamp, telemetry: ITelemetry, environmentId: string): Promise<string> {
|
||||
static async getBAPCopilotCrossGeoFlagEndpoint(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry, environmentId: string): Promise<string> {
|
||||
|
||||
const bapEndpoint = await getBAPEndpoint(serviceEndpointStamp, telemetry);
|
||||
|
||||
|
|
|
@ -12,13 +12,20 @@ export const SCOPE_OPTION_CONTACTS_READ = "Contacts.Read";
|
|||
export const SCOPE_OPTION_USERS_READ_BASIC_ALL = "User.ReadBasic.All";
|
||||
export const SCOPE_OPTION_DEFAULT = "/.default";
|
||||
|
||||
// BAP API constants
|
||||
export const BAP_API_VERSION = '2021-04-01';
|
||||
export const BAP_SERVICE_SCOPE_DEFAULT = "https://api.bap.microsoft.com/.default";//"https://management.core.windows.net/.default";
|
||||
export const BAP_SERVICE_SCOPE_DEFAULT = "https://api.bap.microsoft.com/.default";
|
||||
export const BAP_SERVICE_ENDPOINT = `{rootURL}/providers/Microsoft.BusinessAppPlatform/`;
|
||||
export const BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL = `scopes/admin/environments/{environmentID}?$expand=properties/copilotPolicies&api-version={apiVersion}`;
|
||||
export const BAP_ENVIRONMENT_LIST_URL = `scopes/admin/environments?api-version=2021-04-01&select=name,properties.displayName,properties.linkedEnvironmentMetadata`;
|
||||
|
||||
export enum BAPServiceStamp {
|
||||
// PPAPI constants
|
||||
export const PPAPI_WEBSITES_API_VERSION = '2022-03-01-preview';
|
||||
export const PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT = "https://api.powerplatform.com/.default";
|
||||
export const PPAPI_WEBSITES_ENDPOINT = `{rootURL}/powerpages/environments/{environmentId}/websites`;
|
||||
|
||||
export enum ServiceEndpointCategory {
|
||||
NONE = "",
|
||||
TEST = "test",
|
||||
PREPROD = "preprod",
|
||||
PROD = "prod",
|
||||
|
@ -27,3 +34,8 @@ export enum BAPServiceStamp {
|
|||
MOONCAKE = "mooncake",
|
||||
DOD = "dod",
|
||||
}
|
||||
|
||||
export enum WebsiteApplicationType {
|
||||
Production = "Production",
|
||||
Trial = "Trial",
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { BAPServiceStamp } from "./Constants";
|
||||
import { ServiceEndpointCategory, WebsiteApplicationType } from "./Constants";
|
||||
|
||||
export interface IArtemisServiceEndpointInformation {
|
||||
stamp: BAPServiceStamp;
|
||||
stamp: ServiceEndpointCategory;
|
||||
endpoint: string;
|
||||
}
|
||||
|
||||
export interface IArtemisServiceResponse {
|
||||
stamp: BAPServiceStamp;
|
||||
stamp: ServiceEndpointCategory;
|
||||
response: IArtemisAPIOrgResponse;
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,25 @@ export interface IArtemisAPIOrgResponse {
|
|||
clusterType: string,
|
||||
}
|
||||
|
||||
export interface IArtemisServiceResponse {
|
||||
stamp: ServiceEndpointCategory;
|
||||
response: IArtemisAPIOrgResponse;
|
||||
}
|
||||
|
||||
export interface IIntelligenceAPIEndpointInformation {
|
||||
intelligenceEndpoint: string | null,
|
||||
geoName: string | null,
|
||||
crossGeoDataMovementEnabledPPACFlag: boolean,
|
||||
endpointStamp?: BAPServiceStamp
|
||||
crossGeoDataMovementEnabledPPACFlag: boolean
|
||||
}
|
||||
|
||||
export interface IWebsiteDetails {
|
||||
websiteUrl: string;
|
||||
dataverseInstanceUrl: string;
|
||||
dataverseOrganizationId: string;
|
||||
environmentId: string;
|
||||
id: string;
|
||||
siteVisibility: string;
|
||||
tenantId: string;
|
||||
websiteRecordId: string;
|
||||
type: WebsiteApplicationType;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ITelemetry } from "../OneDSLoggerTelemetry/telemetry/ITelemetry";
|
||||
import { getCommonHeaders, powerPlatformAPIAuthentication } from "./AuthenticationProvider";
|
||||
import { VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED, VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION, VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_COMPLETED, VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_FAILED, VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED } from "./TelemetryConstants";
|
||||
import { ServiceEndpointCategory, PPAPI_WEBSITES_ENDPOINT, PPAPI_WEBSITES_API_VERSION } from "./Constants";
|
||||
import { sendTelemetryEvent } from "../copilot/telemetry/copilotTelemetry";
|
||||
import { IWebsiteDetails } from "./Interfaces";
|
||||
|
||||
export class PPAPIService {
|
||||
public static async getWebsiteDetailsById(serviceEndpointStamp: ServiceEndpointCategory, environmentId: string, websitePreviewId: string, telemetry: ITelemetry): Promise<IWebsiteDetails | null> { // websitePreviewId aka portalId
|
||||
|
||||
try {
|
||||
const ppapiEndpoint = await PPAPIService.getPPAPIServiceEndpoint(serviceEndpointStamp, telemetry, environmentId);
|
||||
const accessToken = await powerPlatformAPIAuthentication(telemetry, ppapiEndpoint, true);
|
||||
const response = await fetch(ppapiEndpoint, {
|
||||
method: 'GET',
|
||||
headers: getCommonHeaders(accessToken)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const websiteDetails = await response.json() as unknown as IWebsiteDetails;
|
||||
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED, orgUrl: websiteDetails.dataverseInstanceUrl });
|
||||
return websiteDetails;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED, errorMsg: (error as Error).message });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async createWebsite(serviceEndpointStamp: ServiceEndpointCategory,
|
||||
environmentId: string,
|
||||
orgId: string,
|
||||
websiteName: string,
|
||||
websiteLanguage: number,
|
||||
websiteId: string,
|
||||
telemetry: ITelemetry) { // websitePreviewId aka portalId
|
||||
|
||||
const ppapiEndpoint = await PPAPIService.getPPAPIServiceEndpoint(serviceEndpointStamp, telemetry, environmentId);
|
||||
console.log(ppapiEndpoint);
|
||||
|
||||
try {
|
||||
console.log("Creating website");
|
||||
const accessToken = await powerPlatformAPIAuthentication(telemetry, ppapiEndpoint, true);
|
||||
const siteSuffix = websiteId;
|
||||
websiteName = websiteName.replace(/\s+/g, '-'); // Replace spaces with '-' in website name
|
||||
const response = await fetch(ppapiEndpoint, {
|
||||
method: 'POST',
|
||||
headers: getCommonHeaders(accessToken),
|
||||
body: JSON.stringify({
|
||||
dataverseOrganizationId: orgId,
|
||||
name: websiteName,
|
||||
selectedBaseLanguage: websiteLanguage,
|
||||
subDomain: websiteName + `-${siteSuffix.slice(siteSuffix.length - 6, siteSuffix.length)}`, // Replace spaces with '-' in website name
|
||||
templateName: "DefaultPortalTemplate",
|
||||
websiteRecordId: siteSuffix // If this ID is passed package installation is not done and portal is associated with the passed ID - we should use this option
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_COMPLETED, data: `environmentId:${environmentId}, orgId:${orgId}, websiteName:${websiteName}` });
|
||||
}
|
||||
else {
|
||||
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_FAILED, errorMsg: `Failed to create website. Response status: ${response.status}` });
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_FAILED, errorMsg: (error as Error).message });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async getPPAPIServiceEndpoint(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry, environmentId: string, websitePreviewId?: string): Promise<string> {
|
||||
|
||||
let ppapiEndpoint = "";
|
||||
|
||||
switch (serviceEndpointStamp) {
|
||||
case ServiceEndpointCategory.TEST:
|
||||
ppapiEndpoint = "https://api.test.powerplatform.com";
|
||||
break;
|
||||
case ServiceEndpointCategory.PREPROD:
|
||||
ppapiEndpoint = "https://api.preprod.powerplatform.com";
|
||||
break;
|
||||
case ServiceEndpointCategory.PROD:
|
||||
ppapiEndpoint = "https://api.powerplatform.com";
|
||||
break;
|
||||
// All below endpoints are not supported yet
|
||||
case ServiceEndpointCategory.DOD:
|
||||
case ServiceEndpointCategory.GCC:
|
||||
case ServiceEndpointCategory.HIGH:
|
||||
case ServiceEndpointCategory.MOONCAKE:
|
||||
default:
|
||||
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION, data: serviceEndpointStamp });
|
||||
break;
|
||||
}
|
||||
|
||||
return PPAPI_WEBSITES_ENDPOINT.replace("{rootURL}", ppapiEndpoint)
|
||||
.replace("{environmentId}", environmentId) +
|
||||
(websitePreviewId ? `/${websitePreviewId}` : '') +
|
||||
`?api-version=${PPAPI_WEBSITES_API_VERSION}`;
|
||||
}
|
||||
}
|
|
@ -15,7 +15,14 @@ export const VSCODE_EXTENSION_GRAPH_CLIENT_AUTHENTICATION_FAILED = "VSCodeExtens
|
|||
export const VSCODE_EXTENSION_GRAPH_CLIENT_AUTHENTICATION_COMPLETED = "VSCodeExtensionGraphClientAuthenticationCompleted";
|
||||
export const VSCODE_EXTENSION_BAP_SERVICE_AUTHENTICATION_FAILED = "VSCodeExtensionBAPServiceAuthenticationFailed";
|
||||
export const VSCODE_EXTENSION_BAP_SERVICE_AUTHENTICATION_COMPLETED = "VSCodeExtensionBAPServiceAuthenticationCompleted";
|
||||
export const VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_FAILED = "VSCodeExtensionPPAPIWebsitesAuthenticationFailed";
|
||||
export const VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_COMPLETED = "VSCodeExtensionPPAPIWebsitesAuthenticationCompleted";
|
||||
export const VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED = "VSCodeExtensionGetCrossGeoDataMovementEnabledFlagFailed";
|
||||
export const VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_COMPLETED = "VSCodeExtensionGetCrossGeoDataMovementEnabledFlagCompleted";
|
||||
export const VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION = "VSCodeExtensionGetBAPEndpointUnsupportedRegion";
|
||||
export const VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION = "VSCodeExtensionGetPPAPIWebsitesEndpointUnsupportedRegion";
|
||||
export const VSCODE_EXTENSION_DECODE_JWT_TOKEN_FAILED = "VSCodeExtensionDecodeJWTTokenFailed";
|
||||
export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED = "VSCodeExtensionPPAPIGetWebsiteByIdCompleted";
|
||||
export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_FAILED = "VSCodeExtensionPPAPIGetWebsiteByIdFailed";
|
||||
export const VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_COMPLETED = "VSCodeExtensionPPAPICreateWebsiteCompleted";
|
||||
export const VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_FAILED = "VSCodeExtensionPPAPICreateWebsiteFailed";
|
||||
|
|
|
@ -13,7 +13,7 @@ import { sendTelemetryEvent } from "../copilot/telemetry/copilotTelemetry";
|
|||
import { getDisabledOrgList, getDisabledTenantList } from "../copilot/utils/copilotUtil";
|
||||
import { CopilotNotAvailable, CopilotNotAvailableECSConfig } from "../copilot/telemetry/telemetryConstants";
|
||||
import { bapServiceAuthentication } from "../services/AuthenticationProvider";
|
||||
import { BAP_ENVIRONMENT_LIST_URL, BAP_SERVICE_ENDPOINT, BAPServiceStamp } from "../services/Constants";
|
||||
import { BAP_ENVIRONMENT_LIST_URL, BAP_SERVICE_ENDPOINT, ServiceEndpointCategory} from "../services/Constants";
|
||||
|
||||
export function getSelectedCode(editor: vscode.TextEditor): string {
|
||||
if (!editor) {
|
||||
|
@ -190,7 +190,7 @@ export function checkCopilotAvailability(
|
|||
}
|
||||
|
||||
//API call to get env list for a org
|
||||
export async function getEnvList(telemetry: ITelemetry, endpointStamp: BAPServiceStamp): Promise<{ envId: string, envDisplayName: string }[]> {
|
||||
export async function getEnvList(telemetry: ITelemetry, endpointStamp: ServiceEndpointCategory): Promise<{ envId: string, envDisplayName: string }[]> {
|
||||
const envInfo: { envId: string, envDisplayName: string }[] = [];
|
||||
try {
|
||||
const bapAuthToken = await bapServiceAuthentication(telemetry, true);
|
||||
|
@ -220,24 +220,24 @@ export async function getEnvList(telemetry: ITelemetry, endpointStamp: BAPServic
|
|||
}
|
||||
}
|
||||
|
||||
export function getBAPEndpoint(serviceEndpointStamp: BAPServiceStamp, telemetry: ITelemetry): string {
|
||||
export function getBAPEndpoint(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry): string {
|
||||
let bapEndpoint = "";
|
||||
|
||||
switch (serviceEndpointStamp) {
|
||||
case BAPServiceStamp.TEST:
|
||||
case ServiceEndpointCategory.TEST:
|
||||
bapEndpoint = "https://test.api.bap.microsoft.com";
|
||||
break;
|
||||
case BAPServiceStamp.PREPROD:
|
||||
case ServiceEndpointCategory.PREPROD:
|
||||
bapEndpoint = "https://preprod.api.bap.microsoft.com";
|
||||
break;
|
||||
case BAPServiceStamp.PROD:
|
||||
case ServiceEndpointCategory.PROD:
|
||||
bapEndpoint = "https://api.bap.microsoft.com";
|
||||
break;
|
||||
// All below endpoints are not supported yet
|
||||
case BAPServiceStamp.DOD:
|
||||
case BAPServiceStamp.GCC:
|
||||
case BAPServiceStamp.HIGH:
|
||||
case BAPServiceStamp.MOONCAKE:
|
||||
case ServiceEndpointCategory.DOD:
|
||||
case ServiceEndpointCategory.GCC:
|
||||
case ServiceEndpointCategory.HIGH:
|
||||
case ServiceEndpointCategory.MOONCAKE:
|
||||
default:
|
||||
sendTelemetryEvent(telemetry, { eventName: "VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION", data: serviceEndpointStamp });
|
||||
break;
|
||||
|
|
|
@ -650,8 +650,8 @@ function isActiveDocument(fileFsPath: string): boolean {
|
|||
}
|
||||
|
||||
async function fetchArtemisData(orgId: string): Promise<IArtemisAPIOrgResponse> {
|
||||
const artemisResponse = await ArtemisService.fetchArtemisResponse(orgId, WebExtensionContext.telemetry.getTelemetryReporter());
|
||||
if (artemisResponse === null || artemisResponse.length === 0) {
|
||||
const artemisResponse = await ArtemisService.getArtemisResponse(orgId, WebExtensionContext.telemetry.getTelemetryReporter(), "");
|
||||
if (artemisResponse === null || artemisResponse.response === null) {
|
||||
WebExtensionContext.telemetry.sendErrorTelemetry(
|
||||
webExtensionTelemetryEventNames.WEB_EXTENSION_ARTEMIS_RESPONSE_FAILED,
|
||||
fetchArtemisData.name,
|
||||
|
|
Загрузка…
Ссылка в новой задаче