diff --git a/client/src/components/windows/settings/IntegrationSettingsEditor.tsx b/client/src/components/windows/settings/IntegrationSettingsEditor.tsx
index 7bd4615..18df746 100644
--- a/client/src/components/windows/settings/IntegrationSettingsEditor.tsx
+++ b/client/src/components/windows/settings/IntegrationSettingsEditor.tsx
@@ -13,6 +13,7 @@ import { testSpotify } from '../../../lib/integration/spotify/spotifyClientCreds
let _ = require('lodash')
interface EditIntegrationProps {
+ upstreamId: number | null,
integration: serverApi.IntegrationDetailsResponse,
original: serverApi.IntegrationDetailsResponse,
editing: boolean,
@@ -112,8 +113,8 @@ function EditIntegration(props: EditIntegrationProps) {
{!props.submitting && { props.onDelete(); }}
>}
- {!props.submitting && }
{props.submitting && }
@@ -231,6 +232,7 @@ export default function IntegrationSettingsEditor(props: {}) {
{editors === null && }
{editors && <>
{editors.map((state: EditorState) => {
}
// Set up integration proxies
- useSpotifyClientCreds(app);
+ app.use('/integrations', checkLogin(), createIntegrations(knex));
// Set up REST API endpoints
app.post(apiBaseUrl + api.CreateSongEndpoint, checkLogin(), _invoke(PostSong));
diff --git a/server/integrations/integrations.ts b/server/integrations/integrations.ts
new file mode 100644
index 0000000..1b34416
--- /dev/null
+++ b/server/integrations/integrations.ts
@@ -0,0 +1,110 @@
+import Knex from "knex";
+import { IntegrationType } from "../../client/src/api";
+
+const { createProxyMiddleware } = require('http-proxy-middleware');
+let axios = require('axios')
+let qs = require('querystring')
+
+async function getSpotifyCCAuthToken(clientId: string, clientSecret: string) {
+ console.log("Details: ", clientId, clientSecret);
+
+ let buf = Buffer.from(clientId + ':' + clientSecret)
+ let encoded = buf.toString('base64');
+
+ let response = await axios.post(
+ 'https://accounts.spotify.com/api/token',
+ qs.stringify({ 'grant_type': 'client_credentials' }),
+ {
+ 'headers': {
+ 'Authorization': 'Basic ' + encoded,
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ }
+ }
+ );
+
+ if (response.status != 200) {
+ throw new Error("Unable to get a Spotify auth token.")
+ }
+
+ return (await response).data.access_token;
+}
+
+export function createIntegrations(knex: Knex) {
+ // This will enable the app to redirect requests like:
+ // /integrations/5/v1/search?q=query
+ // To the external API represented by integration 5, e.g. for spotify:
+ // https://api.spotify.com/v1/search?q=query
+ // Requests need to already have a .user.id set.
+
+ let proxySpotifyCC = createProxyMiddleware({
+ target: 'https://api.spotify.com/',
+ changeOrigin: true,
+ logLevel: 'debug',
+ pathRewrite: (path: string, req: any) => {
+ // Remove e.g. "/integrations/5"
+ console.log("Rewrite URL:", path);
+ return path.replace(/^\/integrations\/[0-9]+/, '');
+ }
+ });
+
+ // In the first layer, retrieve integration details and save details
+ // in the request.
+ return async (req: any, res: any, next: any) => {
+ // Determine the integration to use.
+ req._integrationId = parseInt(req.url.match(/^\/([0-9]+)/)[1]);
+ console.log("URL:", req.url, 'match:', req._integrationId)
+ if (!req._integrationId) {
+ res.status(400).send({ reason: "An integration ID should be provided in the URL." });
+ return;
+ }
+ req._integration = (await knex.select(['id', 'name', 'type', 'details'])
+ .from('integrations')
+ .where({ 'user': req.user.id, 'id': req._integrationId }))[0];
+ if (!req._integration) {
+ res.status(404).send();
+ return;
+ }
+
+ req._integration.details = JSON.parse(req._integration.details);
+
+ switch (req._integration.type) {
+ case IntegrationType.SpotifyClientCredentials: {
+ console.log("Integration: ", req._integration)
+ // FIXME: persist the token
+ req._access_token = await getSpotifyCCAuthToken(
+ req._integration.details.clientId,
+ req._integration.details.clientSecret,
+ )
+ if (!req._access_token) {
+ res.status(500).send({ reason: "Unable to get Spotify auth token." })
+ }
+ req.headers["Authorization"] = "Bearer " + req._access_token;
+ return proxySpotifyCC(req, res, next);
+ }
+ default: {
+ res.status(500).send({ reason: "Unsupported integration type " + req._integration.type })
+ }
+ }
+ };
+
+
+
+ // // First add a layer which creates a token and saves it in the request.
+ // app.use((req: any, res: any, next: any) => {
+ // updateToken('c3e5e605e7814cdf94cd86eeba6f4c4f', '5d870c84a3c34aa3a4cf803aa95cb96a')
+ // .then(() => {
+ // req._access_token = authToken;
+ // next();
+ // })
+ // })
+ // app.use(
+ // '/spotifycc',
+ // createProxyMiddleware({
+ // target: 'https://api.spotify.com/',
+ // changeOrigin: true,
+ // onProxyReq: onProxyReq,
+ // logLevel: 'debug',
+ // pathRewrite: { '^/spotifycc': '' },
+ // })
+ // )
+}
\ No newline at end of file
diff --git a/server/integrations/spotifyClientCreds.ts b/server/integrations/spotifyClientCreds.ts
deleted file mode 100644
index 5ebfd70..0000000
--- a/server/integrations/spotifyClientCreds.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-const { createProxyMiddleware } = require('http-proxy-middleware');
-let axios = require('axios')
-let qs = require('querystring')
-
-// The authorization token to use with the Spotify API.
-// Will need to be refreshed once in a while.
-var authToken: string | null = null;
-
-async function updateToken(clientId: string, clientSecret: string) {
- if (authToken) { return; }
-
- let buf = Buffer.from(clientId + ':' + clientSecret)
- let encoded = buf.toString('base64');
-
- let response = await axios.post(
- 'https://accounts.spotify.com/api/token',
- qs.stringify({ 'grant_type': 'client_credentials' }),
- {
- 'headers': {
- 'Authorization': 'Basic ' + encoded,
- 'Content-Type': 'application/x-www-form-urlencoded'
- }
- }
- );
-
- authToken = (await response).data.access_token;
-}
-
-let onProxyReq = (proxyReq: any, req: any, res: any) => {
- proxyReq.setHeader("Authorization", "Bearer " + req._access_token)
-
- console.log("Proxying request",
- {
- 'path': req.path,
- 'originalUrl': req.originalUrl,
- 'baseUrl': req.baseUrl,
- },
- {
- 'path': proxyReq.path,
- 'originalUrl': proxyReq.originalUrl,
- 'baseUrl': req.baseUrl,
- },
- );
-}
-
-export function useSpotifyClientCreds(app: any) {
- // First add a layer which creates a token and saves it in the request.
- app.use((req: any, res: any, next: any) => {
- updateToken('c3e5e605e7814cdf94cd86eeba6f4c4f', '5d870c84a3c34aa3a4cf803aa95cb96a')
- .then(() => {
- req._access_token = authToken;
- next();
- })
- })
- app.use(
- '/spotifycc',
- createProxyMiddleware({
- target: 'https://api.spotify.com/',
- changeOrigin: true,
- onProxyReq: onProxyReq,
- logLevel: 'debug',
- pathRewrite: { '^/spotifycc': '' },
- })
- )
-}
\ No newline at end of file