Alexa smart home skill lambda is throwing a LWA error - alexa

I am developing alexa smart home skill. As part account linking i am getting AcceptGrant. I am getting below error,When i am getting access_token and refresh_token by using authorization code which i get as part of AcceptGrant request. Something i was missed. Same code is working for another skill. Could you please tell me what i missed?
ERROR Invoke Error {
"message": "Request failed with status code 400",
"name": "Error",
"stack": "Error: Request failed with status code 400\n at createError (/var/task/node_modules/axios/lib/core/createError.js:16:15)\n at settle (/var/task/node_modules/axios/lib/core/settle.js:17:12)\n at IncomingMessage.handleStreamEnd (/var/task/node_modules/axios/lib/adapters/http.js:293:11)\n at IncomingMessage.emit (events.js:412:35)\n at endReadableNT (internal/streams/readable.js:1334:12)\n at processTicksAndRejections (internal/process/task_queues.js:82:21)",
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 1000,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"User-Agent": "axios/0.24.0",
"Content-Length": 206
},
"method": "post",
"url": "https://api.amazon.com/auth/o2/token",
"data": "grant_type=authorization_code&code=RHmcOGELgCJeAHZUDtJm&client_id=amzn1.application-oa2-client.2e90a623fe5343baa8d201d038dd8666&client_secret=47cc11f1a945dde6d9844cf33ff2962fe064703c5a2ad5d651dbc29af31b539d"
},
"status": 400
}
Code
getTokensWithAuthCode(authCode) {
const body = querystring.stringify({
grant_type: 'authorization_code',
code: authCode,
client_id: ALEXA_CLIENT_ID,
client_secret: ALEXA_CLIENT_SECRET
});
return this.amazonTokenPost(body);
},
amazonTokenPost(body) {
return axios.post('https://api.amazon.com/auth/o2/token', body, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
timeout: 1000
});
}

Related

Local HTTP Request not sending with Axios on React Native Expo app

