From 64ac035d910717cbb2af1a8df8db7b154f86bcdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nidhi=20Tyagi=20=F0=9F=8C=9F=F0=9F=90=87=F0=9F=8C=B4?= =?UTF-8?q?=E2=9D=84=EF=B8=8F?= Date: Fri, 26 Jul 2024 15:25:23 +0530 Subject: [PATCH 1/4] [PoC] Site create command --- src/common/services/PPAPIService.ts | 43 ++++++++++++++++++++++- src/common/services/TelemetryConstants.ts | 2 ++ src/web/client/utilities/commonUtil.ts | 3 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/common/services/PPAPIService.ts b/src/common/services/PPAPIService.ts index 1b9f959a3..99d5df1d4 100644 --- a/src/common/services/PPAPIService.ts +++ b/src/common/services/PPAPIService.ts @@ -5,10 +5,11 @@ 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_GET_WEBSITE_BY_ID_COMPLETED } from "./TelemetryConstants"; +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"; +import { v4 as uuidv4 } from 'uuid' export class PPAPIService { public static async getWebsiteDetailsById(serviceEndpointStamp: ServiceEndpointCategory, environmentId: string, websitePreviewId: string, telemetry: ITelemetry): Promise { // websitePreviewId aka portalId @@ -33,6 +34,46 @@ export class PPAPIService { return null; } + public static async createWebsite(serviceEndpointStamp: ServiceEndpointCategory, + environmentId: string, + orgId: string, + websiteName: string, + websiteLanguage: number, + telemetry: ITelemetry) { // websitePreviewId aka portalId + + try { + console.log("Creating website"); + const accessToken = await powerPlatformAPIAuthentication(telemetry, true); + const siteSuffix = uuidv4(); + const response = await fetch(await PPAPIService.getPPAPIServiceEndpoint(serviceEndpointStamp, telemetry, environmentId), { + method: 'POST', + headers: getCommonHeaders(accessToken), + body: JSON.stringify({ + dataverseOrganizationId: orgId, + name: websiteName, // Add name sanitization function + selectedBaseLanguage: websiteLanguage, + subDomain: websiteName + `-${siteSuffix.slice(siteSuffix.length - 6, siteSuffix.length)}`, // Add name sanitization function + templateName: "DefaultPortalTemplate", + websiteRecordId: "" // If this ID is passed package installation is not done and portal is associated with the passed ID - we should use this option + }) + }); + + console.log(response); + + 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 { let ppapiEndpoint = ""; diff --git a/src/common/services/TelemetryConstants.ts b/src/common/services/TelemetryConstants.ts index 4d4d26404..be53bc3cb 100644 --- a/src/common/services/TelemetryConstants.ts +++ b/src/common/services/TelemetryConstants.ts @@ -24,3 +24,5 @@ export const VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION = " 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"; diff --git a/src/web/client/utilities/commonUtil.ts b/src/web/client/utilities/commonUtil.ts index 7d890fb6e..87bed8610 100644 --- a/src/web/client/utilities/commonUtil.ts +++ b/src/web/client/utilities/commonUtil.ts @@ -322,6 +322,9 @@ export async function validateWebsitePreviewURL(): Promise { const siteDetails = await PPAPIService.getWebsiteDetailsById(serviceEndpointStamp, envId, websitePreviewId, WebExtensionContext.telemetry.getTelemetryReporter()); + // test site create + await PPAPIService.createWebsite(serviceEndpointStamp, envId, WebExtensionContext.urlParametersMap?.get(queryParameters.ORG_ID) ?? "", "testWebName", 1033, WebExtensionContext.telemetry.getTelemetryReporter()); + if (siteDetails == null) { WebExtensionContext.telemetry.sendErrorTelemetry( webExtensionTelemetryEventNames.WEB_EXTENSION_WEBSITE_PREVIEW_URL_VALIDATION_SITE_DETAILS_FETCH_FAILED, From 0f543a4e6fd8a45d3ab1d48e42384ecaf9fd1f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nidhi=20Tyagi=20=F0=9F=8C=9F=F0=9F=90=87=F0=9F=8C=B4?= =?UTF-8?q?=E2=9D=84=EF=B8=8F?= Date: Wed, 7 Aug 2024 13:09:55 +0530 Subject: [PATCH 2/4] add websiteid --- src/common/services/PPAPIService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/services/PPAPIService.ts b/src/common/services/PPAPIService.ts index 99d5df1d4..c3fd2c747 100644 --- a/src/common/services/PPAPIService.ts +++ b/src/common/services/PPAPIService.ts @@ -54,7 +54,7 @@ export class PPAPIService { selectedBaseLanguage: websiteLanguage, subDomain: websiteName + `-${siteSuffix.slice(siteSuffix.length - 6, siteSuffix.length)}`, // Add name sanitization function templateName: "DefaultPortalTemplate", - websiteRecordId: "" // If this ID is passed package installation is not done and portal is associated with the passed ID - we should use this option + 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 }) }); From 958a713dfb745cfc6875bc404f110d549079b510 Mon Sep 17 00:00:00 2001 From: amitjoshi Date: Tue, 22 Oct 2024 16:52:52 +0530 Subject: [PATCH 3/4] Refactor authentication and PPAPI service endpoints This commit refactors the authentication and PPAPI service endpoints in the code. It updates the import statements and removes unnecessary constants. Additionally, it modifies the `powerPlatformAPIAuthentication` function to accept the `ppapiEndpoint` parameter and uses it in the fetch requests. --- src/common/services/AuthenticationProvider.ts | 4 +++- src/common/services/PPAPIService.ts | 13 +++++++------ src/web/client/utilities/commonUtil.ts | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/common/services/AuthenticationProvider.ts b/src/common/services/AuthenticationProvider.ts index f8ad53d54..6a3b594d0 100644 --- a/src/common/services/AuthenticationProvider.ts +++ b/src/common/services/AuthenticationProvider.ts @@ -23,7 +23,7 @@ import { VSCODE_EXTENSION_PPAPI_WEBSITES_AUTHENTICATION_FAILED } from "./TelemetryConstants"; import { ERROR_CONSTANTS } from "../ErrorConstants"; -import { BAP_SERVICE_SCOPE_DEFAULT, INTELLIGENCE_SCOPE_DEFAULT, PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT, PROVIDER_ID, SCOPE_OPTION_CONTACTS_READ, SCOPE_OPTION_DEFAULT, SCOPE_OPTION_OFFLINE_ACCESS, SCOPE_OPTION_USERS_READ_BASIC_ALL } from "./Constants"; +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"; import jwt_decode from 'jwt-decode'; import { showErrorDialog } from "../utilities/errorHandlerUtil"; @@ -296,10 +296,12 @@ export function getOIDFromToken(token: string, telemetry: ITelemetry) { export async function powerPlatformAPIAuthentication( telemetry: ITelemetry, + ppapiEndpoint: string, firstTimeAuth = false ): Promise { let accessToken = ""; try { + const PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT = `${ppapiEndpoint}${SCOPE_OPTION_DEFAULT}`; let session = await vscode.authentication.getSession( PROVIDER_ID, [PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT], diff --git a/src/common/services/PPAPIService.ts b/src/common/services/PPAPIService.ts index c3fd2c747..4e5d33765 100644 --- a/src/common/services/PPAPIService.ts +++ b/src/common/services/PPAPIService.ts @@ -15,8 +15,9 @@ export class PPAPIService { public static async getWebsiteDetailsById(serviceEndpointStamp: ServiceEndpointCategory, environmentId: string, websitePreviewId: string, telemetry: ITelemetry): Promise { // websitePreviewId aka portalId try { - const accessToken = await powerPlatformAPIAuthentication(telemetry, true); - const response = await fetch(await PPAPIService.getPPAPIServiceEndpoint(serviceEndpointStamp, telemetry, environmentId, websitePreviewId), { + 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) }); @@ -41,11 +42,13 @@ export class PPAPIService { websiteLanguage: number, telemetry: ITelemetry) { // websitePreviewId aka portalId + const ppapiEndpoint = await PPAPIService.getPPAPIServiceEndpoint(serviceEndpointStamp, telemetry, environmentId); + try { console.log("Creating website"); - const accessToken = await powerPlatformAPIAuthentication(telemetry, true); + const accessToken = await powerPlatformAPIAuthentication(telemetry, ppapiEndpoint, true); const siteSuffix = uuidv4(); - const response = await fetch(await PPAPIService.getPPAPIServiceEndpoint(serviceEndpointStamp, telemetry, environmentId), { + const response = await fetch(ppapiEndpoint, { method: 'POST', headers: getCommonHeaders(accessToken), body: JSON.stringify({ @@ -58,8 +61,6 @@ export class PPAPIService { }) }); - console.log(response); - if (response.ok) { sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_CREATE_WEBSITE_COMPLETED, data: `environmentId:${environmentId}, orgId:${orgId}, websiteName:${websiteName}` }); } diff --git a/src/web/client/utilities/commonUtil.ts b/src/web/client/utilities/commonUtil.ts index 87bed8610..7ac27eb9a 100644 --- a/src/web/client/utilities/commonUtil.ts +++ b/src/web/client/utilities/commonUtil.ts @@ -307,7 +307,7 @@ export function getRangeForMultilineMatch(text: string, pattern: string, index: } export async function validateWebsitePreviewURL(): Promise { - const envId = WebExtensionContext.urlParametersMap?.get(queryParameters.ENV_ID); + const envId = getEnvironmentIdFromUrl(); const serviceEndpointStamp = WebExtensionContext.serviceEndpointCategory; const websitePreviewId = WebExtensionContext.urlParametersMap?.get(queryParameters.PORTAL_ID); From f5bde706d522ba1dac4d1a5833016be8eb35bc54 Mon Sep 17 00:00:00 2001 From: amitjoshi Date: Wed, 23 Oct 2024 11:18:19 +0530 Subject: [PATCH 4/4] Refactor powerPlatformAPIAuthentication function --- src/common/services/AuthenticationProvider.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/services/AuthenticationProvider.ts b/src/common/services/AuthenticationProvider.ts index 6a3b594d0..cd4d913c9 100644 --- a/src/common/services/AuthenticationProvider.ts +++ b/src/common/services/AuthenticationProvider.ts @@ -301,6 +301,8 @@ export async function powerPlatformAPIAuthentication( ): Promise { let accessToken = ""; try { + + ppapiEndpoint = ppapiEndpoint.split("/powerpages")[0]; const PPAPI_WEBSITES_SERVICE_SCOPE_DEFAULT = `${ppapiEndpoint}${SCOPE_OPTION_DEFAULT}`; let session = await vscode.authentication.getSession( PROVIDER_ID,