workbox 3 - ignore URL params on run-time caching - javascript

I want to cache assets from a secure CDN that uses policy token as URL params.
for example: www.cdn.com/image.png?Policy=AAAAA&Key-Pair-Id=BBBBB
and if I re-visit the site, I want to get the asset from the cache even if I have a different policy token and Key-Pair-Id.
for example: www.cdn.com/image.png?Policy=CCCCC&Key-Pair-Id=DDDDD
If I use this code in the service worker:
workbox.routing.registerRoute(
/^(http(s)?:)?\/\/www\.cdn\.com.*/,
workbox.strategies.staleWhileRevalidate()
);
It doesn't find the response in the cache and goes to the network.
I want it to match by the URL without the URL params (even if Policy=CCCCC&Key-Pair-Id=DDDDD is not actually a valid policy). just look if www.cdn.com/image.png exists and retrieve it.

I found a solution for this by using a custom handler:
workbox.routing.registerRoute(
/^(http(s)?:)?\/\/www\.cdn\.com.*/,
({url, event}) => {
return caches.open(`${prefix}-${runtime}-${suffix}`).then((cache) => {
const customRequest = `${url.origin}${url.pathname}`;
return cache.match(customRequest).then((cacheRes) => {
if (cacheRes) {
return cacheRes;
}
return fetch(event.request).then((fetchRes) => {
cache.put(customRequest, fetchRes.clone());
return fetchRes;
});
});
});
}
);

Related

Why all users in Strapi have access to update all users profile?