I am writing a react native expo app that utilizes a .NET backend that I've already established and has worked quite well for a while. Recently, I've gotten to the point of attempting local http requests with axios for my mobile app rather than mock data, and it worked wonderfully for a bit. I have a few get requests that are called in a useEffect like this:
useEffect(() => {
async function getAll() {
const response = await axios({
method: 'GET',
url: `${baseUrl}/ItemName`,
headers: {
authorization: `Bearer ${authToken}`,
'content-type': 'application/x-www-form-urlencoded'
}
}).catch(err => console.log(err));
if(response?.data) {
setItemName(response.data);
}
}
getAll();
}, []);
Then after that was working, I wanted to put in authentication within the app itself rather than using the backend Swagger and copying the token every 30 minutes. Made a signup page and the form worked just fine, but when I made the new axios post request, none of the requests worked - even those that were working before hand. The post looks like this:
const postNewUser = async (values) => {
try {
const postObject = {
method: 'POST',
url: `${baseUrl}/User/Register`,
data: {
firstName: values.firstName,
lastName: values.lastName,
username: values.username,
password: values.password,
email: values.email,
phoneNumber: values.phone,
birthDate: moment(values.birthDate).toISOString()
},
headers: {
'content-type': 'application/json'
}
};
const response = await axios(postObject);
if(response) {
navigation.navigate('Login', {
desiredUsername: values.username
});
}
} catch(err) {
console.log('Error: ', err);
}
}
I've been googling for over a week now trying different answers multiple different times. I've tried updating my nodejs, tried different versions of axios, tried different baseUrls for the request (localhost, 10.0.2.2, and my personal IP) but none of them work. Strangely, localhost and my IP both return very quickly, and 10.0.2.2 takes a solid 30 seconds but returns the same error message.
I have put a log into the user controller on my backend to show whether or not I'm actually hitting the backend or not, and with postman or swagger I get there just fine. With the mobile axios call I don't hit that log, so I'm not even getting to the backend at all. Instead I'm getting a not-so-useful error as follows:
Stack: AxiosError#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:114554:29
handleTimeout#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:115572:39
dispatchEvent#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:30065:31
setReadyState#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:28693:33
__didCompleteResponse#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:28499:29
emit#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:2310:40
__callFunction#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:21321:36
#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:21071:31
__guard#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:21269:15
callFunctionReturnFlushedQueue#http://personalIP:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false:21070:21
callFunctionReturnFlushedQueue#[native code]
Message: timeout exceeded
Name: AxiosError
Code: ECONNABORTED
Config: {
"adapter": [
"xhr",
"http"
],
"data": "{\"firstName\":\"Test\",\"lastName\":\"Test\",\"username\":\"test\",\"password\":\"P#ssw0rd\",\"email\":\"email#example.com\",\"phoneNumber\":\"5555555555\",\"birthDate\":\"2022-11-27T19:13:57.458Z\"}",
"env": {
"Blob": [Function Blob
],
"FormData": [Function FormData
]
},
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json"
},
"maxBodyLength": -1,
"maxContentLength": -1,
"method": "post",
"timeout": 0,
"transformRequest": [
[Function transformRequest
]
],
"transformResponse": [
[Function transformResponse
]
],
"transitional": {
"clarifyTimeoutError": false,
"forcedJSONParsing": true,
"silentJSONParsing": true
},
"url": "http://10.0.2.2:5000/api/User/Register",
"validateStatus": [Function validateStatus
],
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN"
}
Request: {
"DONE": 4,
"HEADERS_RECEIVED": 2,
"LOADING": 3,
"OPENED": 1,
"UNSENT": 0,
"_aborted": false,
"_cachedResponse": undefined,
"_hasError": true,
"_headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json"
},
"_incrementalEvents": false,
"_lowerCaseResponseHeaders": {},
"_method": "POST",
"_perfKey": "network_XMLHttpRequest_http://10.0.2.2:5000/api/User/Register",
"_performanceLogger": {
"_closed": false,
"_extras": {},
"_pointExtras": {},
"_points": {
"initializeCore_end": 606677771.370125,
"initializeCore_start": 606677745.343875
},
"_timespans": {
"network_XMLHttpRequest_http://10.0.2.2:5000/api/User/Register": [Object
],
"network_XMLHttpRequest_http://personalIp:19000/logs": [Object
],
"network_XMLHttpRequest_http://personalIp:19000/symbolicate": [Object
],
"network_XMLHttpRequest_http://personalIp:5000/api/User/Register": [Object
],
"network_XMLHttpRequest_http://localhost:5000/api/User/Register": [Object
]
}
},
"_requestId": null,
"_response": "The request timed out.",
"_responseType": "",
"_sent": true,
"_subscriptions": [],
"_timedOut": true,
"_trackingName": "unknown",
"_url": "http://10.0.2.2:5000/api/User/Register",
"readyState": 4,
"responseHeaders": undefined,
"status": 0,
"timeout": 0,
"upload": {},
"withCredentials": true
}
I'm testing this currently on my mobile expo app. I've tested in the past on the web version but SecureStore doesn't work with web. I was able to confirm before adding the new requests that the mobile version was able to call the getAll just fine before the signup was added.

Excel Add-In keeps getting 401 error when trying to access Dynamics 365 Web Api

