Shopify & VueJs How to hide apiKey and apiPass - vue.js

Im using shopify's admin API in VueJs to make some Api calls. The problem is that I'm fairly sure I have to send the Key and Password a long to get it work. Which means it's exposed on my site. How can i hide it? Or did I use a wrong setup?
I can't find this problem anywhere else, so im fairly sure i'm just stupid. Help! Here's what my code looks like.
async mounted () {
let config = {
headers: {
'X-Shopify-Access-Token': 'Access-Token',
}
}
let apikey = 'apikey ';
let apipass = 'apipass ';
let url = 'url.myshopify.com';
let getrequest = '/admin/api/2020-01/products.json?limit=200';
await axios.get('https://'+ apikey + apipass + '#' + url + getrequest, config)
.then(response => this.products = response.data.products).catch( error => { console.log(error);
});
this.sortAfterCategory();
if(custombundle == true) {
this.custombundle = true;
}
if(this.cart_count >= 3 && actualItems >= 3 || this.custombundle == true) {
return this.EnableAddToCartButton();
}
},
delimiters: ['${', '}'],
});

The correct answer is to install an App in your shop, and setup the App Proxy in that App. Once you do that, you can make calls from your front-end code using JS, and it is all secure and safe, and you can return all the Admin API data you want.

Related

Spotify API - can get my own data, but can't get a user's data if the user is not a registered Spotify API developer

<script>
/* */
import axios from 'axios';
import {onMount} from 'svelte';
let root;
let token;
let tokentype;
let CLIENT_ID = 'e4786b5e94404f12958b48fbb6301176';
let SPOTIFY_AUTHORIZE_ENDPOINT = 'https://accounts.spotify.com/authorize';
let REDIRECT_URI_AFTER_LOGIN = 'http://localhost:8080/';
let PLAYLISTS_ENDPOINT = 'https://api.spotify.com/v1/me/';
let SCOPES = [
'ugc-image-upload',
'user-read-playback-state',
'user-top-read',
'user-read-recently-played',
'playlist-read-private',
'user-read-currently-playing'
];
let SCOPES_MODIFIED = SCOPES.join('%20');
function returnData(hash) {
let stringAfterHashtag = hash.substring(1);
let paramsInUrl = stringAfterHashtag.split('&');
let paramsSplit = paramsInUrl.reduce((accumulater, currentValue) => {
console.log(currentValue);
let [key, value] = currentValue.split('=');
accumulater[key] = value;
return accumulater;
}, {});
return paramsSplit;
}
onMount(() => {
if (window.location.hash) {
let {access_token, token_type, expires_in} = returnData(window.location.hash);
token = access_token;
tokentype = token_type;
}
});
function handleLogin() {
window.location = `${SPOTIFY_AUTHORIZE_ENDPOINT}?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI_AFTER_LOGIN}&scopes=${SCOPES_MODIFIED}&response_type=token&show_dialog=true`;
}
function handleGetPlaylist() {
axios
.get(PLAYLISTS_ENDPOINT, {
headers: {
Authorization: 'Bearer ' + token
}
})
.then(res => {
root = res.data.items;
console.log(res.data.items);
})
.catch(err => {
console.log(err);
});
}
</script>
Here, as you can see, I'm trying to get user playlists. When I tried it on my own account, it worked. But when I tried it on someone's account that is not registered for Spotify API, it didn't work.
Here was the error User not registered in the Developer Dashboard
I want to be able to get every user's playlists if they're logged in. Please help
You get this error, because you'll need a quota extension to let other people use your app now.
You can read here about this change, and read here about the different app modes.

Vue component doesn't show registers from api

