mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
Integrate new account backend
This commit is contained in:
7245
backend/package-lock.json
generated
7245
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,42 +1,43 @@
|
|||||||
{
|
{
|
||||||
"name": "musicplayer-v2-backend",
|
"name": "musicplayer-v2-backend",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "The backend for MusicPlayerV2",
|
"description": "The backend for MusicPlayerV2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/simplePCBuilding/MusicPlayerV2.git"
|
"url": "git+https://github.com/simplePCBuilding/MusicPlayerV2.git"
|
||||||
},
|
},
|
||||||
"author": "Janis Hutz",
|
"author": "Janis Hutz",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/simplePCBuilding/MusicPlayerV2/issues"
|
"url": "https://github.com/simplePCBuilding/MusicPlayerV2/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/simplePCBuilding/MusicPlayerV2#readme",
|
"homepage": "https://github.com/simplePCBuilding/MusicPlayerV2#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.29.0",
|
"@eslint/js": "^9.29.0",
|
||||||
"@stylistic/eslint-plugin": "^5.0.0",
|
"@stylistic/eslint-plugin": "^5.0.0",
|
||||||
"@types/express-session": "^1.18.0",
|
"@types/express-session": "^1.18.0",
|
||||||
"eslint-plugin-vue": "^10.2.0",
|
"eslint-plugin-vue": "^10.2.0",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"typescript-eslint": "^8.35.0"
|
"typescript-eslint": "^8.35.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/body-parser": "^1.19.5",
|
"@janishutz/login-sdk-server": "^1.2.0",
|
||||||
"@types/cors": "^2.8.17",
|
"@janishutz/login-sdk-server-stubs": "^1.0.0",
|
||||||
"@types/express": "^4.17.21",
|
"@janishutz/store-sdk": "^1.0.0",
|
||||||
"@types/jsonwebtoken": "^9.0.6",
|
"@types/body-parser": "^1.19.5",
|
||||||
"body-parser": "^1.20.2",
|
"@types/cors": "^2.8.17",
|
||||||
"cors": "^2.8.5",
|
"@types/express": "^4.17.21",
|
||||||
"express": "^4.19.2",
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"express-session": "^1.18.0",
|
"body-parser": "^1.20.2",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"cors": "^2.8.5",
|
||||||
"node-mysql": "^0.4.2",
|
"express": "^4.19.2",
|
||||||
"oauth-janishutz-client-server": "file:../../oauth/client/server/dist",
|
"express-session": "^1.18.0",
|
||||||
"socket.io": "^4.7.5",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"store.janishutz.com-sdk": "file:../../store/sdk/dist"
|
"node-mysql": "^0.4.2",
|
||||||
}
|
"socket.io": "^4.7.5"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,48 +3,58 @@ import db from './storage/db';
|
|||||||
|
|
||||||
const createUser = ( uid: string, username: string, email: string ): Promise<boolean> => {
|
const createUser = ( uid: string, username: string, email: string ): Promise<boolean> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
db.writeDataSimple( 'users', 'uid', uid, { 'uid': uid, 'username': username, 'email': email } ).then( () => {
|
db.writeDataSimple( 'users', 'uid', uid, {
|
||||||
|
'uid': uid,
|
||||||
|
'username': username,
|
||||||
|
'email': email
|
||||||
|
} ).then( () => {
|
||||||
resolve( true );
|
resolve( true );
|
||||||
} ).catch( err => {
|
} )
|
||||||
reject( err );
|
.catch( err => {
|
||||||
} );
|
reject( err );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
};
|
||||||
|
|
||||||
const saveUserData = ( uid: string, data: object ): Promise<boolean> => {
|
const saveUserData = ( uid: string, data: object ): Promise<boolean> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
db.writeDataSimple( 'users', 'uid', uid, { 'data': data } ).then( () => {
|
db.writeDataSimple( 'users', 'uid', uid, {
|
||||||
|
'data': data
|
||||||
|
} ).then( () => {
|
||||||
resolve( true );
|
resolve( true );
|
||||||
} ).catch( err => {
|
} )
|
||||||
reject( err );
|
.catch( err => {
|
||||||
} );
|
reject( err );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
};
|
||||||
|
|
||||||
const checkUser = ( uid: string ): Promise<boolean> => {
|
const checkUser = ( uid: string ): Promise<boolean> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
db.checkDataAvailability( 'users', 'uid', uid ).then( res => {
|
db.checkDataAvailability( 'users', 'uid', uid ).then( res => {
|
||||||
resolve( res );
|
resolve( res );
|
||||||
} ).catch( err => {
|
|
||||||
reject( err );
|
|
||||||
} )
|
} )
|
||||||
|
.catch( err => {
|
||||||
|
reject( err );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
const getUserData = ( uid: string ): Promise<object> => {
|
const getUserData = ( uid: string ): Promise<object> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
db.getDataSimple( 'users', 'uid', uid ).then( data => {
|
db.getDataSimple( 'users', 'uid', uid ).then( data => {
|
||||||
resolve( data );
|
resolve( data );
|
||||||
} ).catch( err => {
|
} )
|
||||||
reject( err );
|
.catch( err => {
|
||||||
} );
|
reject( err );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createUser,
|
createUser,
|
||||||
saveUserData,
|
saveUserData,
|
||||||
checkUser,
|
checkUser,
|
||||||
getUserData
|
getUserData
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import path from 'path';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import account from './account';
|
|
||||||
import sdk from 'oauth-janishutz-client-server';
|
|
||||||
import {
|
import {
|
||||||
createServer
|
createServer
|
||||||
} from 'node:http';
|
} from 'node:http';
|
||||||
@@ -15,26 +13,19 @@ import crypto from 'node:crypto';
|
|||||||
import type {
|
import type {
|
||||||
Room, Song
|
Room, Song
|
||||||
} from './definitions';
|
} from './definitions';
|
||||||
import storeSDK from 'store.janishutz.com-sdk';
|
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
|
|
||||||
|
|
||||||
|
// ┌ ┐
|
||||||
|
// │ Handle FOSS vs paid version │
|
||||||
|
// └ ┘
|
||||||
const isFossVersion = true;
|
const isFossVersion = true;
|
||||||
|
|
||||||
declare let __dirname: string | undefined;
|
import storeSDK from '@janishutz/store-sdk';
|
||||||
|
import sdk from '@janishutz/login-sdk-server';
|
||||||
|
// import storeSDK from './sdk/store-sdk-stub';
|
||||||
|
// import sdk from '@janishutz/login-sdk-server-stubs';
|
||||||
|
|
||||||
if ( typeof __dirname === 'undefined' ) {
|
|
||||||
__dirname = path.resolve( path.dirname( '' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Change config file, as well as in main.ts, index.html, oauth, if deploying there
|
|
||||||
// const sdkConfig = JSON.parse( fs.readFileSync( path.join(
|
|
||||||
// __dirname,
|
|
||||||
// '/config/sdk.config.testing.json'
|
|
||||||
// ) ).toString() );
|
|
||||||
const sdkConfig = JSON.parse( fs.readFileSync( path.join(
|
|
||||||
__dirname,
|
|
||||||
'/config/sdk.config.secret.json'
|
|
||||||
) ).toString() );
|
|
||||||
|
|
||||||
const run = () => {
|
const run = () => {
|
||||||
const app = express();
|
const app = express();
|
||||||
@@ -45,10 +36,6 @@ const run = () => {
|
|||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
if ( !isFossVersion ) {
|
if ( !isFossVersion ) {
|
||||||
// storeSDK.configure( JSON.parse( fs.readFileSync( path.join(
|
|
||||||
// __dirname,
|
|
||||||
// '/config/store-sdk.config.testing.json'
|
|
||||||
// ) ).toString() ) );
|
|
||||||
storeSDK.configure( JSON.parse( fs.readFileSync( path.join(
|
storeSDK.configure( JSON.parse( fs.readFileSync( path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'/config/store-sdk.config.secret.json'
|
'/config/store-sdk.config.secret.json'
|
||||||
@@ -58,26 +45,49 @@ const run = () => {
|
|||||||
const httpServer = createServer( app );
|
const httpServer = createServer( app );
|
||||||
|
|
||||||
if ( !isFossVersion ) {
|
if ( !isFossVersion ) {
|
||||||
|
const sdkConfig = JSON.parse( fs.readFileSync( path.join(
|
||||||
|
__dirname,
|
||||||
|
'/config/sdk.config.secret.json'
|
||||||
|
) ).toString() );
|
||||||
|
|
||||||
// Load id.janishutz.com SDK and allow signing in
|
// Load id.janishutz.com SDK and allow signing in
|
||||||
sdk.routes( app, ( uid: string ) => {
|
sdk.setUp(
|
||||||
return new Promise( ( resolve, reject ) => {
|
{
|
||||||
account.checkUser( uid ).then( stat => {
|
'prod': false,
|
||||||
resolve( stat );
|
'service': {
|
||||||
} )
|
'serviceID': 'jh-music',
|
||||||
.catch( e => {
|
'serviceToken': sdkConfig[ 'token' ]
|
||||||
reject( e );
|
},
|
||||||
} );
|
'user-agent': sdkConfig[ 'ua' ],
|
||||||
} );
|
'sessionType': 'memory',
|
||||||
}, ( uid: string, email: string, username: string ) => {
|
'frontendURL': 'https://music.janishutz.com',
|
||||||
return new Promise( ( resolve, reject ) => {
|
'corsWhitelist': [ 'https://music.janishutz.com' ],
|
||||||
account.createUser( uid, username, email ).then( stat => {
|
'recheckTimeout': 300 * 1000,
|
||||||
resolve( stat );
|
'advancedVerification': 'sdk'
|
||||||
} )
|
},
|
||||||
.catch( e => {
|
app,
|
||||||
reject( e );
|
() => {
|
||||||
} );
|
return new Promise( resolve => {
|
||||||
} );
|
resolve( true );
|
||||||
}, sdkConfig );
|
} );
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
return new Promise( resolve => {
|
||||||
|
resolve( true );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
return new Promise( resolve => {
|
||||||
|
resolve( true );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
return new Promise( resolve => {
|
||||||
|
resolve( true );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
sdkConfig
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Websocket for events
|
// Websocket for events
|
||||||
@@ -291,7 +301,7 @@ const run = () => {
|
|||||||
} ) }\n\n` );
|
} ) }\n\n` );
|
||||||
const sid = sdk.getSessionID( request );
|
const sid = sdk.getSessionID( request );
|
||||||
|
|
||||||
if ( sdk.checkAuth( request ) ) {
|
if ( sdk.getSignedIn( request ) ) {
|
||||||
importantClients[ sid ] = {
|
importantClients[ sid ] = {
|
||||||
'response': response,
|
'response': response,
|
||||||
'room': String( request.query.room )
|
'room': String( request.query.room )
|
||||||
@@ -488,38 +498,35 @@ const run = () => {
|
|||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
'/createRoomToken',
|
'/createRoomToken',
|
||||||
|
sdk.loginCheck(),
|
||||||
( request: express.Request, response: express.Response ) => {
|
( request: express.Request, response: express.Response ) => {
|
||||||
if ( sdk.checkAuth( request ) ) {
|
// eslint-disable-next-line no-constant-binary-expression
|
||||||
// eslint-disable-next-line no-constant-binary-expression
|
const roomName = String( request.query.roomName ) ?? '';
|
||||||
const roomName = String( request.query.roomName ) ?? '';
|
|
||||||
|
|
||||||
if ( !socketData[ roomName ] ) {
|
if ( !socketData[ roomName ] ) {
|
||||||
const roomToken = crypto.randomUUID();
|
const roomToken = crypto.randomUUID();
|
||||||
|
|
||||||
socketData[ roomName ] = {
|
socketData[ roomName ] = {
|
||||||
'playbackStart': 0,
|
'playbackStart': 0,
|
||||||
'playbackStatus': false,
|
'playbackStatus': false,
|
||||||
'playlist': [],
|
'playlist': [],
|
||||||
'playlistIndex': 0,
|
'playlistIndex': 0,
|
||||||
'roomName': roomName,
|
'roomName': roomName,
|
||||||
'roomToken': roomToken,
|
'roomToken': roomToken,
|
||||||
'ownerUID': sdk.getUserData( request ).uid,
|
'ownerUID': sdk.getUID( request ),
|
||||||
'useAntiTamper': request.query.useAntiTamper === 'true'
|
'useAntiTamper': request.query.useAntiTamper === 'true'
|
||||||
? true : false,
|
? true : false,
|
||||||
};
|
};
|
||||||
response.send( roomToken );
|
response.send( roomToken );
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
socketData[ roomName ].ownerUID
|
|
||||||
=== sdk.getUserData( request ).uid
|
|
||||||
) {
|
|
||||||
response.send( socketData[ roomName ].roomToken );
|
|
||||||
} else {
|
|
||||||
response.status( 409 ).send( 'ERR_CONFLICT' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
response.status( 403 ).send( 'ERR_FORBIDDEN' );
|
if (
|
||||||
|
socketData[ roomName ].ownerUID
|
||||||
|
=== sdk.getUID( request )
|
||||||
|
) {
|
||||||
|
response.send( socketData[ roomName ].roomToken );
|
||||||
|
} else {
|
||||||
|
response.status( 409 ).send( 'ERR_CONFLICT' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -569,46 +576,43 @@ const run = () => {
|
|||||||
|
|
||||||
const checkIfOwned = ( request: express.Request ): Promise<boolean> => {
|
const checkIfOwned = ( request: express.Request ): Promise<boolean> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
if ( sdk.checkAuth( request ) ) {
|
const uid = sdk.getUID( request );
|
||||||
const userData = sdk.getUserData( request );
|
|
||||||
|
|
||||||
if ( ownedCache[ userData.uid ] ) {
|
if ( ownedCache[ uid ] ) {
|
||||||
resolve( ownedCache[ userData.uid ] );
|
resolve( ownedCache[ uid ] );
|
||||||
} else {
|
} else {
|
||||||
storeSDK.getSubscriptions( userData.uid )
|
storeSDK.getSubscriptions( uid )
|
||||||
.then( stat => {
|
.then( stat => {
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
|
|
||||||
for ( const sub in stat ) {
|
for ( const sub in stat ) {
|
||||||
if ( stat[ sub ].expires - now > 0
|
if ( stat[ sub ].expires - now > 0
|
||||||
&& (
|
&& (
|
||||||
stat[ sub ].id
|
stat[ sub ].id
|
||||||
=== 'com.janishutz.MusicPlayer.subscription'
|
=== 'com.janishutz.MusicPlayer.subscription'
|
||||||
|| stat[ sub ].id
|
|| stat[ sub ].id
|
||||||
=== 'com.janishutz.MusicPlayer.subscription-month'
|
=== 'com.janishutz.MusicPlayer.subscription-month'
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
ownedCache[ userData.uid ] = true;
|
ownedCache[ uid ] = true;
|
||||||
resolve( true );
|
resolve( true );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ownedCache[ userData.uid ] = false;
|
ownedCache[ uid ] = false;
|
||||||
resolve( false );
|
resolve( false );
|
||||||
} )
|
} )
|
||||||
.catch( e => {
|
.catch( e => {
|
||||||
console.error( e );
|
console.error( e );
|
||||||
reject( 'ERR_NOT_OWNED' );
|
reject( 'ERR_NOT_OWNED' );
|
||||||
} );
|
} );
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject( 'ERR_AUTH_REQUIRED' );
|
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
'/checkUserStatus',
|
'/checkUserStatus',
|
||||||
|
sdk.loginCheck(),
|
||||||
( request: express.Request, response: express.Response ) => {
|
( request: express.Request, response: express.Response ) => {
|
||||||
checkIfOwned( request )
|
checkIfOwned( request )
|
||||||
.then( owned => {
|
.then( owned => {
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
import express from 'express';
|
|
||||||
import expressSession from 'express-session';
|
|
||||||
import crypto from 'node:crypto';
|
|
||||||
|
|
||||||
// TODO: Use also express-session to make it work with getSessionID and session referencing
|
|
||||||
const checkAuth = ( request: express.Request ) => {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AuthSDKConfig {
|
|
||||||
token: string;
|
|
||||||
name: string;
|
|
||||||
client: string;
|
|
||||||
backendURL: string;
|
|
||||||
failReturnURL: string;
|
|
||||||
useSecureCookie?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'express-session' {
|
|
||||||
interface SessionData {
|
|
||||||
isAuth: boolean;
|
|
||||||
uid: string;
|
|
||||||
username: string;
|
|
||||||
email: string;
|
|
||||||
additionalData: object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getUserData = ( request: express.Request ) => {
|
|
||||||
if ( !request.session.uid ) {
|
|
||||||
request.session.uid = crypto.randomUUID();
|
|
||||||
request.session.username = 'FOSS-Version';
|
|
||||||
request.session.email = 'example@example.com';
|
|
||||||
}
|
|
||||||
return { 'email': request.session.email, 'username': request.session.username, 'uid': request.session.uid, 'id': request.session.id };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
checkAuth,
|
|
||||||
getUserData
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
const getSubscriptions = ( uid: string ) => {
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
return [ {
|
const getSubscriptions = ( _uid: string ) => {
|
||||||
'id': 'com.janishutz.MusicPlayer.subscription',
|
return [
|
||||||
'expires': new Date().getTime() + 200000,
|
{
|
||||||
'status': true
|
'id': 'com.janishutz.MusicPlayer.subscription',
|
||||||
} ];
|
'expires': new Date().getTime() + 200000,
|
||||||
}
|
'status': true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getSubscriptions,
|
getSubscriptions,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ import path from 'path';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as sqlDB from './mysqldb.js';
|
import * as sqlDB from './mysqldb.js';
|
||||||
|
|
||||||
declare let __dirname: string | undefined
|
declare let __dirname: string | undefined;
|
||||||
if ( typeof( __dirname ) === 'undefined' ) {
|
|
||||||
|
if ( typeof __dirname === 'undefined' ) {
|
||||||
__dirname = path.resolve( path.dirname( '' ) );
|
__dirname = path.resolve( path.dirname( '' ) );
|
||||||
} else {
|
} else {
|
||||||
__dirname = __dirname + '/../';
|
__dirname = __dirname + '/../';
|
||||||
@@ -22,9 +23,8 @@ const dbRef = {
|
|||||||
'user': 'music_users',
|
'user': 'music_users',
|
||||||
'users': 'music_users',
|
'users': 'music_users',
|
||||||
};
|
};
|
||||||
|
const dbh = new sqlDB.SQLDB();
|
||||||
|
|
||||||
|
|
||||||
let dbh = new sqlDB.SQLDB();
|
|
||||||
dbh.connect();
|
dbh.connect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +32,7 @@ dbh.connect();
|
|||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
const initDB = (): undefined => {
|
const initDB = (): undefined => {
|
||||||
( async() => {
|
( async () => {
|
||||||
console.log( '[ DB ] Setting up...' );
|
console.log( '[ DB ] Setting up...' );
|
||||||
dbh.setupDB();
|
dbh.setupDB();
|
||||||
console.log( '[ DB ] Setting up complete!' );
|
console.log( '[ DB ] Setting up complete!' );
|
||||||
@@ -48,11 +48,16 @@ const initDB = (): undefined => {
|
|||||||
*/
|
*/
|
||||||
const getDataSimple = ( db: string, column: string, searchQuery: string ): Promise<object> => {
|
const getDataSimple = ( db: string, column: string, searchQuery: string ): Promise<object> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
dbh.query( { 'command': 'getFilteredData', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( data => {
|
dbh.query( {
|
||||||
|
'command': 'getFilteredData',
|
||||||
|
'property': column,
|
||||||
|
'searchQuery': searchQuery
|
||||||
|
}, dbRef[ db ] ).then( data => {
|
||||||
resolve( data );
|
resolve( data );
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,7 +71,7 @@ const getDataSimple = ( db: string, column: string, searchQuery: string ): Promi
|
|||||||
* @param {string} nameOfMatchingParam Which properties should be matched to get the data, e.g. order.user_id=users.id
|
* @param {string} nameOfMatchingParam Which properties should be matched to get the data, e.g. order.user_id=users.id
|
||||||
* @returns {Promise<Object | Error>} Returns all records from the db and all matching data specified with the matchingParam from the secondTable.
|
* @returns {Promise<Object | Error>} Returns all records from the db and all matching data specified with the matchingParam from the secondTable.
|
||||||
*/
|
*/
|
||||||
const getDataWithLeftJoinFunction = ( db: string, column: string, searchQuery: string, secondTable: string, columns: object, nameOfMatchingParam: string ): Promise<Object> => {
|
const getDataWithLeftJoinFunction = ( db: string, column: string, searchQuery: string, secondTable: string, columns: object, nameOfMatchingParam: string ): Promise<object> => {
|
||||||
/*
|
/*
|
||||||
LeftJoin (Select values in first table and return all corresponding values of second table):
|
LeftJoin (Select values in first table and return all corresponding values of second table):
|
||||||
- operation.property (the column to search for the value),
|
- operation.property (the column to search for the value),
|
||||||
@@ -76,24 +81,26 @@ const getDataWithLeftJoinFunction = ( db: string, column: string, searchQuery: s
|
|||||||
- operation.matchingParam (Which properties should be matched to get the data, e.g. order.user_id=users.id)
|
- operation.matchingParam (Which properties should be matched to get the data, e.g. order.user_id=users.id)
|
||||||
*/
|
*/
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
let settings = {
|
const settings = {
|
||||||
'command': 'LeftJoin',
|
'command': 'LeftJoin',
|
||||||
'property': column,
|
'property': column,
|
||||||
'searchQuery': searchQuery,
|
'searchQuery': searchQuery,
|
||||||
'selection': '',
|
'selection': '',
|
||||||
'secondTable': dbRef[ secondTable ],
|
'secondTable': dbRef[ secondTable ],
|
||||||
'matchingParam': dbRef[ db ] + '.' + nameOfMatchingParam + '=' + dbRef[ secondTable ] + '.' + nameOfMatchingParam,
|
'matchingParam': dbRef[ db ] + '.' + nameOfMatchingParam + '=' + dbRef[ secondTable ] + '.' + nameOfMatchingParam,
|
||||||
}
|
};
|
||||||
for ( let el in columns ) {
|
|
||||||
|
for ( const el in columns ) {
|
||||||
settings.selection += dbRef[ columns[ el ].db ] + '.' + columns[ el ].column + ',';
|
settings.selection += dbRef[ columns[ el ].db ] + '.' + columns[ el ].column + ',';
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.selection = settings.selection.slice( 0, settings.selection.length - 1 );
|
settings.selection = settings.selection.slice( 0, settings.selection.length - 1 );
|
||||||
dbh.query( settings, dbRef[ db ] ).then( data => {
|
dbh.query( settings, dbRef[ db ] ).then( data => {
|
||||||
resolve( data );
|
resolve( data );
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,13 +109,16 @@ const getDataWithLeftJoinFunction = ( db: string, column: string, searchQuery: s
|
|||||||
* @param {string} db The database of which all data should be retrieved
|
* @param {string} db The database of which all data should be retrieved
|
||||||
* @returns {Promise<object>} Returns an object containing all data
|
* @returns {Promise<object>} Returns an object containing all data
|
||||||
*/
|
*/
|
||||||
const getData = ( db: string ): Promise<Object> => {
|
const getData = ( db: string ): Promise<object> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
dbh.query( { 'command': 'getAllData' }, dbRef[ db ] ).then( data => {
|
dbh.query( {
|
||||||
|
'command': 'getAllData'
|
||||||
|
}, dbRef[ db ] ).then( data => {
|
||||||
resolve( data );
|
resolve( data );
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,25 +130,40 @@ const getData = ( db: string ): Promise<Object> => {
|
|||||||
* @param {string} data The data to write. Also include the column & searchQuery parameters, if they also need to be added
|
* @param {string} data The data to write. Also include the column & searchQuery parameters, if they also need to be added
|
||||||
* @returns {Promise<object>} Returns a promise that resolves to the interaction module return.
|
* @returns {Promise<object>} Returns a promise that resolves to the interaction module return.
|
||||||
*/
|
*/
|
||||||
const writeDataSimple = ( db: string, column: string, searchQuery: string, data: any ): Promise<Object> => {
|
const writeDataSimple = ( db: string, column: string, searchQuery: string, data: any ): Promise<object> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
dbh.query( { 'command': 'checkDataAvailability', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( res => {
|
dbh.query( {
|
||||||
|
'command': 'checkDataAvailability',
|
||||||
|
'property': column,
|
||||||
|
'searchQuery': searchQuery
|
||||||
|
}, dbRef[ db ] ).then( res => {
|
||||||
if ( res.length > 0 ) {
|
if ( res.length > 0 ) {
|
||||||
dbh.query( { 'command': 'updateData', 'property': column, 'searchQuery': searchQuery, 'newValues': data }, dbRef[ db ] ).then( dat => {
|
dbh.query( {
|
||||||
|
'command': 'updateData',
|
||||||
|
'property': column,
|
||||||
|
'searchQuery': searchQuery,
|
||||||
|
'newValues': data
|
||||||
|
}, dbRef[ db ] ).then( dat => {
|
||||||
resolve( dat );
|
resolve( dat );
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} else {
|
} else {
|
||||||
dbh.query( { 'command': 'addData', 'data': data }, dbRef[ db ] ).then( dat => {
|
dbh.query( {
|
||||||
|
'command': 'addData',
|
||||||
|
'data': data
|
||||||
|
}, dbRef[ db ] ).then( dat => {
|
||||||
resolve( dat );
|
resolve( dat );
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,11 +176,16 @@ const writeDataSimple = ( db: string, column: string, searchQuery: string, data:
|
|||||||
*/
|
*/
|
||||||
const deleteDataSimple = ( db: string, column: string, searchQuery: string ): Promise<object> => {
|
const deleteDataSimple = ( db: string, column: string, searchQuery: string ): Promise<object> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
dbh.query( { 'command': 'deleteData', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( dat => {
|
dbh.query( {
|
||||||
|
'command': 'deleteData',
|
||||||
|
'property': column,
|
||||||
|
'searchQuery': searchQuery
|
||||||
|
}, dbRef[ db ] ).then( dat => {
|
||||||
resolve( dat );
|
resolve( dat );
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,15 +198,20 @@ const deleteDataSimple = ( db: string, column: string, searchQuery: string ): Pr
|
|||||||
*/
|
*/
|
||||||
const checkDataAvailability = ( db: string, column: string, searchQuery: string ): Promise<boolean> => {
|
const checkDataAvailability = ( db: string, column: string, searchQuery: string ): Promise<boolean> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
dbh.query( { 'command': 'checkDataAvailability', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( res => {
|
dbh.query( {
|
||||||
|
'command': 'checkDataAvailability',
|
||||||
|
'property': column,
|
||||||
|
'searchQuery': searchQuery
|
||||||
|
}, dbRef[ db ] ).then( res => {
|
||||||
if ( res.length > 0 ) {
|
if ( res.length > 0 ) {
|
||||||
resolve( true );
|
resolve( true );
|
||||||
} else {
|
} else {
|
||||||
resolve( false );
|
resolve( false );
|
||||||
}
|
}
|
||||||
} ).catch( error => {
|
} )
|
||||||
reject( error );
|
.catch( error => {
|
||||||
} );
|
reject( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -186,16 +221,18 @@ const checkDataAvailability = ( db: string, column: string, searchQuery: string
|
|||||||
* @returns {Promise<object>} Returns the data from all files
|
* @returns {Promise<object>} Returns the data from all files
|
||||||
*/
|
*/
|
||||||
const getJSONDataBatch = async ( files: Array<string> ): Promise<object> => {
|
const getJSONDataBatch = async ( files: Array<string> ): Promise<object> => {
|
||||||
let allFiles = {};
|
const allFiles = {};
|
||||||
for ( let file in files ) {
|
|
||||||
|
for ( const file in files ) {
|
||||||
try {
|
try {
|
||||||
allFiles[ files[ file ] ] = await getJSONData( files[ file ] );
|
allFiles[ files[ file ] ] = await getJSONData( files[ file ] );
|
||||||
} catch( err ) {
|
} catch ( err ) {
|
||||||
allFiles[ files[ file ] ] = 'ERROR: ' + err;
|
allFiles[ files[ file ] ] = 'ERROR: ' + err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return allFiles;
|
return allFiles;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all data from a JSON file
|
* Load all data from a JSON file
|
||||||
@@ -245,7 +282,7 @@ const getJSONDataSimple = ( file: string, identifier: string ): Promise<object>
|
|||||||
* @param {string} file The file to be loaded (path relative to root)
|
* @param {string} file The file to be loaded (path relative to root)
|
||||||
* @returns {object} Returns the JSON file
|
* @returns {object} Returns the JSON file
|
||||||
*/
|
*/
|
||||||
const getJSONDataSync = ( file: string ): Object => {
|
const getJSONDataSync = ( file: string ): object => {
|
||||||
return JSON.parse( fs.readFileSync( path.join( __dirname + '/' + file ) ).toString() );
|
return JSON.parse( fs.readFileSync( path.join( __dirname + '/' + file ) ).toString() );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -263,14 +300,17 @@ const writeJSONDataSimple = ( db: string, identifier: string, values: any ) => {
|
|||||||
reject( 'Error occurred: Error trace: ' + error );
|
reject( 'Error occurred: Error trace: ' + error );
|
||||||
} else {
|
} else {
|
||||||
let dat = {};
|
let dat = {};
|
||||||
|
|
||||||
if ( data.byteLength > 0 ) {
|
if ( data.byteLength > 0 ) {
|
||||||
dat = JSON.parse( data.toString() ) ?? {};
|
dat = JSON.parse( data.toString() ) ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
dat[ identifier ] = values;
|
dat[ identifier ] = values;
|
||||||
fs.writeFile( path.join( __dirname + '/../../data/' + db + '.json' ), JSON.stringify( dat ), ( error ) => {
|
fs.writeFile( path.join( __dirname + '/../../data/' + db + '.json' ), JSON.stringify( dat ), error => {
|
||||||
if ( error ) {
|
if ( error ) {
|
||||||
reject( 'Error occurred: Error trace: ' + error );
|
reject( 'Error occurred: Error trace: ' + error );
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve( true );
|
resolve( true );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
@@ -286,7 +326,7 @@ const writeJSONDataSimple = ( db: string, identifier: string, values: any ) => {
|
|||||||
*/
|
*/
|
||||||
const writeJSONData = ( db: string, data: object ): Promise<boolean> => {
|
const writeJSONData = ( db: string, data: object ): Promise<boolean> => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
fs.writeFile( path.join( __dirname + '/../../data/' + db + '.json' ), JSON.stringify( data ), ( error ) => {
|
fs.writeFile( path.join( __dirname + '/../../data/' + db + '.json' ), JSON.stringify( data ), error => {
|
||||||
if ( error ) {
|
if ( error ) {
|
||||||
reject( 'Error occurred: Error trace: ' + error );
|
reject( 'Error occurred: Error trace: ' + error );
|
||||||
} else {
|
} else {
|
||||||
@@ -309,14 +349,17 @@ const deleteJSONDataSimple = ( db: string, identifier: string ): Promise<boolean
|
|||||||
reject( 'Error occurred: Error trace: ' + error );
|
reject( 'Error occurred: Error trace: ' + error );
|
||||||
} else {
|
} else {
|
||||||
let dat = {};
|
let dat = {};
|
||||||
|
|
||||||
if ( data.byteLength > 0 ) {
|
if ( data.byteLength > 0 ) {
|
||||||
dat = JSON.parse( data.toString() ) ?? {};
|
dat = JSON.parse( data.toString() ) ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
delete dat[ identifier ];
|
delete dat[ identifier ];
|
||||||
fs.writeFile( path.join( __dirname + '/../../data/' + db + '.json' ), JSON.stringify( dat ), ( error ) => {
|
fs.writeFile( path.join( __dirname + '/../../data/' + db + '.json' ), JSON.stringify( dat ), error => {
|
||||||
if ( error ) {
|
if ( error ) {
|
||||||
reject( 'Error occurred: Error trace: ' + error );
|
reject( 'Error occurred: Error trace: ' + error );
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve( true );
|
resolve( true );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
@@ -324,7 +367,19 @@ const deleteJSONDataSimple = ( db: string, identifier: string ): Promise<boolean
|
|||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
export default { initDB, checkDataAvailability, deleteDataSimple, deleteJSONDataSimple, getData,
|
export default {
|
||||||
getDataSimple, getDataWithLeftJoinFunction, getJSONData, getJSONDataBatch, getJSONDataSimple,
|
initDB,
|
||||||
getJSONDataSync, writeDataSimple, writeJSONData, writeJSONDataSimple
|
checkDataAvailability,
|
||||||
|
deleteDataSimple,
|
||||||
|
deleteJSONDataSimple,
|
||||||
|
getData,
|
||||||
|
getDataSimple,
|
||||||
|
getDataWithLeftJoinFunction,
|
||||||
|
getJSONData,
|
||||||
|
getJSONDataBatch,
|
||||||
|
getJSONDataSimple,
|
||||||
|
getJSONDataSync,
|
||||||
|
writeDataSimple,
|
||||||
|
writeJSONData,
|
||||||
|
writeJSONDataSimple
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ import mysql from 'mysql';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
declare let __dirname: string | undefined
|
declare let __dirname: string | undefined;
|
||||||
if ( typeof( __dirname ) === 'undefined' ) {
|
|
||||||
|
if ( typeof __dirname === 'undefined' ) {
|
||||||
__dirname = path.resolve( path.dirname( '' ) );
|
__dirname = path.resolve( path.dirname( '' ) );
|
||||||
} else {
|
} else {
|
||||||
__dirname = __dirname + '/../';
|
__dirname = __dirname + '/../';
|
||||||
@@ -22,21 +23,35 @@ if ( typeof( __dirname ) === 'undefined' ) {
|
|||||||
// to the whitelist of the database
|
// to the whitelist of the database
|
||||||
|
|
||||||
class SQLConfig {
|
class SQLConfig {
|
||||||
|
|
||||||
command: string;
|
command: string;
|
||||||
|
|
||||||
property?: string;
|
property?: string;
|
||||||
|
|
||||||
searchQuery?: string;
|
searchQuery?: string;
|
||||||
|
|
||||||
selection?: string;
|
selection?: string;
|
||||||
|
|
||||||
query?: string;
|
query?: string;
|
||||||
|
|
||||||
newValues?: object;
|
newValues?: object;
|
||||||
|
|
||||||
secondTable?: string;
|
secondTable?: string;
|
||||||
|
|
||||||
matchingParam?: string;
|
matchingParam?: string;
|
||||||
|
|
||||||
data?: object;
|
data?: object;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SQLDB {
|
class SQLDB {
|
||||||
|
|
||||||
sqlConnection: mysql.Connection;
|
sqlConnection: mysql.Connection;
|
||||||
|
|
||||||
isRecovering: boolean;
|
isRecovering: boolean;
|
||||||
|
|
||||||
config: object;
|
config: object;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this.config = JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/db.config.secret.json' ) ) );
|
this.config = JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/db.config.secret.json' ) ) );
|
||||||
this.sqlConnection = mysql.createConnection( this.config );
|
this.sqlConnection = mysql.createConnection( this.config );
|
||||||
@@ -46,19 +61,23 @@ class SQLDB {
|
|||||||
connect () {
|
connect () {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
if ( this.isRecovering ) {
|
if ( this.isRecovering ) {
|
||||||
console.log( '[ SQL ] Attempting to recover from critical error' );
|
console.log( '[ SQL ] Attempting to recover from critical error' );
|
||||||
this.sqlConnection = mysql.createConnection( this.config );
|
this.sqlConnection = mysql.createConnection( this.config );
|
||||||
this.isRecovering = false;
|
this.isRecovering = false;
|
||||||
}
|
}
|
||||||
this.sqlConnection.connect( ( err ) => {
|
|
||||||
|
this.sqlConnection.connect( err => {
|
||||||
if ( err ) {
|
if ( err ) {
|
||||||
console.error( '[ SQL ]: An error ocurred whilst connecting: ' + err.stack );
|
console.error( '[ SQL ]: An error ocurred whilst connecting: ' + err.stack );
|
||||||
reject( err );
|
reject( err );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log( '[ SQL ] Connected to database successfully' );
|
console.log( '[ SQL ] Connected to database successfully' );
|
||||||
self.sqlConnection.on( 'error', ( err ) => {
|
self.sqlConnection.on( 'error', err => {
|
||||||
if ( err.code === 'ECONNRESET' ) {
|
if ( err.code === 'ECONNRESET' ) {
|
||||||
self.isRecovering = true;
|
self.isRecovering = true;
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
@@ -81,15 +100,17 @@ class SQLDB {
|
|||||||
async setupDB () {
|
async setupDB () {
|
||||||
this.sqlConnection.query( 'SELECT @@default_storage_engine;', ( error, results ) => {
|
this.sqlConnection.query( 'SELECT @@default_storage_engine;', ( error, results ) => {
|
||||||
if ( error ) throw error;
|
if ( error ) throw error;
|
||||||
|
|
||||||
if ( results[ 0 ][ '@@default_storage_engine' ] !== 'InnoDB' ) throw 'DB HAS TO USE InnoDB!';
|
if ( results[ 0 ][ '@@default_storage_engine' ] !== 'InnoDB' ) throw 'DB HAS TO USE InnoDB!';
|
||||||
} );
|
} );
|
||||||
this.sqlConnection.query( 'CREATE TABLE music_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, uid TINYTEXT, lang TINYTEXT, username TINYTEXT, settings VARCHAR( 5000 ), PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => {
|
this.sqlConnection.query( 'CREATE TABLE music_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, uid TINYTEXT, lang TINYTEXT, username TINYTEXT, settings VARCHAR( 5000 ), PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', error => {
|
||||||
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
|
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
|
||||||
|
|
||||||
return 'DONE';
|
return 'DONE';
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
query ( operation: SQLConfig, table: string ): Promise<Array<Object>> {
|
query ( operation: SQLConfig, table: string ): Promise<Array<object>> {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
/*
|
/*
|
||||||
Possible operation.command values (all need the table argument of the method call):
|
Possible operation.command values (all need the table argument of the method call):
|
||||||
@@ -141,6 +162,7 @@ class SQLDB {
|
|||||||
- operation.query (the SQL instruction to be executed) --> NOTE: This command will not be sanitised, so use only with proper sanitisation!
|
- operation.query (the SQL instruction to be executed) --> NOTE: This command will not be sanitised, so use only with proper sanitisation!
|
||||||
*/
|
*/
|
||||||
let command = '';
|
let command = '';
|
||||||
|
|
||||||
if ( operation.command === 'getAllData' ) {
|
if ( operation.command === 'getAllData' ) {
|
||||||
command = 'SELECT * FROM ' + table;
|
command = 'SELECT * FROM ' + table;
|
||||||
} else if ( operation.command === 'getFilteredData' || operation.command === 'checkDataAvailability' ) {
|
} else if ( operation.command === 'getFilteredData' || operation.command === 'checkDataAvailability' ) {
|
||||||
@@ -150,19 +172,23 @@ class SQLDB {
|
|||||||
} else if ( operation.command === 'addData' ) {
|
} else if ( operation.command === 'addData' ) {
|
||||||
let keys = '';
|
let keys = '';
|
||||||
let values = '';
|
let values = '';
|
||||||
for ( let key in operation.data ) {
|
|
||||||
|
for ( const key in operation.data ) {
|
||||||
keys += String( key ) + ', ';
|
keys += String( key ) + ', ';
|
||||||
values += this.sqlConnection.escape( String( operation.data[ key ] ) ) + ', ' ;
|
values += this.sqlConnection.escape( String( operation.data[ key ] ) ) + ', ';
|
||||||
}
|
}
|
||||||
command = 'INSERT INTO ' + table + ' (' + keys.slice( 0, keys.length - 2 ) + ') VALUES (' + values.slice( 0, values.length - 2 ) + ');';
|
|
||||||
|
command = 'INSERT INTO ' + table + ' (' + keys.slice( 0, keys.length - 2 ) + ') VALUES (' + values.slice( 0, values.length - 2 ) + ');';
|
||||||
} else if ( operation.command === 'updateData' ) {
|
} else if ( operation.command === 'updateData' ) {
|
||||||
if ( !operation.property || !operation.searchQuery ) reject( 'Refusing to run destructive command: Missing Constraints' );
|
if ( !operation.property || !operation.searchQuery ) reject( 'Refusing to run destructive command: Missing Constraints' );
|
||||||
else {
|
else {
|
||||||
command = 'UPDATE ' + table + ' SET ';
|
command = 'UPDATE ' + table + ' SET ';
|
||||||
let updatedValues = '';
|
let updatedValues = '';
|
||||||
for ( let value in operation.newValues ) {
|
|
||||||
|
for ( const value in operation.newValues ) {
|
||||||
updatedValues += value + ' = ' + this.sqlConnection.escape( String( operation.newValues[ value ] ) ) + ', ';
|
updatedValues += value + ' = ' + this.sqlConnection.escape( String( operation.newValues[ value ] ) ) + ', ';
|
||||||
}
|
}
|
||||||
|
|
||||||
command += updatedValues.slice( 0, updatedValues.length - 2 );
|
command += updatedValues.slice( 0, updatedValues.length - 2 );
|
||||||
command += ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery );
|
command += ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery );
|
||||||
}
|
}
|
||||||
@@ -178,12 +204,17 @@ class SQLDB {
|
|||||||
} else if ( operation.command === 'RightJoin' ) {
|
} else if ( operation.command === 'RightJoin' ) {
|
||||||
command = 'SELECT ' + operation.selection + ' FROM ' + table + ' RIGHT JOIN ' + operation.secondTable + ' ON ' + operation.matchingParam + ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery );
|
command = 'SELECT ' + operation.selection + ' FROM ' + table + ' RIGHT JOIN ' + operation.secondTable + ' ON ' + operation.matchingParam + ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sqlConnection.query( command, ( error, results ) => {
|
this.sqlConnection.query( command, ( error, results ) => {
|
||||||
if ( error ) reject( error );
|
if ( error ) reject( error );
|
||||||
|
|
||||||
resolve( results );
|
resolve( results );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { SQLConfig, SQLDB };
|
export {
|
||||||
|
SQLConfig, SQLDB
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user