I am trying to make the codes you see here:
https://glitch.com/edit/#!/amusing-swallow?path=index.html:7:68
executable on my node js application. Please note that the codes on that link is working.
What I did is that I set up an environment like this:
root folder
--public
--index.html
--script.js
--app.js
--package.json
And then I copied the html code to my index.html file like this:
<!DOCTYPE html>
<html>
<head>
<title>Spotify Implicit Grant Template</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://sp-bootstrap.global.ssl.fastly.net/8.0.0/sp-bootstrap.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
</head>
<body class="container">
<h1 class="text-salmon">Spotify Implicit Grant Template</h1>
<h3>This app uses the implicit grant authorization flow to authenticate users and get user data.</h3>
<p>
Here are your top artists on Spotify:
<ol id="top-artists"></ol>
</p>
<script src="../script.js" type='text/javascript'></script>
</body>
</html>
Nothing special and then I made the script.js a self invoking function like this:
(function() {
// Get the hash of the url
const hash = window.location.hash
.substring(1)
.split("&")
.reduce(function(initial, item) {
if (item) {
var parts = item.split("=");
initial[parts[0]] = decodeURIComponent(parts[1]);
}
return initial;
}, {});
window.location.hash = "";
// Set token
let _token = hash.access_token;
const authEndpoint = "https://accounts.spotify.com/authorize";
// Replace with your app's client ID, redirect URI and desired scopes
const clientId = "xxxxxxxxxxxxxxxxxxxxxxxx";
const redirectUri = "http://localhost:8888/callback/";
const scopes = ["user-top-read"];
// If there is no token, redirect to Spotify authorization
if (!_token) {
window.location = `${authEndpoint}?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scopes.join(
"%20"
)}&response_type=token&show_dialog=true`;
}
// Make a call using the token
$.ajax({
url:
"https://api.spotify.com/v1/search?query=tania+bowra&offset=0&limit=20&type=artist",
type: "GET",
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + _token);
},
success: function(data) {
// Do something with the returned data
data.items.map(function(artist) {
let item = $("<li>" + artist.name + "</li>");
item.appendTo($("#top-artists"));
});
}
});
})();
And then finally on my app.js for express:
var express = require("express"); // Express web server framework
var app = express();
app.use(express.static(__dirname + "/public"));
console.log("Listening on host 8888......");
app.listen(8888);
So I tried to run this and whenever I visit the localhost:8888, I keep on getting these:
GET http://localhost:8888/script.js 404 (Not Found)
Refused to execute script from 'http://localhost:8888/script.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
I am not sure why. But I just copied the same exact code and just put my credentials there but it won't still work. Any idea what am I doing wrong?
Related
I'm attempting to integrate LinkedIn Learning Single-Sign-On via an LTI connection, however I'm always faced with the response: LTI_FAILED_AUTHENTICATION.
LinkedIn Learning - LTI_FAILED_AUTHENTICATION
When I test it out on the Saltire test platform, it strangely works.
The parameters match what I am sending from the code below:
Saltire LTI Success authentication
Have tried copying over the the values of oauth_nonce, timestamp and oauth_signature from Saltire to my page, and that worked also, which scores out the possibility of domain whitelisting requirement.
LinkedIn support have come back saying there seems to be something wrong with the generated signature, but I'm not sure what is wrong about it, since that is generated by the parameters passed.
Is there something incorrectly setup from my page which I am not seeing?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="robots" content="noindex" />
<title>Access LinkedIn Learning</title>
<script src="bundle.js"></script>
</head>
<body>
<form id="id_frmConnect" name="frmConnect" enctype="application/x-www-form-urlencoded">
</form>
<script>
var oauth = require('oauth-sign');
var action = 'https://www.linkedin.com/checkpoint/enterprise/login/[accountID]?application=learning&redirect=https://www.linkedin.com/learning/me';
var method = 'POST';
var consumer_key = '************';
var consumer_secret = '************';
var timestamp = Math.round(Date.now() / 1000);
var params = {
lti_message_type: 'basic-lti-launch-request',
lti_version: 'LTI-1p0',
oauth_callback: 'about:blank',
oauth_consumer_key: consumer_key,
oauth_nonce: btoa(timestamp),
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: timestamp,
oauth_version: '1.0',
user_id: 'S495696'
};
var signature = oauth.hmacsign(method, action, params, consumer_secret);
params.oauth_signature = signature;
var form = document.querySelector("#id_frmConnect");
form.action = action;
form.method = method;
for (var name in params) {
var node = document.createElement("input");
node.type = 'hidden';
node.name = name;
node.value = params[name];
form.appendChild(node);
}
</script>
</body>
</html>
I figured out the issue. By using the Saltire test tool, I was able to verify that my signature was generated correctly when using their testing URL: https://lti.tools/saltire/tp
You can play with an example here: https://learningcom.github.io/ltitest/index.html
So after looking at the LinkedIn URL, I discovered that the signature was getting generated with an unnecessary long URL which contained parameters.
Removed: ?application=learning&redirect=https://www.linkedin.com/learning/me
Therefore, I shortened the URL to:
var action = 'https://www.linkedin.com/checkpoint/enterprise/login/[accountID]';
No more errors!
I'm having trouble reliably triggering a Firebase Cloud Function via the HTTP trigger method. It doesn't work in all browsers, and sometimes only works if you reload the page. The html webpage is hosted with Firebase Hosting.
Premise is simple, main html page has a button which when pressed, sends the HTTP request to the Cloud Function, and then navigates to another page saying done. The Cloud Function sends an FCM notification and works reliably when manually using the HTTP request url.
Is there something wrong with my HTTP request in scripts.js? What would make this very inconsistent behaviour? It works generally in Chrome, not in Firefox, and sometimes in Edge.
index.html looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel=icon href=favicon.ico>
<title>Title</title>
</head>
<body>
<h1>New heading</h1>
<input type="button" value="Send FCM" onclick="doThing()">
<script src="scripts.js"></script>
</body>
</html>
scripts.js looks like this
var request = require('request')
function doThing(){
const url = '<HTTP request URL>';
request(url, function(error, response, body){
if (!error && response.statusCode == 200){
window.location.href = "outro.html";
}
})
}
and outro.html looks like this;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
<body>
<h1>Cya</h1>
</body>
</body>
</html>
For clarity, this is the Cloud Function script:
const functions = require('firebase-functions');
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.https.onRequest((request, response) =>{
var topic = 'all';
var payload = {
notification:{
title: 'Title!',
body: 'Test!'
},
};
return admin.messaging().sendToTopic(topic, payload).then((res) =>{
response.status(200).send("ok");
return console.log("Success:");
}).catch((err) =>{
console.log("Error: ", err);
response.status(500).send("bad");
});
});
All are deployed with firebase deploy.
My File Structure -
> client-
> -app.js
> index.html
> require.js
> server.js
server.js - to create a basic http server
const http = require('http'),
fs = require('fs');
function send404(response) {
response.writeHead(404, {'Content-Type': 'text/plain'});
response.write('Error 404: Resource not found.');
response.end();
}
const server = http.createServer( (req,res) => {
if(req.method == 'GET' && req.url == '/')
{
res.writeHead(200, {'content-type': 'text/html'});
fs.createReadStream('index.html').pipe(res);
}
else
{
send404(res);
}
}).listen(3000);
console.log('server running on port 3000');```
index.html
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello There</title>
<script
src="require.js"
data-main="client/app.js">
</script>
</head>
<body>
<p>Press Ctrl + Shift + J (windows) or CMD + Opt + J (MacOSX) to open up the console.</p>
</body>
</html>
```
app.js
console.log('Hello RequireJS!');
I am supposed to get Hello RequireJS! as output in the chrome developer tools console.
But, i get 3 errors as shown below:
1.
Denying load of
chrome-extension://laankejkbhbdhmipfmgcngdelahlfoji/app.js. Resources
must be listed in the web_accessible_resources manifest key in order
to be loaded by pages outside the extension.
2.
GET http://localhost:3000/require.js net::ERR_ABORTED 404 (Not Found)
3.
GET chrome-extension://invalid/ net::ERR_FAILED
Please tell me if you have also encountered this problem and how to solve this.
Thanks.
`
I've been experimenting with panels development for Premiere Pro CC 2019, and am now trying to follow the tutorial found on https://medium.com/adobetech/how-to-build-a-node-js-server-in-a-panel-ba1d63ea67e2 on creating a localserver with nodejs alongside a panel, but I can't get it to work
I've uploaded my code here, which doesn't differ much from the tutorial beside updated manifest.xml version numbers: https://github.com/VanMuylemSven/AdobePanelNodeSample
Clicking the panel returns an empty alert, tested in both Premiere Pro CC 2019 and Photoshop CC 2019
Enabling the debug always tells me that the connection is refused, and none of the console logs in the localserver ever get triggered.
Manifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<ExtensionManifest Version="7.0" ExtensionBundleId="com.my.test" ExtensionBundleVersion="1.0.0"
ExtensionBundleName="NodeSamplePanel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ExtensionList>
<Extension Id="com.my.test.panel" Version="1.0" />
<Extension Id="com.my.localserver" Version="1.0" />
</ExtensionList>
<ExecutionEnvironment>
<HostList>
<Host Name="PHXS" Version="14.0" />
<Host Name="PHSP" Version="14.0" />
<Host Name="PPRO" Version="7.0" />
</HostList>
<LocaleList>
<Locale Code="All" />
</LocaleList>
<RequiredRuntimeList>
<RequiredRuntime Name="CSXS" Version="7.0" />
</RequiredRuntimeList>
</ExecutionEnvironment>
<DispatchInfoList>
<Extension Id="com.my.test.panel">
<DispatchInfo >
<Resources>
<MainPath>./client/index.html</MainPath>
<CEFCommandLine>
<Parameter>--allow-file-access</Parameter>
<Parameter>--allow-file-access-from-files</Parameter>
<Parameter>--enable-nodejs</Parameter>
<Parameter>--mixed-context</Parameter>
</CEFCommandLine>
<ScriptPath>./host/index.jsx</ScriptPath>
</Resources>
<Lifecycle>
<AutoVisible>true</AutoVisible>
</Lifecycle>
<UI>
<Type>Panel</Type>
<Menu>NodeJS SAMPLE PANEL</Menu>
<Geometry>
<Size>
<Height>540</Height>
<Width>600</Width>
</Size>
</Geometry>
</UI>
</DispatchInfo>
</Extension>
<Extension Id="com.my.localserver">
<DispatchInfo>
<Resources>
<MainPath>./client/localServer.html</MainPath>
<CEFCommandLine>
<Parameter>--allow-file-access</Parameter>
<Parameter>--allow-file-access-from-files</Parameter>
<Parameter>--enable-nodejs</Parameter>
<Parameter>--mixed-context</Parameter>
</CEFCommandLine>
</Resources>
<Lifecycle>
<AutoVisible>false</AutoVisible>
</Lifecycle>
<UI>
<Type>Custom</Type>
<Icons />
</UI>
</DispatchInfo>
</Extension>
</DispatchInfoList>
</ExtensionManifest>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Your First Fullstack Panel</title>
<script>
console.log(" console log in index.html test " );
</script>
</head>
<body>
<!-- Simple HTML UI elements to get us started. -->
<h1>Your First Full Stack Panel</h1>
<button id="import-button">Import from external server</button>
<!-- Add you dependencies here -->
<script src="../lib/jquery-1.9.1.js"></script>
<script src="CSInterface.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js
/* Create an instance of CSInterface. */
var csInterface = new CSInterface();
/* Load your server extension */
csInterface.requestOpenExtension("com.my.localserver", "");
/* Make a reference to your HTML button and add a click handler. */
var openButton = document.querySelector("#import-button");
openButton.addEventListener("click", importDoc);
if (typeof(require) !== 'undefined') {
alert("Node.js is enabled");
} else {
alert("Node.js is disabled");
}
/* Get the path for your panel */
var extensionDirectory = csInterface.getSystemPath("extension");
function importDoc() {
/* Make sure to include the full URL */
//https://www.countryflags.io/be/flat/64.png //Test url, this one returns a success, but doesn't execute server code?
console.log("Function: importDoc()");
console.log("extensiondirectory = " + extensionDirectory);
var url = "http://localhost:3200/import"; //Port 8088 atleast returns "Not Found"-error instead of nothing, but that might be becuase of the .debug port.
console.log("communicating with server");
/* Use ajax to communicate with your server */
$.ajax({
type: "GET",
url: url,
headers: {
"directory": extensionDirectory
},
success: response => {
/* Use the ExtendScript function to display the downloaded file */
console.log("SUCCESS IN RESPONSE");
csInterface.evalScript(`openDocument("${response}")`);
},
error: (jqXHR, textStatus, errorThrown) => {
console.log(jqXHR);
console.log(" ///textstatus= " + textStatus);
console.log(" /// errorthrown= " + errorThrown);
alert(errorThrown, jqXHR.responseJSON);
}
})
}
localserver.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
console.log(" ============== localserver.html ================= " );
console.log(__dirname + + '/server/main.js');
/* This script uses cep_node to start the Node.js server located at '/server/main.js' */
var localServer = cep_node.require(__dirname + '/server/main.js')();
</script>
<title>Import Example App</title>
</head>
<body>
</body>
</html>
server/main.js
/* npm Modules */
const express = require("express");
const app = express();
const request = require('request');
const http = require('http');
const path = require("path");
const bodyParser = require("body-parser");
const fs = require('fs');
const httpServer = http.Server(app);
console.log("main.js code started");
module.exports = run
function run(){
console.log("//////////////////////////////////////")
console.log("SERVER CODE")
var port = 3200;
var hostname = "localhost"
/* Start the server */
httpServer.listen(port, hostname);
/* Middlewares */
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ limit: '50mb',extended: true }));
app.use(express.static(path.join(__dirname, "../client")));
/* /import route that can be hit from the client side */
app.get("/import", (req, res, next) => {
console.log(" ========================= app.get ===========================");
/* Get the directory path from the header and name the file */
var path = req.headers["directory"] + "/placeholder.png"
/* This is an example URL */
var uri = "http://via.placeholder.com/350x150";
/* write a helper function to download the image and save it */
var saveImage = function(uri, filepath, callback){
request.head(uri, function(err, res, body){
request(uri).pipe(fs.createWriteStream(filepath)).on('close', callback);
});
};
saveImage(uri, path, function(){
/* Send the path back to the client side */
res.status(200).send(path)
});
});
}
host/index.jsx
// function openDocument(){
// var fileRef = new File("~/Downloads/MyFile.jpg");
// var docRef = app.open(fileRef);
// }
function openDocument(location){
var fileRef = new File(location);
var docRef = app.open(fileRef);
}
Is there something blatantly ovious I'm doing wrong? Does this have something to do with the wrong version numbers in the manifest.xml? I really don't know why the server wouldn't even start or give any feedback seeing as nodejs itself is definitely enabled, any help would be appreciated.
There's a comment on the article which was originally posted here:
https://community.adobe.com/t5/premiere-pro/cannot-get-csinterface-to-open-extension-server-invisibly-alongside-panel/td-p/10437661 by sven-vm
He says replace:
<UI>
<Type>Custom</Type>
<Icons />
</UI>
with
<UI>
<Type>Custom</Type>
<Geometry>
<Size>
<Height>600</Height>
<Width>600</Width>
</Size>
</Geometry>
</UI>
This worked for me.
I am using the following two files attached.
index2.html file located on the local server which is calling the JavaScript file which is also located on the local machine
fetch-ajax3.js - JavaScript file located on the local server consisting of the function and method to authenticate and authorize the API call and retreive data and post it in the console.
I am not sure what to input in redirect URI.
Can someone help?
Resolution - i was able to resolve the issue after whitelisting the callback uri in the spotify api app.
const hash = window.location.hash
.substring(1)
.split('&')
.reduce(function (initial, item) {
if (item) {
var parts = item.split('=');
initial[parts[0]] = decodeURIComponent(parts[1]);
}
return initial;
}, {});
window.location.hash = '';
// Set token
let _token = hash.access_token;
const authEndpoint = 'https://accounts.spotify.com/authorize';
// Replace with your app's client ID, redirect URI and desired scopes
const clientId = '';
const redirectUri = '';
const scopes = [
'user-top-read'
];
// If there is no token, redirect to Spotify authorization
if (!_token) {
window.location = `${authEndpoint}?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scopes.join('%20')}&response_type=token&show_dialog=true`;
}
// Make a call using the token
$.ajax({
url: "https://api.spotify.com/v1/me/top/artists",
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Bearer ' + _token );},
success: function(data) {
// Do something with the returned data
data.items.map(function(artist) {
let item = $('<li>' + artist.name + '</li>');
item.appendTo($('#top-artists'));
});
}
});
<html>
<head>
<title>Spotify Implicit Grant Template</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://sp-bootstrap.global.ssl.fastly.net/8.0.0/sp-bootstrap.min.css" rel="stylesheet" />
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="./fetch-ajax3.js" defer></script>
</head>
<body class="container">
<h1 class="text-salmon">Spotify Implicit Grant Template</h1>
<h3>This app uses the implicit grant authorization flow to authenticate users and get user data.</h3>
<p>
Here are your top artists on Spotify:
<ol id="top-artists"></ol>
</body>
</html>
After whitelisting the callback url in the app , i was able to connect it.
specify your URL as Http for localhost in the app settings in your Spotify dashboard
You need to add your URL in Redirect URI which will whitelist your URL. It works for me.