diff --git a/backend/config.schema.json b/backend/config.schema.json new file mode 100644 index 0000000..4a0a782 --- /dev/null +++ b/backend/config.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "foss", + "hosted" + ], + "default": "foss", + "description": "Mode to use for the login. If set to hosted, sdk configuration needs to be complete" + }, + "clientMode": { + "type": "string", + "enum": [ + "sse", + "poll" + ], + "default": "poll", + "description": "Default information retrieval mode for the basic remote displays. Polling is slightly cheaper at the cost of responsiveness" + }, + "webUrl": { + "type": "string", + "description": "The URL to the frontend. Just the host, in form https://music.janishutz.com" + } + } +} diff --git a/backend/config/config.json b/backend/config/config.json new file mode 100644 index 0000000..18b2732 --- /dev/null +++ b/backend/config/config.json @@ -0,0 +1,4 @@ +{ + "$schema": "../config.schema.json", + "mode": "foss" +} diff --git a/backend/src/app.ts b/backend/src/app.ts index 9b4a449..c6df1b9 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -1,14 +1,13 @@ -import cors from 'cors'; +import devtoken from './routes/devtoken'; import express from 'express'; import expressSession from 'express-session'; -import fs from 'fs'; -import jwt from 'jsonwebtoken'; import path from 'path'; const run = () => { const app = express(); + // TODO: Use db store for this (via sdk or stubs) app.use( expressSession( { 'secret': 'dev', 'resave': true, @@ -16,45 +15,19 @@ const run = () => { } ) ); - app.get( '/', ( request: express.Request, response: express.Response ) => { + app.get( '/', ( _request: express.Request, response: express.Response ) => { response.send( 'HELLO WORLD' ); } ); - - const privateKey = fs.readFileSync( path.join( - __dirname, - '/config/apple_private_key.p8' - ) ).toString(); - const musicApiConfig = JSON.parse( fs.readFileSync( path.join( - __dirname, - '/config/apple-music-api.config.secret.json' - ) ).toString() ); - - app.get( '/dev-token', cors( { - 'origin': 'http://localhost:8081', - 'credentials': true - } ), ( _request: express.Request, response: express.Response ) => { - // sign dev token - const now = new Date().getTime(); - const tomorrow = now + ( 24 * 3600 * 1000 ); - const jwtToken = jwt.sign( { - 'iss': musicApiConfig.teamID, - 'iat': Math.floor( now / 1000 ), - 'exp': Math.floor( tomorrow / 1000 ) - }, privateKey, { - 'algorithm': 'ES256', - 'keyid': musicApiConfig.keyID - } ); - - response.send( jwtToken ); - } ); - app.use( ( _request: express.Request, response: express.Response ) => { response.sendFile( path.join( __dirname, '' ) ); } ); + devtoken.routes( app ); + + const PORT = process.env.PORT || 8080; app.listen( PORT ); diff --git a/backend/src/routes/devtoken.ts b/backend/src/routes/devtoken.ts new file mode 100644 index 0000000..1d5354e --- /dev/null +++ b/backend/src/routes/devtoken.ts @@ -0,0 +1,39 @@ +import cors from 'cors'; +import express from 'express'; +import fs from 'fs'; +import jwt from 'jsonwebtoken'; +import path from 'path'; + +const routes = ( app: express.Application ) => { + const privateKey = fs.readFileSync( path.join( + __dirname, + '/../config/apple_private_key.p8' + ) ).toString(); + const musicApiConfig = JSON.parse( fs.readFileSync( path.join( + __dirname, + '/../config/apple-music-api.config.secret.json' + ) ).toString() ); + + app.get( '/dev-token', cors( { + 'origin': 'http://localhost:8081', + 'credentials': true + } ), ( _request: express.Request, response: express.Response ) => { + // sign dev token + const now = new Date().getTime(); + const tomorrow = now + ( 24 * 3600 * 1000 ); + const jwtToken = jwt.sign( { + 'iss': musicApiConfig.teamID, + 'iat': Math.floor( now / 1000 ), + 'exp': Math.floor( tomorrow / 1000 ) + }, privateKey, { + 'algorithm': 'ES256', + 'keyid': musicApiConfig.keyID + } ); + + response.send( jwtToken ); + } ); +}; + +export default { + routes +} diff --git a/backend/src/routes/room/index.ts b/backend/src/routes/room/index.ts new file mode 100644 index 0000000..93f82a4 --- /dev/null +++ b/backend/src/routes/room/index.ts @@ -0,0 +1,20 @@ +import express from 'express'; +import tracking from './tracking'; +import update from './update'; + +const routes = ( app: express.Application ) => { + tracking.routes( app ); + update.routes( app ); + + app.get( '/room/create', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/close', ( request: express.Request, response: express.Response ) => { + + } ); +}; + +export default { + routes +}; diff --git a/backend/src/routes/room/tracking.ts b/backend/src/routes/room/tracking.ts new file mode 100644 index 0000000..7132378 --- /dev/null +++ b/backend/src/routes/room/tracking.ts @@ -0,0 +1,24 @@ +import express from 'express'; + +const routes = ( app: express.Application ) => { + app.get( '/room/:id/tracking/exit', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/tracking/ping', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/tracking/connect', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/admin', ( request: express.Request, response: express.Response ) => { + // Endpoint for the streamer to connect to, all above events are sent there + + } ); +}; + +export default { + routes +}; diff --git a/backend/src/routes/room/update.ts b/backend/src/routes/room/update.ts new file mode 100644 index 0000000..2cc6b4d --- /dev/null +++ b/backend/src/routes/room/update.ts @@ -0,0 +1,23 @@ +import express from 'express'; + +const routes = ( app: express.Application ) => { + app.get( '/room/:id/connect', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/poll', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/update/playlist', ( request: express.Request, response: express.Response ) => { + + } ); + + app.get( '/room/:id/update/state', ( request: express.Request, response: express.Response ) => { + + } ); +}; + +export default { + routes +}; diff --git a/backend/src/routes/user/index.ts b/backend/src/routes/user/index.ts new file mode 100644 index 0000000..b30205d --- /dev/null +++ b/backend/src/routes/user/index.ts @@ -0,0 +1,11 @@ +import express from 'express'; + +const routes = ( app: express.Application ) => { + app.get( '/user/playlists', ( request: express.Request, response: express.Response ) => { + + } ); + + app.post( '/user/playlists', ( request: express.Request, response: express.Response ) => { + + } ); +}; diff --git a/backend/src/sdk/store-sdk-stub.ts b/backend/src/sdk/store-sdk-stub.ts index 02cda1f..5052d2f 100644 --- a/backend/src/sdk/store-sdk-stub.ts +++ b/backend/src/sdk/store-sdk-stub.ts @@ -1,15 +1,12 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars const getSubscriptions = ( _uid: string ) => { - return [ - { - 'id': 'com.janishutz.MusicPlayer.subscription', - 'expires': new Date().getTime() + 200000, - 'status': true - } - ]; + return [ { + 'id': 'com.janishutz.MusicPlayer.subscription', + 'expires': new Date().getTime() + 200000, + 'status': true + } ]; }; export default { - getSubscriptions, + getSubscriptions }; -