diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bf64ecec..d9f2fb34 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,8 +1,5 @@ -* @contentstack/marketplace-pr-reviewers -.github/workflows/sca-scan.yml @contentstack/security-admin - +* @contentstack/developer-ecosystem-pr-reviewers +.github/workflows/ @contentstack/security-admin **/.snyk @contentstack/security-admin - -.github/workflows/policy-scan.yml @contentstack/security-admin - -.github/workflows/issues-jira.yml @contentstack/security-admin \ No newline at end of file +**/CODEOWNERS @contentstack/security-admin +**/.gitguardian.yaml @contentstack/security-admin \ No newline at end of file diff --git a/.github/workflows/issues-jira.yml b/.github/workflows/issues-jira.yml deleted file mode 100644 index 7bf04694..00000000 --- a/.github/workflows/issues-jira.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Create Jira Ticket for Github Issue - -on: - issues: - types: [opened] - -jobs: - issue-jira: - runs-on: ubuntu-latest - steps: - - - name: Login to Jira - uses: atlassian/gajira-login@master - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - - name: Create Jira Issue - id: create_jira - uses: atlassian/gajira-create@master - with: - project: ${{ secrets.JIRA_PROJECT }} - issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} - summary: Github | Issue | ${{ github.event.repository.name }} | ${{ github.event.issue.title }} - description: | - *GitHub Issue:* ${{ github.event.issue.html_url }} - - *Description:* - ${{ github.event.issue.body }} - fields: "${{ secrets.ISSUES_JIRA_FIELDS }}" \ No newline at end of file diff --git a/.github/workflows/sca-scan.yml b/.github/workflows/sca-scan.yml index 2307d489..79b65575 100644 --- a/.github/workflows/sca-scan.yml +++ b/.github/workflows/sca-scan.yml @@ -5,6 +5,9 @@ on: jobs: security-sca: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write steps: - uses: actions/checkout@master - name: Run Snyk to check for vulnerabilities diff --git a/__test__/uiLocation.test.ts b/__test__/uiLocation.test.ts index 1c743a50..f51be413 100644 --- a/__test__/uiLocation.test.ts +++ b/__test__/uiLocation.test.ts @@ -2,7 +2,6 @@ import { AxiosRequestConfig, AxiosResponse } from "axios"; import postRobot from "post-robot"; -import UiLocation from "../src/uiLocation"; import { IAppConfigInitData, IAssetSidebarInitData, @@ -14,8 +13,9 @@ import { LocationType, Region, } from "../src/types"; -import { RequestOption } from "../src/types/common.types"; import { RequestConfig } from "../src/types/api.type"; +import { RequestOption } from "../src/types/common.types"; +import UiLocation from "../src/uiLocation"; jest.mock("post-robot"); jest.mock("wolfy87-eventemitter"); @@ -310,7 +310,13 @@ describe("UI Location", () => { const config = await uiLocation.getConfig(); expect(config).toEqual({}); expect(postRobotSendToParentMock).toHaveBeenLastCalledWith( - "getConfig", {"context": {"extensionUID": "extension_uid", "installationUID": "installation_uid"}} + "getConfig", + { + context: { + extensionUID: "extension_uid", + installationUID: "installation_uid", + }, + } ); }); }); @@ -458,6 +464,9 @@ describe("UI Location", () => { const uiLocation = new UiLocation({ ...initData, type: "FIELD_MODIFIER_LOCATION", + schema: { + $uid: "", + }, } as IFieldModifierLocationInitData); expect(uiLocation.location.FieldModifierLocation).toBeDefined(); expect(uiLocation.location.FieldModifierLocation).toHaveProperty( @@ -478,6 +487,9 @@ describe("UI Location", () => { const uiLocation = new UiLocation({ ...initData, type: "FULL_PAGE_LOCATION", + schema: { + $uid: "", + }, } as IFullPageLocationInitData); expect(uiLocation.location.FullPage).toBeDefined(); expect(uiLocation.location.FullPage).toHaveProperty("stack"); @@ -487,6 +499,9 @@ describe("UI Location", () => { const uiLocation = new UiLocation({ ...initData, type: "FIELD", + schema: { + $uid: "", + }, } as IFieldInitData); expect(uiLocation.location.CustomField).toBeDefined(); expect(uiLocation.location.CustomField).toHaveProperty("field"); @@ -502,6 +517,9 @@ describe("UI Location", () => { const uiLocation = new UiLocation({ ...initData, type: "", + schema: { + $uid: "", + }, } as any); expect(uiLocation.location.CustomField).toBeDefined(); expect(uiLocation.location.CustomField).toHaveProperty("field"); diff --git a/package-lock.json b/package-lock.json index 88ce9830..02820f62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/app-sdk", - "version": "2.4.0", + "version": "2.4.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/app-sdk", - "version": "2.4.0", + "version": "2.4.1", "license": "MIT", "dependencies": { "axios": "^1.7.9", diff --git a/package.json b/package.json index 6aecd069..13c2068e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/app-sdk", - "version": "2.4.0", + "version": "2.4.1", "types": "dist/src/index.d.ts", "description": "The Contentstack App SDK allows you to customize your Contentstack applications.", "main": "dist/index.js", diff --git a/src/uiLocation.ts b/src/uiLocation.ts index 7d1b9dec..b84d68f7 100755 --- a/src/uiLocation.ts +++ b/src/uiLocation.ts @@ -2,10 +2,9 @@ import { AxiosRequestConfig, AxiosResponse } from "axios"; import postRobot from "post-robot"; import EventEmitter from "wolfy87-eventemitter"; +import { AppConfig } from "./appConfig"; import AssetSidebarWidget from "./AssetSidebarWidget"; import ContentTypeSidebarWidget from "./ContentTypeSidebarWidget"; -import { IRTEPluginInitializer } from "./RTE/types"; -import { AppConfig } from "./appConfig"; import Entry from "./entry"; import EventRegistry from "./EventRegistry"; import Field from "./field"; @@ -14,6 +13,7 @@ import FieldModifierLocationField from "./fieldModifierLocation/field"; import FieldModifierLocationFrame from "./fieldModifierLocation/frame"; import Metadata from "./metadata"; import Modal from "./modal"; +import { IRTEPluginInitializer } from "./RTE/types"; import Stack from "./stack"; import Store from "./store"; import { @@ -22,20 +22,20 @@ import { IDashboardWidget, IFieldModifierLocation, IFullPageLocation, + IGlobalFullPageLocation, IRTEInitData, ISidebarWidget, InitializationData, LocationType, Manifest, - IGlobalFullPageLocation, RegionType, } from "./types"; +import { ContentstackEndpoints } from "./types/api.type"; import { GenericObjectType } from "./types/common.types"; import { User } from "./types/user.types"; +import { dispatchAdapter, dispatchApiRequest } from "./utils/adapter"; import { formatAppRegion, onData, onError } from "./utils/utils"; import Window from "./window"; -import { dispatchApiRequest, dispatchAdapter } from "./utils/adapter"; -import { ContentstackEndpoints } from "./types/api.type"; const emitter = new EventEmitter(); @@ -263,6 +263,11 @@ class UiLocation { case LocationType.FIELD_MODIFIER_LOCATION: { initializationData.self = true; + // Fix for FIELD_NOT_FOUND issue introduced in v2.4.0 + // Schema field UIDs contain the complete field path, including parent paths + // Custom Field and Field Modifier UIDs currently contain only the field UID + // As a result, schema field lookup fails for nested fields because the full path is required + // MKT-18455 this.location.FieldModifierLocation = { entry: new FieldModifierLocationEntry( initializationData, @@ -273,7 +278,10 @@ class UiLocation { currentBranch: initializationData.currentBranch, }), field: new FieldModifierLocationField( - initializationData, + { + ...initializationData, + uid: initializationData.schema.$uid, + }, postRobot, emitter ), @@ -309,8 +317,20 @@ class UiLocation { case LocationType.FIELD: default: { initializationData.self = true; + // Fix for FIELD_NOT_FOUND issue introduced in v2.4.0 + // Schema field UIDs contain the complete field path, including parent paths + // Custom Field and Field Modifier UIDs currently contain only the field UID + // As a result, schema field lookup fails for nested fields because the full path is required + // MKT-18455 this.location.CustomField = { - field: new Field(initializationData, postRobot, emitter), + field: new Field( + { + ...initializationData, + uid: initializationData.schema.$uid, + }, + postRobot, + emitter + ), fieldConfig: initializationData.field_config, entry: new Entry(initializationData, postRobot, emitter), stack: new Stack(initializationData.stack, postRobot, { @@ -400,9 +420,7 @@ class UiLocation { ]); } if (event.data.name === "onError") { - emitter.emitEvent("onError", [ - event.data.data, - ]); + emitter.emitEvent("onError", [event.data.data]); } }); } catch (err) { @@ -436,7 +454,12 @@ class UiLocation { return Promise.resolve(this.config); } return this.postRobot - .sendToParent("getConfig", {context:{installationUID:this.installationUID, extensionUID:this.locationUID}}) + .sendToParent("getConfig", { + context: { + installationUID: this.installationUID, + extensionUID: this.locationUID, + }, + }) .then(onData) .catch(onError); }; @@ -490,7 +513,7 @@ class UiLocation { api = (url: string, option?: RequestInit): Promise => dispatchApiRequest(url, option) as Promise; - + /** * Method used to create an adapter for management sdk. */ @@ -524,4 +547,4 @@ class UiLocation { } } -export default UiLocation; \ No newline at end of file +export default UiLocation;