when user wants to to POST somthing he must be singed in(without username & pass).
Problem is i'm trying to make when CreatePost() invoked it will call SingUser() and based on SingUser() fetch request it will call CreatePost() again to let user post after he sign in.
this is in createpost component
CreatePost(){
fetch(url ,{
method :'POST',
headers:{
Accept:'application/json',
'Content-Type' :'application/json',
},
body: JSON.stringify(post)
}).then((response) => response.json())
.then((responseJson)=>{
if(responseJson.status =='inactive'){
//SignUser
}else{
//post
}
}).catch((error)=>{ //later
});
}
here is SingUser() in other file
async function SignUser() {
try{
User.vtoken = await AsyncStorage.getItem('vtoken');
var userTemp={
vtoken: User.vtoken,
ntoken : User.ntoken
}
fetch(url,{
method :'POST',
headers:{
Accep : 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(userTemp)
}).then((response)=> response.json()).
then((responseJson)=>{
if(responseJson.path == 2){
Save(responseJson, userTemp);}
else return;
}).catch((error)=>{
});
}catch(error){}
}
async function Save(result , userTemp){
try{
await AsyncStorage.setItem('vtoken', result.vtoken);
User.vtoken = result.vtoken;
userTemp.vtoken = result.vtoken;
fetch(url,{
method :'POST',
headers:{
Accep : 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(userTemp)
}).then((response)=>response.json()).
then((responseJson)=>{
return 'done';
}).catch((error)=>{})
}
catch(error){}
}
export {SignUser}
i hope u understand what im trying to do if there is better way to do it thnx:(
You can do something like this:
const errorCodeMap = {
USER_INACTIVE: 10,
}
const statusMap = {
INACTIVE: `inactive`
}
const METHOD = `POST`
const APPLICATION_JSON = `application/json`
const headerDefault = {
Accept: APPLICATION_JSON,
'Content-Type': APPLICATION_JSON,
}
const who = `post`
async function createPost(payload, options) {
try {
const {
url = ``,
fetchOptions = {
method: METHOD,
headers: headerDefault,
},
} = options
const {
post,
} = payload
const response = await fetch(url, {
...fetchOptions,
body: JSON.stringify(post)
})
const {
status,
someUsefulData,
} = await response.json()
if (status === statusMap.INACTIVE) {
return {
data: null,
errors: [{
type: who,
code: errorCodeMap.USER_INACTIVE,
message: `User inactive`
}]
}
} else {
const data = someNormalizeFunction(someUsefulData)
return {
data,
errors: [],
}
}
} catch (err) {
}
}
async function createPostRepeatOnInactive(payload, options) {
try {
const {
repeat = 1,
} = options
let index = repeat
while (index--) {
const { data, errors } = createPost(payload, options)
if (errors.length) {
await signUser()
} else {
return {
data,
errors,
}
}
}
} catch (err) {
}
}
solve it, I did little adjustments
async CreatePost(){
try{
var response = await fetch(url ,{
method :'POST',
headers:{
Accept:'application/json',
'Content-Type' :'application/json',
},
body: JSON.stringify(post)});
var responseJson = await response.json();
if(responseJson.status =='inactive' && postRepeat == true){
postRepeat == false;
await SignUser();
this.CreatePost();
}
else{
//posted
}
}catch(err){}
}
Related
I got following error at file.getSignedUrl. I have other function to copy the file and create new file on Cloud Storage. Why this function need permission and where do I need to set?
Error: The caller does not have permission at Gaxios._request (/layers/google.nodejs.yarn/yarn_modules/node_modules/gaxios/build/src/gaxios.js:129:23) at runMicrotasks () at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Compute.requestAsync (/layers/google.nodejs.yarn/yarn_modules/node_modules/google-auth-library/build/src/auth/oauth2client.js:368:18) at async GoogleAuth.signBlob (/layers/google.nodejs.yarn/yarn_modules/node_modules/google-auth-library/build/src/auth/googleauth.js:662:21) at async sign (/layers/google.nodejs.yarn/yarn_modules/node_modules/#google-cloud/storage/build/src/signer.js:103:35) { name: 'SigningError' }
const functions = require("firebase-functions");
const axios = require("axios");
const { Storage } = require("#google-cloud/storage");
const storage = new Storage();
// Don't forget to replace with your bucket name
const bucket = storage.bucket("projectid.appspot.com");
async function getAlbums() {
const endpoint = "https://api.mydomain.com/graphql";
const headers = {
"content-type": "application/json",
};
const graphqlQuery = {
query: `query Albums {
albums {
id
album_cover
}
}`,
};
const response = await axios({
url: endpoint,
method: "post",
headers: headers,
data: graphqlQuery,
});
if (response.errors) {
functions.logger.error("API ERROR : ", response.errors); // errors if any
} else {
return response.data.data.albums;
}
}
async function updateUrl(id, url) {
const endpoint = "https://api.mydomain.com/graphql";
const headers = {
"content-type": "application/json",
};
const graphqlQuery = {
query: `mutation UpdateAlbum($data: AlbumUpdateInput!, $where:
AlbumWhereUniqueInput!) {
updateAlbum(data: $data, where: $where) {
id
}
}`,
variables: {
data: {
album_cover: {
set: url,
},
},
where: {
id: id,
},
},
};
const response = await axios({
url: endpoint,
method: "post",
headers: headers,
data: graphqlQuery,
});
if (response.errors) {
functions.logger.error("API ERROR : ", response.errors); // errors if any
} else {
return response.data.data.album;
}
}
const triggerBucketEvent = async () => {
const config = {
action: "read",
expires: "03-17-2025",
};
const albums = await getAlbums();
albums.map((album) => {
const resizedFileName = album.id + "_300x200.webp";
const filePath = "images/albums/thumbs/" + resizedFileName;
const file = bucket.file(filePath);
functions.logger.info(file.name);
file.getSignedUrl(config, function (err, url) {
if (err) {
functions.logger.error(err);
return;
} else {
functions.logger.info(
`The signed url for ${resizedFileName} is ${url}.`
);
updateUrl(album.id, url);
}
} );
});
};
exports.updateResizedImageUrl = functions.https.onRequest(async () => {
await triggerBucketEvent();
});
I need to add Service Account Token Creator role for App Engine default service account.
Given is an application for managing users. Following help files are used for this purpose:
AuthenticationAction.js
ManagementAction.js
AuthenticationAction.js is used for authentication:
export function authenticateUser(userID, password) {
console.log("Authenticate")
return dispatch => {
dispatch(getAuthenticateUserPendingAction());
login(userID, password).then(userSession => {
const action = getAuthenticationSuccessAction(userSession);
dispatch(action);
}, error => {
dispatch(getAuthenticationErrorAction(error));
}).catch(error => {
dispatch(getAuthenticationErrorAction(error));
})
}
}
function login(userID, password) {
const hash = Buffer.from(`${userID}:${password}`).toString('base64')
const requestOptions = {
method: 'POST',
headers: {
'Authorization': `Basic ${hash}`
},
};
return fetch('https://localhost:443/authenticate', requestOptions)
.then(handleResponse)
.then(userSession => {
return userSession;
});
}
function handleResponse(response) {
console.log(response)
const authorizationHeader = response.headers.get('Authorization');
return response.text().then(text => {
if (authorizationHeader) {
var token = authorizationHeader.split(" ")[1];
}
if (!response.ok) {
if (response.status === 401) {
logout();
}
const error = response.statusText;
return Promise.reject(error);
} else {
let userSession = {
/* user: data, */
accessToken: token
}
return userSession;
}
});
}
ManagementAction.js is there for the Crud Functions.
export function createUser(userID, username, password) {
console.log("Create a User")
return dispatch => {
dispatch(getShowUserManagementAction());
createaUser(userID, username, password).then(userSession => {
const action = getShowUserManagementActionSuccess(userSession);
dispatch(action);
}, error => { dispatch(getShowUserManagementErrorAction(error)); }).catch(error => { dispatch(getShowUserManagementErrorAction(error)); })
}
}
function createaUser(userID, username, password) {
const token = "whatever"
const requestOptions = {
method: 'POST',
headers: { 'Authorization': `Basic ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ userID: userID, userName: username, password: password })
};
console.log(requestOptions)
return fetch('https://localhost:443/user/', requestOptions)
.then(handleResponse)
.then(userSession => {
return userSession;
});
}
question:
Now if I want to use the createaUser function instead of the hardcoded token value with the accestoken I created in login, how do I get the accesstoken and how do I have to rewrite the createaUser function ?
you can store the token you created in the local storage like this:
AuthenticationAction.js
let userSession = {
/* user: data, */
accessToken: token
}
localStorage.setItem("token", userSession.accessToken)
and you can access it as below:
ManagementAction.js
function createaUser(userID, username, password) {
const token = localStorage.getItem("token")
const requestOptions = {
method: 'POST',
headers: { 'Authorization': `Basic ${token}`, 'Content-Type': 'application/json' },
then
so you can send your token value with the request
I have don't the API check if the token is expired. I have to make a GET call, if I got the 403, error from the API, then I should re-login.
I attempted:
app.get = async (body) => {
return new Promise((resolve, reject) => {
let user = await user.findOne({
where: {
accountId: body.accountId
}
});
if(user){
body.accessToken = user.accessToken;
} else {
body.accessToken = await app.login();
}
request(
{
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + body.accessToken
},
method: 'GET',
uri: `${config.acs.url}${body.url}`,
json: true
}
)
.then((response) => {
resolve(response);
})
.catch((error) => {
// logger.info(error);
if(error.statusCode == 403){
body.accessToken = await app.login(); <<------------- 🐞🐞🐞
app.get(body);
}
reject(error);
});
});
}
I don't know how else to avoid this error.
SyntaxError: await is only valid in an async function
I already have
app.get = async (body) => { ...
I need to re-login only when I get the 403 code in the error block.
How do I re-structure my code to achieve what I described?
The function used in the Promise is not an async function
Try this snippet
app.get = async (body) => {
let resolve, reject;
const promise = new Promise((re, rj) => {
resolve = re;
reject = rj;
});
let user = await user.findOne({
where: {
accountId: body.accountId
}
});
if(user){
body.accessToken = user.accessToken;
} else {
body.accessToken = await app.login();
}
request(
{
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + body.accessToken
},
method: 'GET',
uri: `${config.acs.url}${body.url}`,
json: true
}
)
.then((response) => {
resolve(response);
})
.catch(async (error) => {
// logger.info(error);
if(error.statusCode == 403){
body.accessToken = await app.login(); <<------------- 🐞🐞🐞
app.get(body);
}
reject(error);
});
return promise;
}
Hello after setup a simple async function with promise return i'd like to use then promise instead of try!
But is returning
await is a reserved word
for the second await in the function.
i've tried to place async return promise the data! but did not worked either
async infiniteNotification(page = 1) {
let page = this.state.page;
console.log("^^^^^", page);
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
fetch(`/notifications?page=${page}`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Access: auth_token
},
params: { page }
})
.then(data => data.json())
.then(data => {
var allData = this.state.notifications.concat(data.notifications);
this.setState({
notifications: allData,
page: this.state.page + 1,
});
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
fetch("/notifications/mark_as_read", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Access: auth_token
},
body: JSON.stringify({
notification: {
read: true
}
})
}).then(response => {
this.props.changeNotifications();
});
})
.catch(err => {
console.log(err);
});
}
> await is a reserved word (100:25)
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
^
fetch("/notifications/mark_as_read", {
You should refactor how you make your requests. I would have a common function to handle setting up the request and everything.
const makeRequest = async (url, options, auth_token) => {
try {
// Default options and request method
if (!options) options = {}
options.method = options.method || 'GET'
// always pass a body through, handle the payload here
if (options.body && (options.method === 'POST' || options.method === 'PUT')) {
options.body = JSON.stringify(options.body)
} else if (options.body) {
url = appendQueryString(url, options.body)
delete options.body
}
// setup headers
if (!options.headers) options.headers = {}
const headers = new Headers()
for(const key of Object.keys(options.headers)) {
headers.append(key, (options.headers as any)[key])
}
if (auth_token) {
headers.append('Access', auth_token)
}
headers.append('Accept', 'application/json')
headers.append('Content-Type', 'application/json')
options.headers = headers
const response = await fetch(url, options as any)
const json = await response.json()
if (!response.ok) {
throw json
}
return json
} catch (e) {
console.error(e)
throw e
}
}
appendQueryString is a little helper util to do the get qs params in the url
const appendQueryString = (urlPath, params) => {
const searchParams = new URLSearchParams()
for (const key of Object.keys(params)) {
searchParams.append(key, params[key])
}
return `${urlPath}?${searchParams.toString()}`
}
Now, to get to how you update your code, you'll notice things become less verbose and more extensive.
async infiniteNotification(page = 1) {
try {
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
const data = await makeRequest(
`/notifications`,
{ body: { page } },
auth_token
)
var allData = this.state.notifications.concat(data.notifications);
this.setState({
notifications: allData,
page: this.state.page + 1,
});
const markedAsReadResponse = makeRequest(
"/notifications/mark_as_read",
{
method: "POST",
body: {
notification: { read: true }
},
auth_token
)
this.props.changeNotifications();
} catch (e) {
// TODO handle your errors
}
}
I have a conditional fetch that determines a part of a URL for a subsequent fetch, but I only want it to run in certain conditions.
The following is not waiting and runs the try right away:
async function fetchURLs() {
let sessionWait = false;
if ((check1 === true) && (check2 === false))
{sessionWait = await getURL();
} else {sessionWait = true}
if (sessionWait === true){
try {
var [a, b, c] = await Promise.all([
fetch(dataUrl, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'post',
}).then((response) => response.text()).catch(error => console.log(error.message)),
fetch(settingsUrl).then((response) => response.text()).catch(error => console.log(error.message))
} catch (error) {
console.log(error);
}
});
}
async function getURL(){
let subDomain = 'a';
fetchAdd = "https://" + subDomain + ".dexcom.com/ShareWebServices/Services/General/LoginPublisherAccountByName"
await fetch(fetchAdd, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
}).then((res) => res.json()).then((SessionData) => dataUrl = "https://" + SessionData).catch(error => console.log(error.message));
return true;
}
const tasks = getTaskArray();
return tasks.reduce((promiseChain, currentTask) => {
return promiseChain.then(chainResults =>
currentTask.then(currentResult =>
[ ...chainResults, currentResult ] )
);
}, Promise.resolve([])).then(arrayOfResults => {
// Do something with all results
});
This Link might help you.
https://decembersoft.com/posts/promises-in-serial-with-
array-reduce/