I added a new filed called config (type: json) to the User model. I use built-in swagger of Strapi local document. The problem is that I can update another user config (data) with put method.
First, I authorized by POST /auth/local and get my token and my user id (in this cast it's 5)
I add my token to swagger Authorize button.
Then, I use PUT /user/{id} in this case id is 5.
Calling api http://localhost:1337/api/users/4 returns 200!
I expect that I get 403 error! Because I should not able to change other user profiles!!!
Is it normal? If yes, tell me a solution to fix this.
This is because Strapi has only two default roles:
Public
Authenticated
So by default, when you setup permissions, whatever authentication state currently the user has access to all the content accordingly (e.g. Public to only public, Authenticated to authenticated)
To work with this, and to limit the user actions in the auth scope you have to use middleware or policy, so since this is in user-permissions scope let's add policy to user-permissions:
Strapi 4.5.3
yarn strapi generate
? Strapi Generatos
>policy
? Policy name
isOwner
? Where do you want to add this policy?
> Add policy to root of project
Next step is in your /src/extensions folder you have to create folder users-permissions, and in this folder file strapi-server.js with following content:
/src/extensions/users-permissions/strapi-server.js
module.exports = (plugin) => {
for (let i = 0; i < plugin.routes["content-api"].routes.length; i++) {
const route = plugin.routes["content-api"].routes[i];
if (
route.method === "GET" &&
route.path === "/users/:id" &&
route.handler === "user.findOne"
) {
console.log(route);
plugin.routes["content-api"].routes[i] = {
...route,
config: {
...route.config,
policies: route.config.policies
? [...route.config.policies, "global::isOwner"] // tests if policies were defined
: ["global::isOwner"],
},
};
}
}
return plugin;
};
if you did the step correct in your strapi server console you have to see:
info: In isOwner policy. if you send get request to /api/users/:id
Next step is we are going to modify policy file like so:
/src/policies/isOwner.js
"use strict";
/**
* `isOwner` policy
*/
module.exports = async (policyContext, config, { strapi }) => {
strapi.log.info("In isOwner policy.");
const { user, auth } = policyContext.state;
const { params } = policyContext;
// this case the userId is the same as the id we are requesting
// other cases would need more extensive validation...
const canDoSomething = user.id == params.id;
if (canDoSomething) {
return true;
}
return false;
};
and whoala:
{
"data": null,
"error": {
"status": 403,
"name": "PolicyError",
"message": "Policy Failed",
"details": {}
}
}
if we try to get other user profile

CORS No 'Access-Control-Allow-Origin' error in React app w/ Facebook

I'm a junior developer that's fairly new to using Facebook for Developers. I'm hitting a wall with the ReactJs application I'm building and could use your help!
My boss has requested a Grid representation of the Page Plugin, not the actual Plugin itself. For this project, he's requested I make and use a test 'Page' I've found that DevExtreme's Data Grid seems to be the best option in terms of the desired visual, and I'm trying to call my Facebook Page using the Graph API documentation. I know it's hitting at least the area I want it to with my console.log because it's returning the error message.
Here are the errors my browser is returning:
Access to fetch at 'https://www.facebook.com/Feeds-Tester-170107151801959/' from origin 'https://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
GET https://www.facebook.com/Feeds-Tester-170107151801959/ net::ERR_FAILED
The link you'll see referenced in my URL variable has been triple checked to be the correct link. Since I'm using NodeJS, I tried installing the CORS npm package but I'm not 100% sure where to put it to use it, I'm wondering if that's the cause of the issue?
Here's my full code snippet (I'm using VS Code, if that helps):
/*global FB*/
import React from 'react';
import { DataGrid, Editing, Scrolling, Lookup, Summary, TotalItem } from 'devextreme-react/data-grid';
import { Button } from 'devextreme-react/button';
import { SelectBox } from 'devextreme-react/select-box';
import CustomStore from 'devextreme/data/custom_store';
import { formatDate } from 'devextreme/localization';
import 'whatwg-fetch';
const URL = 'https://www.facebook.com/Feeds-Tester-170107151801959/';
const REFRESH_MODES = ['full', 'reshape', 'repaint'];
class Grid extends React.Component {
constructor(props) {
super(props);
this.state = {
fbData: null,
ordersData: new CustomStore({
key: 'OrderID',
load: () => this.sendRequest(`${URL}`, 'GET'),
}),
requests: [],
refreshMode: 'reshape'
};
this.clearRequests = this.clearRequests.bind(this);
this.handleRefreshModeChange = this.handleRefreshModeChange.bind(this);
var body = 'Reading JS SDK documentation';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
console.log('Error occured');
} else {
console.log('Post ID: ' + response.id);
}
})
}
sendRequest(url, method, data) {
method = method || 'GET';
data = data || {};
this.logRequest(method, url, data);
if(method === 'GET') {
return fetch(url, {
method: method,
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Access-Control-Allow-Origin': '*'
}
}).then(result => result.json().then(json => {
if(result.ok) return json.data;
throw json.Message;
}));
}
const params = Object.keys(data).map((key) => {
return `${encodeURIComponent(key) }=${ encodeURIComponent(data[key])}`;
}).join('&');
return fetch(url, {
method: method,
body: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
credentials: 'include'
}).then(result => {
if(result.ok) {
return result.text().then(text => text && JSON.parse(text));
} else {
return result.json().then(json => {
throw json.Message;
});
}
});
}
logRequest(method, url, data) {
const args = Object.keys(data || {}).map(function(key) {
return `${key }=${ data[key]}`;
}).join(' ');
const time = formatDate(new Date(), 'HH:mm:ss');
const request = [time, method, url.slice(URL.length), args].join(' ');
this.setState((state) => {
return { requests: [request].concat(state.requests) };
});
}
clearRequests() {
this.setState({ requests: [] });
}
handleRefreshModeChange(e) {
this.setState({ refreshMode: e.value });
}
render() {
const { refreshMode, ordersData } = this.state;
return (
<React.Fragment>
<DataGrid
id="grid"
showBorders={true}
dataSource={ordersData}
repaintChangesOnly={true}
>
<Editing
refreshMode={refreshMode}
mode="cell"
allowAdding={true}
allowDeleting={true}
allowUpdating={true}
/>
<Scrolling
mode="virtual"
/>
<Lookup dataSource={ordersData} valueExpr="Value" displayExpr="Text" />
<Summary>
{/* <TotalItem column="CustomerID" summaryType="count" />
<TotalItem column="Freight" summaryType="sum" valueFormat="#0.00" /> */}
</Summary>
</DataGrid>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<span>Refresh Mode: </span>
<SelectBox
value={refreshMode}
items={REFRESH_MODES}
onValueChanged={this.handleRefreshModeChange}
/>
</div>
<div id="requests">
<div>
<div className="caption">Network Requests</div>
<Button id="clear" text="Clear" onClick={this.clearRequests} />
</div>
<ul>
{this.state.requests.map((request, index) => <li key={index}>{request}</li>)}
</ul>
</div>
</div>
</React.Fragment>
);
}
}
export default Grid;
This is the link to the docs for the module I'm trying to reference
I'm trying to not bite off more than I can chew and just start with retrieving the data before I even think about manipulating it or sending any in return. Any insight or guidance you can provide would be greatly appreciated. Thank you!! :)
Do not use fetch with the Facebook URL, it won't let it happen on the browser, instead, use the Facebook API for everything you need to do with it
For example, instead of fetching the page, use the api with the page
FB.api('/Feeds-Tester-170107151801959', function(response) {
// ...
});
If you need to fetch the page, then you have to do it outside the browser environment or use a proxy like cors anywhere, but you can avoid that by using the Facebook API
I was also getting these error. I found that the pageId, I was using was wrong🤦‍♀️. These errors come only when your pageId is wrong or the domain is not whitelisted properly(I even tried with a ngrok url and it worked😵).
So the steps which I followed were:
In buisness.facebook.com go to inbox from sidebar and select chat plugin. [https://i.stack.imgur.com/rDk5d.png]
Click on setup to add your domain. [https://i.stack.imgur.com/exOi2.png]
Pick a setup method(standard for react/nextjs) and setup chat plugin(add language, domain, copy code and paste it). [https://i.stack.imgur.com/hDArZ.png]
You can add multiple domains. [https://i.stack.imgur.com/zGdgx.png]
You will get pageId already embedded. [https://i.stack.imgur.com/iRT13.png]
Use this code and paste it in _document.js file in nextjs. and after deploying it will work perfectly. For any confusion please let me know. Thanks, Happy Coding ☺

Error with Fetch request for Google places API [duplicate]

I really do NOT understand how I'm supposed to make this work:
var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';
console.log(requestURL);
$.getJSON( requestURL, function( data ) {
// data
console.log(data);
});
and my HTML file:
<body>
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script src="main.js" charset="utf-8"></script>
</body>
I always get the No 'Access-Control-Allow-Origin' header is present on the requested resource. message... even though if I go to https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw in my browser I get the proper JSON returned.
I am lead to believe that CORS can help me here. I don't understand CORS. Please, can anyone help me in plain simple terms? What should I change to make this work??
Thanks
You are trying to use the Google Places API Web Service on client side whereas it is designed for server side applications. That's probably why appropriate CORS response headers are not set by the server.
As explained in the Notes at the beginning of the Place Details documentation, you should use the Places Library in the Google Maps JavaScript API:
If you're building a client-side application, take a look at the Google Places API for Android, the Google Places API for iOS, and the Places Library in the Google Maps JavaScript API.
Note: you will need to enable the Google Maps JavaScript API in your Google Developer Console first.
Here is a way you can proceed to get place details (based on the example from the documentation):
<head>
<script type="text/javascript">
function logPlaceDetails() {
var service = new google.maps.places.PlacesService(document.getElementById('map'));
service.getDetails({
placeId: 'ChIJN1t_tDeuEmsRUsoyG83frY4'
}, function (place, status) {
console.log('Place details:', place);
});
}
</script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw&libraries=places&callback=logPlaceDetails"></script>
</head>
<body>
<div id="map"></div>
</body>
#rd3n already answered about why to use Google Maps' SDK, but if you really need to use the API instead of SDK on a web app (reuse code, for exemple), you can bypass CORS using proxy parameter from Webpack's DevServer.
const GMAPS_PLACES_AUTOCOMPLETE_URL = (
process.env.NODE_ENV === 'production'
? 'https://maps.googleapis.com/maps/api/place/autocomplete/json'
: 'place-api' // on development, we'll use the Webpack's dev server to redirect the request
const urlParams = new URLSearchParams([
...
])
const response = await fetch(
`${GMAPS_PLACES_AUTOCOMPLETE_URL}?${urlParams}`,
{ method: 'GET' }
)
And on your webpack.config.js...
module.exports = {
devServer: {
proxy: {
'/place-api': {
target: 'https://maps.googleapis.com/maps/api/place/autocomplete/json',
changeOrigin: true,
pathRewrite: { '^/place-api': '' }
}
}
}
}
I know this is an old question, and this might not be a direct answer to this question, but just in case someone could use this trick, I always like to go around this issue using PHP to create my own API, then fetch the newly created API using JavaScript:
1# Create an api.php file:
<?php
$google_URL = 'https://maps.googleapis.com/maps/api/place/details/json';
$api = 'YOUR_GOOGLE_API';
$place = 'PLACE_ID';
$field = [
'user_ratings_total',
'rating'
];
$fields = join(",", $field);
$result_url = $google_URL.'?placeid='.$place.'&fields='.$fields.'&key='.$api;
$result_content = file_get_contents($result_url);
$json_data = json_decode($result_content, true);
if ( isset($json_data) && $json_data['status'] === 'OK' ) {
echo json_encode($json_data['result']);
}else {
echo json_encode($json_data['error_message']);
}
header("content-type: application/json");
2# Create a script.js file:
const url = './api.php';
fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(error => console.log(error))
Using the same url you provided, this is for pure front-end (React), but a less secure solution:
var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';
Cut out the following from url: 'https://maps.googleapis.com/maps/api/place' and create a proxy line in your package.json:
"proxy": "https://maps.googleapis.com/maps/api/place"
Then following google documentations you'll be left with the following code (wherever you're fetching the api):
var axios = require('axios');
var config = {
method: 'get',
url: '/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw', //the rest of your url
secure: false //important
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});

How to read the JSON file from the API in the interface

I want to read a JSON file from the API every 11 seconds and display it in the interface
In my case :
the interface server is running at http://localhost:8080/
the API at http://localhost:8088/route (and I need to refresh it every 11 seconds because parameters changes)
and in route.js :
var i=0;
var delayInms = 11000;
var myVar = setInterval(TempFunction, 1000);
function TempFunction() {
router.get('/', (req,res,next)=>{
var text =[
{"carspeed":[233+i,445+i,223+i,444+i,234+i]},
]
console.log(text);
res.status(200).json(text);
});
window.location.reload(true);
i++;
}
********THE PROBLEM is that I get this error:
ReferenceError: window is not defined
I have another question :
to read the JSON (which is updated in http://localhost:8088/route every 11 seconds) I did this :
in car.vue :
<template>
.
.
<ul>
<li v-for="todo of todos" :key="todo.id">{{todo.text}}</li>
</ul>
.
.
</template>
followed by :
<script>
import axios from 'axios';
const WorkersURL="http://localhost:8088/route";
export default {
data: () => ({
drawer: false,
todos:[]
}),
async created()
{
try
{
const res = await axios.get(WorkersURL);
this.todos=res.data;
}
catch(e)
{
console.error(e)
}
}
}
<script>
********AND THE SECOND PROBLEM : it doesn't read the JSON file from http://localhost:8088/route
You'll need to make sure that you are enabling your server to be hit from web pages running at a different host/domain/port. In your case, the server is running on a different port than the webpage itself, so you can't make XHR (which is what Axios is doing) calls successfully because CORS (Cross-Origin Resource Sharing) is not enabled by default. Your server will need to set the appropriate headers to allow that. Specifically, the Access-Control-Allow-Origin header. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Second, to update your client every 11 seconds there are a few choices. The simplest would be to make you call via axios every 11 seconds using setInterval:
async created()
{
try
{
const res = await axios.get(WorkersURL);
this.todos=res.data;
// set a timer to do this again every 11 seconds
setInterval(() => {
axios.get(WorkersURL).then((res) => {
this.todos=res.data;
});
}, 11000);
}
catch(e)
{
console.error(e)
}
}
There are a couple of options that are more advanced such as serve-sent events (See https://github.com/mdn/dom-examples/tree/master/server-sent-events) or websockets (https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). Both of these options allow you to control the interval on the server instead of the client. There are some things to consider when setting up your server for this, so the setInterval options is probably best in your case.

Implementing a custom ember-simple-auth Authenticator

Firstly, I am not a seasoned JS Developer, so please excuse obvious mistakes that I could have made.
I am trying to implement a custom Authenticator for authenticating a user with Keycloak using the OAuth2 Password Grant which requires the client_id be passed as part of the request body.
import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant';
export default OAuth2PasswordGrant.extend({
serverTokenEndpoint: 'http://localhost:8080/something/token',
makeRequest(url, data, headers = {}) {
data.client_id = 'my-app';
return this._super(url, data, headers);
}
});
I have a controller that uses this Authenticator by calling this action:
actions: {
authenticate() {
let {username, password} = this.getProperties('username', 'password');
this.get('session').authenticate('authenticator:oauth2', username, password).then(() => {
// Do something
}).catch((response) => {
// Show error
});
}
}
This causes Firefox to hang and gives me an unresponsive script message.
If I remove the return from the makeRequest() method, I can see from the browser debugger that the call to Keycloak actually returns correctly with the object that contains my token etc. However ember inspector shows some errors related to unresolved promises. But I guess that's because I'm no longer returning the promise.
What am I doing wrong here?
How can I fix the unresponsive script issue?
Is there another way for me to achieve my goal?
Edit 1: This is when I remove the return
Here is the actual object that is returned:
{
"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJTRUNSd09fMlZWdGhxUVBUWnFxNHlqX0tKekxnOElSTjBrQkx5UTlacklrIn0.eyJqdGkiOiI1NDgzZDdkMi0zMDdhLTQyZjItYWUxZC0xYTZjMTZjOTM2ZjAiLCJleHAiOjE1MDgzMzE5MjAsIm5iZiI6MCwiaWF0IjoxNTA4MzMxNjIwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvc2Z4LWl0cmFuc2Zlci13ZWItYWdlbnQiLCJhdWQiOiJhZ2VudC13ZWItYXBwIiwic3ViIjoiMzZiMWY4OWMtNGYwMC00OTU1LWE0YzMtZWQ0NzZmZDU2OGM3IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYWdlbnQtd2ViLWFwcCIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjQwODMxZWFhLTRmMmEtNDk2ZS05NDVkLTdiZWIxN2U0NmU0NCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1bWFfYXV0aG9yaXphdGlvbiIsImJhY2stb2ZmaWNlLWFnZW50Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwibmFtZSI6IlVtYXIgS2hvbHZhZGlhIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1hciIsImdpdmVuX25hbWUiOiJVbWFyIiwiZmFtaWx5X25hbWUiOiJLaG9sdmFkaWEiLCJlbWFpbCI6InVtYXJAYWlydmFudGFnZS5jby56YSJ9.eUJFklRiRjQPOC1rQLcqrljsSWmGXCpNNKqLJGAcvbnbwx8X0T1iqrmpFdyMN3EKRrIfTZyYRfcTEbpcBEjZcZtgDY9V0Ntvt4pvpUx_8Ey6I8xZQolHVwferjM30puLqG8MImADUimNrj3ghbJbAaCOJktIKgLnTIhDbkNb-8lzgbyq-rEP6lYAWjQ2OuOZnc8NQQ9CJiR9M1SB79SEmY2iQW9E_J8xo8BgZQ0GUBrhaWPo-Kn4RnlEcRNzVnlLHQKi5FM7Zpov3SMQUbAeLat38V41y09ap2XVCy7MfL_7-TrSlMx0TLrhWqPgA5aaXbmsT9_vKOoXNZoJ9bWCuA",
"expires_in":300,
"refresh_expires_in":1800,
"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJTRUNSd09fMlZWdGhxUVBUWnFxNHlqX0tKekxnOElSTjBrQkx5UTlacklrIn0.eyJqdGkiOiIxNTUwNDIyZS02OThkLTQ5N2ItODZmYi00YmY5MTFlMTcwYzYiLCJleHAiOjE1MDgzMzM0MjAsIm5iZiI6MCwiaWF0IjoxNTA4MzMxNjIwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvc2Z4LWl0cmFuc2Zlci13ZWItYWdlbnQiLCJhdWQiOiJhZ2VudC13ZWItYXBwIiwic3ViIjoiMzZiMWY4OWMtNGYwMC00OTU1LWE0YzMtZWQ0NzZmZDU2OGM3IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImFnZW50LXdlYi1hcHAiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI0MDgzMWVhYS00ZjJhLTQ5NmUtOTQ1ZC03YmViMTdlNDZlNDQiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidW1hX2F1dGhvcml6YXRpb24iLCJiYWNrLW9mZmljZS1hZ2VudCJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX19.XgYSZWwfaHeY1yZZuwnQ5bj-0IHP4UEmiPTqaeCE1KVyjl3kZz3HJVisndtcKPr05kalS-M_NqU0TaYvbcZ_zesJRIga5sz4gGRqObUmUCUJoQ_iWoOhbM2SutiVnlfgJDACvOxegIcSvakZTgQsEcSweio_0kMFqi-2DYzFp6Rl0TpQ8vALLkc7rEOonUGyt7S4qQzkT-xB1_ZDlSVfm6mC-QKYNZhtqBT18P7MKxBhEgwrJtCytA_4ft7qNAbgvZ3kUohcbhzxGvtHej5RKHNI2wTzwK3IWHbkLWNndxSk_Lzj2-lCx380VpTkVpiDJfq5umjskOmI13dyPF7paA",
"token_type":"bearer",
"not-before-policy":0,
"session_state":"40831eaa-4f2a-496e-945d-7beb17e46e44"
}
This is what ember inspector (Promises) shows:
Here is the stacktrace from the Promise:
Ember Inspector ($E): authenticate/<#http://localhost:4200/assets/vendor.js:77927:9
initializePromise#http://localhost:4200/assets/vendor.js:63591:7
Promise#http://localhost:4200/assets/vendor.js:64067:35
authenticate#http://localhost:4200/assets/vendor.js:77919:14
authenticate#http://localhost:4200/assets/vendor.js:78528:14
authenticate#http://localhost:4200/assets/vendor.js:79420:14
authenticate#http://localhost:4200/assets/sfx-itransfer-web-agent.js:855:9
join#http://localhost:4200/assets/vendor.js:20249:24
run$1.join#http://localhost:4200/assets/vendor.js:37657:12
makeClosureAction/</<#http://localhost:4200/assets/vendor.js:29073:16
exports.flaggedInstrument#http://localhost:4200/assets/vendor.js:37087:14
makeClosureAction/<#http://localhost:4200/assets/vendor.js:29072:15
submit/<#http://localhost:4200/assets/vendor.js:70453:20
tryCatch#http://localhost:4200/assets/vendor.js:63549:14
invokeCallback#http://localhost:4200/assets/vendor.js:63562:15
publish#http://localhost:4200/assets/vendor.js:63532:9
#http://localhost:4200/assets/vendor.js:54458:16
invoke#http://localhost:4200/assets/vendor.js:19948:17
flush#http://localhost:4200/assets/vendor.js:19827:25
flush#http://localhost:4200/assets/vendor.js:20019:25
end#http://localhost:4200/assets/vendor.js:20128:26
run#http://localhost:4200/assets/vendor.js:20212:21
join#http://localhost:4200/assets/vendor.js:20219:24
run$1.join#http://localhost:4200/assets/vendor.js:37657:12
handleEvent/<#http://localhost:4200/assets/vendor.js:58233:18
exports.flaggedInstrument#http://localhost:4200/assets/vendor.js:37087:14
handleEvent#http://localhost:4200/assets/vendor.js:58232:17
_Mixin$create.handleEvent#http://localhost:4200/assets/vendor.js:57385:12
_bubbleEvent#http://localhost:4200/assets/vendor.js:57685:14
setupHandler/<#http://localhost:4200/assets/vendor.js:57619:20
dispatch#http://localhost:4200/assets/vendor.js:5546:16
add/elemData.handle#http://localhost:4200/assets/vendor.js:5355:6
Actually you solution looks like right.
I guess you have a problem in server response or mismatch request methods GET/POST. To solve this try to debug promise inside makeRequest.
return new RSVP.Promise((resolve, reject) => {
fetch(url, options).then((response) => {
response.text().then((text) => { //<-- here debug text
let json = text ? JSON.parse(text) : {};
if (!response.ok) { //<-- and here debug response
response.responseJSON = json;
reject(response);
} else {
resolve(json);
}
});
}).catch(reject);
So if problem will here, just rewrite whole method of makeRequest and add you own promise with custom fetch.
Another way is to write custom Authenticator, overriding authenticate, restore and (optionally) invalidate methods as wrote in documentation: https://github.com/simplabs/ember-simple-auth#implementing-a-custom-authenticator

Categories

Resources