Please help with this problem
I'm trying to show registers from an api route (/api/orders)
When I call them from axios, I use get petittion to /api/orders
This is my method:
listarOrdenesIngreso (page,buscar,criterio) {
let me=this;
var url= '/api/orders?page=' + page + '&buscar='+ buscar +'&criterio='+ criterio;
axios.get(url)
.then(function (response) {
var respuesta= response.data;
me.arrayOrders = respuesta.orders.data;
me.pagination = respuesta.pagination;
// handle success
})
........
Here is the API route routes/api.php file
Route::resource('orders', 'EntryOrderController',['except' => ['create','edit']]);
and here the code of controller (EntryOrderController.php file)
public function index(Request $request)
{ if (!$request->ajax()) return redirect('/');
$entries = EntryOrder::all();
//return response()->json(['data' => $entries], 200);
return $this->showAll($entries);
}
The problem It shows in image 1, where not show any register in my vue component When I call them from the URL in the browser, show me correctly the array with data.
I hope you can help me Thanks
Your problem is the request result data not founded
`listarOrdenesIngreso (page,buscar,criterio){
let me=this;
var url= '/api/orders?page=' + page + '&buscar='+ buscar + '&criterio='+ criterio;
axios.get(url)
.then(function (response) {
me.pagination = response.pagination;
me.arrayOrders = response.data.data; // do this
//me.arrayOrders = respuesta.orders.data; // errors here
// handle success
})

API Request in Dialogflow Fulfillment (Javascript)

So I'm trying to make a google action using Dialogflow that requires an external API. I've always used jQuery .getJSON() to make API calls, so I had no idea how to do this. After searching this up online, I found a way to do this using vanilla javascript (I also tested the way on my website and it worked fine). The code for that is below:
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
console.log(xmlhttp.responseText);
}
};
xmlhttp.open("GET", "https://translate.yandex.net/api/v1.5/tr.json/translate?lang=en-es&key=trnsl.1.1.20190105T052356Z.7f8f950adbfaa46e.9bb53211cb35a84da9ce6ef4b30649c6119514a4&text=eat", true);
xmlhttp.send();
}
The code worked fine on my website, but as soon as I added it to the Dialogflow, it would give me the error
XMLHttpRequest is not defined
Obviously that happened because I never defined it (using var), except it worked without me doing anything. So then, I tried adding this line
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
to the code, and it stopped giving me the error (because I defined XMLHttpRequest). But then, my code wouldn't work.
TL;DR: How can I make an external API call using Dialogflow fulfillment?
You can use https. But make sure that you upgrade to Blaze Pay(or any other plans) to make external API calls, else you will receive an error such as
Error:
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions.
Code to make external api call,
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
"use strict";
const functions = require("firebase-functions");
const { WebhookClient } = require("dialogflow-fulfillment");
const { Card, Suggestion } = require("dialogflow-fulfillment");
const https = require("https");
process.env.DEBUG = "dialogflow:debug"; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(
(request, response) => {
const agent = new WebhookClient({ request, response });
console.log(
"Dialogflow Request headers: " + JSON.stringify(request.headers)
);
console.log("Dialogflow Request body: " + JSON.stringify(request.body));
function getWeather() {
return weatherAPI()
.then(chat => {
agent.add(chat);
})
.catch(() => {
agent.add(`I'm sorry.`);
});
}
function weatherAPI() {
const url =
"https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";
return new Promise((resolve, reject) => {
https.get(url, function(resp) {
var json = "";
resp.on("data", function(chunk) {
console.log("received JSON response: " + chunk);
json += chunk;
});
resp.on("end", function() {
let jsonData = JSON.parse(json);
let chat = "The weather is " + jsonData.weather[0].description;
resolve(chat);
});
});
});
}
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
let intentMap = new Map();
intentMap.set("Default Welcome Intent", welcome);
intentMap.set("Default Fallback Intent", fallback);
intentMap.set("Weather Intent", getWeather);
agent.handleRequest(intentMap);
}
);
This article is a diamond! It really helped to clarify what's going on and what's required in Dialogflow fullfilments.
A small suggestion is to gracefully catch the error in the connection to the webservice:
function weatherAPI() {
const url = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";
return new Promise((resolve, reject) => {
https.get(url, function(resp) {
var json = "";
resp.on("data", function(chunk) {
console.log("received JSON response: " + chunk);
json += chunk;
});
resp.on("end", function() {
let jsonData = JSON.parse(json);
let chat = "The weather is " + jsonData.weather[0].description;
resolve(chat);
});
}).on("error", (err) => {
reject("Error: " + err.message);
});
});
}

Node Express redirect not working in Safari in Production