I am trying to develop a word add in in React with Typescript that allows me to access the dynamics 365 Web Api. The best example I've actually found was in a sample excel add in that accesses the graph api using MSAL 2.0 here https://github.com/OfficeDev/PnP-OfficeAddins/tree/master/Samples/auth/Office-Add-in-Microsoft-Graph-React. If I can get a successful get request to my Dynamics 365 api after modifying the example code I will port the code over to my Word Add in.
However I keep getting a 401 error when trying to go to https://saltrial.crm.dynamics.com/api/data/v9.1/
I get a response back when I simply paste this in a browser, but inside the add in I get 401 unauthorized. I also get 401 unauthorized when I paste the token received from the add in into postman with the header of Bearer + token. I have gotten a successful Access token however when I selected
I will show you my setup in Azure AD.... I have a client secret setup, but am not using it in my add in code.
Manifest
{
"id": "35c3a758-0edb-45f6-a97d-9c7180decd73",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": true,
"appId": "4f7xxxxxxxxxxxxxxxxxxxxxx310bf0",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2021-01-24T07:09:12Z",
"disabledByMicrosoftStatus": null,
"groupMembershipClaims": null,
"identifierUris": [
"api://localhost:3000/4fxxxxxxxxxxxxxxxxxxxxxxx"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "TrySSO",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "Enable Office to call the add-in's web APIs with the same rights as the current user.",
"adminConsentDisplayName": "Office can act as the user",
"id": "5b3a4e4a-e55e-45ba-820b-ea16efbe3d5f",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "User",
"userConsentDescription": "Enable Office to call the add-in's web APIs with the same rights that you have.",
"userConsentDisplayName": "Office can act as you",
"value": "access_as_user"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-31T05:00:00Z",
"keyId": "570axxxxxxxxxxxxxxxxxxxxxxxxxxbcd1",
"startDate": "2021-01-28T04:11:05.086Z",
"value": null,
"createdOn": "2021-01-28T04:11:06.027737Z",
"hint": "mm-",
"displayName": "wordaddinsecret"
}
],
"preAuthorizedApplications": [
{
"appId": "ea5a67f6-b6f3-4338-b240-c655ddc3cc8e",
"permissionIds": [
"5b3a4e4a-e55e-45ba-820b-ea16efbe3d5f"
]
},
{
"appId": "d3590ed6-52b3-4102-aeff-aad2292ab01c",
"permissionIds": [
"5b3a4e4a-e55e-45ba-820b-ea16efbe3d5f"
]
},
{
"appId": "57fb890c-0dab-4253-a5e0-7188c88b2bb4",
"permissionIds": [
"5b3a4e4a-e55e-45ba-820b-ea16efbe3d5f"
]
},
{
"appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3",
"permissionIds": [
"5b3a4e4a-e55e-45ba-820b-ea16efbe3d5f"
]
}
],
"publisherDomain": "salnewtrial.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://localhost:3000/login/login.html",
"type": "Spa"
},
{
"url": "https://login.microsoftonline.com/common/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "https://localhost:3000/login.html",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "00000007-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "78ce3f0f-a1ce-49c2-8cde-64b5c0896db4",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "14dad69e-099b-42c9-810b-d002981feec1",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
},
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADMyOrg",
"tags": [],
"tokenEncryptionKeyId": null
}
Inside my login.ts in excel add in
(() => {
// The initialize function must be run each time a new page is loaded
Office.initialize = () => {
const msalInstance = new PublicClientApplication({
auth: {
clientId: "4f7f40ec-xxxxxxxxx-5d6b18310bf0",
authority: "https://login.microsoftonline.com/cd77a053-xxxxxxxxxx3402c0fd62", *This is tenant id
redirectUri: "https://localhost:3000/login/login.html", // Must be registered as "spa" type
},
cache: {
cacheLocation: "localStorage", // needed to avoid "login required" error
storeAuthStateInCookie: true, // recommended to avoid certain IE/Edge issues
},
});
// handleRedirectPromise should be invoked on every page load
msalInstance
.handleRedirectPromise()
.then((response) => {
// If response is non-null, it means page is returning from AAD with a successful response
if (response) {
Office.context.ui.messageParent(
JSON.stringify({ status: "success", result: response.accessToken })
);
} else {
// Otherwise, invoke login
msalInstance.loginRedirect({
scopes: [
"user.read",
"files.read.all",
"https://saltrial.crm.dynamics.com//user_impersonation",
],
});
}
})
.catch((error) => {
const errorData: string = `errorMessage: ${error.errorCode}
message: ${error.errorMessage}
errorCode: ${error.stack}`;
Office.context.ui.messageParent(
JSON.stringify({ status: "failure", result: errorData })
);
});
};
})();
Here is my API Call in Add in
import axios from 'axios';
export const getGraphData = async (url: string, accesstoken: string) => {
const response = await axios({
url: url,
method: 'get',
headers: {'Authorization': `Bearer ${accesstoken}`,
'OData-MaxVersion': '4.0',
'OData-Version': '4.0',
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8",
}
});
return response;
};
Code that calls my api function and passes the scopes and dynamics url. I console log the access token and put it into postman with header Bearer token, I get 401. Also the add-in displays 401 unauthorized in the task pane....Ignore any naming of functions referring to the graph api, I'm hitting the dynamics 365 api and hoping I don't get the 401 error. Thanks.
getFileNames = async () => {
this.setState({ fileFetch: "fetchInProcess" });
getGraphData(
// Get the `name` property of the first 3 Excel workbooks in the user's OneDrive.
"https://saltrial.crm.dynamics.com/api/data/v9.1/WhoAmI",
this.accessToken
)
.then(async (response) => {
await writeFileNamesToWorksheet(response, this.displayError);
this.setState({ fileFetch: "fetched", headerMessage: "Success" });
})
.catch((requestError) => {
// If this runs, then the `then` method did not run, so this error must be
// from the Axios request in getGraphData, not the Office.js in
// writeFileNamesToWorksheet
console.log("Access Token >>>>>>>>>>>>>>>>> ", this.accessToken);
this.displayError(requestError);
});
};

