Hello,
I am creating a dashboard gadget app. I was able to install and run with static text. However, I am getting Content Security Policy error when trying to make call to Jira API.
Below is the sample code:
import api, { route } from "@forge/api";
const View = () => {
var jql = 'filter = "Filter by Type"';
var payload = `{ jql: ${jql}, startAt: 0, maxResults: 3000 }`
const response = await api.asApp().requestJira(route`/rest/api/2/search`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: payload
});
const json = await response.json();
console.log(`Response: ${response.status} ${response.statusText}`);
console.log(json);
return json;
}
In the menifest have below permission:
permissions:
scopes:
- read:jira-work
index.jsx:82 Refused to connect to âhttps://jira/rest/api/2/searchâ because it violates the following Content Security Policy directive: âconnect-src âselfâ https://api.atlassian.com/metal/ingestâ.
The app is running under https://mydomain.atlassian.net/jira/dashboards/10001/edit
The ârouteâ should be âhttps://mydomain.atlassian.netâ and not âhttps://jiraâ.
Thanks for you help!
Hi @AhmedPan, the @forge/api
package is meant to be used in Forge backend resolvers and the deprecated old version of UI Kit (which makes a call to the Forge backend resolver by default).
If you want to make an API request to Jira from your front end, then you are probably want to use requestJira in the @forge/bridge
package.
How do I return a promise from the resolver and use that in the front end? In the resolver I canât await a call.
resolver.define('getText', (req) => {
console.log(req);
var jql = 'filter = "Filter by Type"';
var payload = `{ "jql": ${jql}, startAt: 0, maxResults: 3000 }`
var p = {
"jql": jql,
"startAt": 0,
"maxResults": 3000
}
const response = api.asApp().requestJira(route`/rest/api/2/search`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(p)
});
return response;
});
Code in the front-end:
useEffect(() => {
invoke('getText', { example: 'my-invoke-variable' }).then( async (rr) => {
console.log(rr);
const result = await rr.json();
setData(result);
});
}, []);
Thanks @BoZhang for you input. It help me find the solution. I got it working both front-end and back-end. Below are both solution for reference.
Forge version 10.5.0
Module: jira:dashboardGadget
Front-end solution (indext.jsx):
const View = () => {
const [data, setData] = useState(null);
const context = useProductContext();
const fetchFilter = async () => {
var jql = 'filter = "Filter by Type"';
var p = {
"jql": jql,
"startAt": 0,
"maxResults": 3000
}
const response = await requestJira('/rest/api/2/search', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(p)
});
const result = await response.text();
console.log(result);
return result;
};
fetchFilter().then((r) => {
setData(r);
})
return (
<>
<Text>data: {data}</Text>
</>
);
};
requestJira: rest call is made as the current user.
Note: the âfetchFilterâ method is returning text and not JSON.
Back-end solution:
indext.js: the resolver
resolver.define('getText', async (req) => {
console.log(req);
var jql = 'filter = "Filter by Type"';
var p = {
"jql": jql,
"startAt": 0,
"maxResults": 3000
}
const response = await api.asApp().requestJira(route`/rest/api/2/search`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(p)
});
const result = await response.json();
return result;
});
Indext.jsx calling resolver:
const View = () => {
const [data, setData] = useState(null);
const context = useProductContext();
useEffect(() => {
invoke('getText', { example: 'my-invoke-variable' }).then((rr) => {
const id = rr.issues[0].id;
const key = rr.issues[0].key;
setData(`id: ${id}, key: ${key}`);
});
}, []);
return (
<>
<Text>data: {data}</Text>
</>
);
};
1 Like