This route redirect is doing exactly what I want in Chrome and Firefox, but for some reason, it is not working in Safari in the production environment:
var express = require('express');
var router = express.Router();
var pool = require('../modules/pg-pool');
router.get('/', async (req, res) => {
var client = await pool.connect();
try {
var stripeConnectState = req.query.state;
var stripeConnectVendorIdResult = await client.query('SELECT vendor_id ' +
'FROM users_vendors ' +
'WHERE stripe_connect_state=$1;',
[stripeConnectState])
client.release();
if (stripeConnectVendorIdResult.rows[0] && stripeConnectVendorIdResult.rows[0].vendor_id) {
var stripeConnectVendorId = stripeConnectVendorIdResult.rows[0].vendor_id;
}
if (stripeConnectVendorId) {
var redirectUrl = [req.protocol, '://', req.get('Host'), '/#/account/vendor/details/', stripeConnectVendorId, '?', req.originalUrl.split("?").pop()].join('');
res.redirect(redirectUrl);
} else {
console.log('There was no vendor id to match the stripe state received');
res.sendStatus(403);
}
} catch (e) {
console.log('Error vendor id GET SQL query task', e);
res.sendStatus(500);
}
});
module.exports = router;
The craziest part to me is that when I I tested locally in Safari, it worked! For some reason, when I deploy to Heroku, it no longer works in production for Safari.
When I test locally, it is redirecting to
http://localhost:5000/#/account/vendor/details/7?state=XXXXXXXXXXXXXXXXXXXXXXXX&scope=read_write&code=ac_XXXXXXXXXXXXXXXXXX
But in production, it is redirecting to the base url
https://www.fairlywed.com/
without the incredibly important query parameters sent along by Stripe. This almost seems like I have a race condition on my hands that never triggers in Chrome or Firefox, but always triggers in Safari.
I'm also wondering if my use of angular-ui-router or the fact that stripe is directing to my site might be involved, but none of those really make a whole lot of sense to me. I might just be grasping at straws at this point.
I found a band-aid fix, but I'm still not sure why this is happening. On production, the req.protocol was coming in as http which is handled by another part of my code:
function redirectChecker (req, res, next) {
if (env === 'production') {
if (req.headers['x-forwarded-proto'] !== 'https') {
var urlAfterConversion = ['https://', req.get('Host'), req.url].join('');
return res.redirect(urlAfterConversion);
}
}
return next();
};
For some reason on Safari, that redirect doesn't work (maybe Safari doesn't accept a redirect followed by a redirect?)
So it failed and redirected to my landing page. I'm still not sure why it solved the problem, but this code is working:
if (stripeConnectVendorId) {
var env = process.env.NODE_ENV || 'development';
var redirectUrl = [req.protocol, '://', req.get('Host'), '/#/account/vendor/details/', stripeConnectVendorId, '?', req.originalUrl.split("?").pop()].join('');
if (env === 'production') {
redirectUrl = 'https:' + redirectUrl.split(':')[1];
}
res.redirect(redirectUrl);
} else {
console.log('There was no vendor id to match the stripe state received');
res.sendStatus(403);
}

Github Api, fetching user email

I would like to make a simple api GET request to get user email based on account name/username.
I am using axios and when I make GET request using this https://api.github.com/users/[username]
I get back everything I need(repository, followers...) except for the user email. It is always null. It would be enough for me to get just the email from users that set it as a public on their profile but no matter what it is set to it will always return null. I am reading that maybe I need authorisation. I made personal Access Token on my github account but how would I use it? What si the best way to get user email?
This is what I have now
import axios from 'axios'
const REQUEST = 'https://api.github.com/users/'
module.exports = {
getData: (accountName) => {
const encodedAccountName = encodeURIComponent(accountName)
const requestUrl = `${REQUEST}${encodedAccountName}`
return axios.get(requestUrl).then((res) => {
return res
})
}
}
Ok. I managed to get this working like this. I simply send a header with personalAccessToken together with request. You can get personal access token on github page under settings/Personal access token/Generate new token and choose user:email for scope. It would be good to use ENV variable now for access token.
import axios from 'axios'
const REQUEST = 'https://api.github.com/users/'
var config = {
headers: {'Authorization': 'token 847762643...'}
}
module.exports = {
getData: (accountName) => {
const encodedAccountName = encodeURIComponent(accountName)
const requestUrl = `${REQUEST}${encodedAccountName}`
return axios.get(requestUrl, config).then(res => {
return res
})
}
}
You can look at the Requestable.js object from GitHub.js tool
It does define the AuthorizationHeader based on a token:
this.__apiBase = apiBase || 'https://api.github.com';
this.__auth = {
token: auth.token,
username: auth.username,
password: auth.password
};
if (auth.token) {
this.__authorizationHeader = 'token ' + auth.token;
} else if (auth.username && auth.password) {
this.__authorizationHeader = 'Basic ' + Base64.encode(auth.username + ':' + auth.password);
}
I was able to get user email from GitHub API using below code.
https://api.github.com/user/emails?access_token=${token}