Axios GET request timeouts randomly

We are working on a React app, which makes REST API calls using Axios. And we are randomly seeing request timeouts. We checked the network connection and it was fine (100 MBPS connection). We checked our server logs, the request reached the server and it got processed without any errors. But the client never got back the response. I am adding the code we use to make those api calls below. If you find any issue with the code, a solution will be much appreciated. If you think that the code is looking good, then please give us some tips on resolving/debugging the timeout. I am also adding the error below.
import axios from 'axios';
import axiosRetry from 'axios-retry';
import { v4 } from 'uuid';
axios.defaults.timeout = 30000;
axios.interceptors.request.use((config) => {
const updatedConfig = { ...config };
updatedConfig.headers['X-CORRELATION-ID'] = v4();
return updatedConfig;
});
axiosRetry(axios, {
retries: 3,
retryDelay: (retryCount) => retryCount * 1000,
});
axios({
method: 'get',
url: `${requestURL}`,
headers: {
authorization: `Bearer ${token}`,
},
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
{
"error": {
"message": "timeout of 30000ms exceeded",
"name": "Error",
"stack": "Error: timeout of 30000ms exceeded\n at e.exports (https://file.js:2:2141051)\n at XMLHttpRequest.h.ontimeout (https://file.js:2:2140157)",
"config": {
"url": "requestURL",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*",
"authorization": "Bearer TOKEN",
"X-CORRELATION-ID": "UDID"
},
"transformRequest": [null],
"transformResponse": [null],
"timeout": 30000,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"axios-retry": {
"retryCount": 0,
"lastRequestTime": 1597096169071
}
},
"code": "ECONNABORTED"
}
}
Thanks in advance

Login with $cordovaOauth in Facebook returns null data

I am using $cordovaOauth to authenticate on an Ionic app (angular/cordova) but after settings everything on developers.facebook.com and getting the access_token I call again to get user data, but it returns an error with data=null.
Code:
$scope.facebookLogin = function() {
$cordovaOauth.facebook(FACEBOOK_ID, ["email", "public_profile"], {
redirect_uri: "http://localhost/callback"
}).then(function(result) {
var access_token = result.access_token;
//console.log(JSON.stringify(result));
$http.get("https://graph.facebook.com/v2.2/me", {
params: {
access_token: access_token,
fields: "first_name,last_name,gender,picture,locale",
format: "json"
}
}).then(function(result) {
console.log("RETURN: " + JSON.stringify(result)); // Here is where I see that JSON data
}, function(error) {
alert("Error: " + error);
});
}, function(error) {
console.log(error);
});
}
And here is the returned JSON:
{
"data": null,
"status": -1,
"config": {
"method": "GET",
"transformRequest": [null],
"transformResponse": [null],
"params": {
"access_token": "EAAS8ChUdfHEBALdJimUl5TA1sfWGZAZBv8lxlRlpcSaMhKo1NQX5JEgVuTjjpYP4agdZBZCXO0vwFJs0kLXr5CEz2h35JPZAhls9ZBVyyuwfQFlfWQkFDyGMVxsZBmGZA0s6F6XO97HpJRd7c7iZCuwEHhZAKfnMdoKerT0s5HHPW3xAZDZD",
"fields": "first_name,last_name,gender,picture,locale",
"format": "json"
},
"url": "https://graph.facebook.com/v2.2/me",
"headers": {
"Accept": "application/json"
},
"withCredentials": true
},
"statusText": ""
}
Anybody has an idea of what's wrong?

Outlook Rest calling form angularjs

Using outlook I am trying to create event, When i send request using POSTMAN its working fine, But same code in Angularjs its not wotking.
what is wrong with code.
Please help.
$scope.createEvents = function(){
var url = "https://outlook.office.com/api/v2.0/$metadata#Me/Calendars";
//var url = "https://outlook.office.com/api/v2.0/$metadata#me/Calendars";
var add_events = {
"Subject": "Discuss the Calendar REST API",
"Body": {
"ContentType": "HTML",
"Content": "I think it will meet our requirements!"
},
"Start": {
"DateTime": "2016-10-10T18:00:00",
"TimeZone": "Pacific Standard Time"
},
"End": {
"DateTime": "2016-10-10T19:00:00",
"TimeZone": "Pacific Standard Time"
},
"Attendees": [
{
"EmailAddress": {
"Address": "sathish.gopikrishnan#stradegi.com",
"Name": "Sathish Gopi"
},
"Type": "Required"
}
]
};
$http({
method: 'POST',
url: url,
headers:{
'Authorization':'Bearer '+$scope.token,
'Content-Type': "application/json",
'Accept': 'application/json;odata.metadata=minimal',
'Access-Control-Allow-Origin':'*'
},
data: add_events
}).Succes(function (response) {
alert("Saved")
});
I am getting.
Failed to load resource: the server responded with a status of 406 (Not Acceptable). To solve this problem i am using this code now
$scope.createEvents = function(){
var url = "https://outlook.office.com/api/v2.0/$metadata#Me/Calendars";
//var url = "https://outlook.office.com/api/v2.0/$metadata#me/Calendars";
var add_events = {
"Subject": "Discuss the Calendar REST API",
"Body": {
"ContentType": "HTML",
"Content": "I think it will meet our requirements!"
},
"Start": {
"DateTime": "2016-10-10T18:00:00",
"TimeZone": "Pacific Standard Time"
},
"End": {
"DateTime": "2016-10-10T19:00:00",
"TimeZone": "Pacific Standard Time"
},
"Attendees": [
{
"EmailAddress": {
"Address": "sathish.gopikrishnan#stradegi.com",
"Name": "Sathish Gopi"
},
"Type": "Required"
}
]
};
$http({
method: 'JSONP',
url: url,
headers:{
'Authorization':'Bearer '+$scope.token,
'Content-Type': "application/json",
'Accept': 'application/json;odata.metadata=minimal',
'Access-Control-Allow-Origin':'*'
},
data: add_events
}).Succes(function (response) {
alert("Saved")
});
After Using Jsonp as method I am getting this error
Uncaught SyntaxError: Unexpected token <
406 Not Acceptable is defined as the following:
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.
see restapitutorial: http status codes
You send the following Accept header:
'Accept': 'application/json;odata.metadata=minimal'
The server says, it cannot produce this content type. If you got it running using postman, have a look at which accept header you've provided there.
Concerning your second try: jsonp is not an http method/verb (GET, PUT, POST, DELETE, PATCH). I'm not an angularjs expert but in case you need jsonp, there is a method you can call.
JSONP is a quite specific (and somewhat problematic) technique. So as long as you can do that, try to avoid it.
i know its an old post, i've had the same problem and this is the solution if someone falls into the same problem,
you should use https://graph.microsoft.com/v1.0/me/calendar/events as URL
Exemple tested code :
var url = "https://graph.microsoft.com/v1.0/me/calendar/events";
var add_events = {
"Subject": "Title",
"Body": {
"ContentType": "HTML",
"Content": " Exemple"
},
"Start": {
"DateTime": "2010-05-17T18:00:00",
"TimeZone": "UTC"
},
"End": {
"DateTime": "2010-05-17T19:00:00",
"TimeZone": "UTC"
}
};
$http({
method: 'POST',
url: url,
headers:{
'Authorization':'Bearer '+localStorage.getItem('Your Token here'),
'Content-Type':'application/json',
'Accept': 'application/json;odata.metadata=minimal',
'Access-Control-Allow-Origin':'*',
'token_type':'Bearer'
},
data: add_events
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
localStorage.setItem('etat_mytoken', 0);
$window.location.href = url_base+'/'+url_base_v+'/app/assets/views/token.html';
});

Resources