Added cli for user management, abstracted some database queries into handler functions.
parent
abcd6787ca
commit
68f9866c16
|
@ -354,6 +354,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"flags": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/flags/-/flags-0.1.3.tgz",
|
||||
"integrity": "sha1-lh0vyM3zZp1jBB4w5bJK2tNvV1g="
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
|
@ -1017,6 +1022,12 @@
|
|||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz",
|
||||
"integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==",
|
||||
"dev": true
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
"author": "knotteye",
|
||||
"scripts": {
|
||||
"start": "node build/controller.js",
|
||||
"build": "tsc"
|
||||
"build": "tsc",
|
||||
"user": "node build/cli.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -15,12 +16,14 @@
|
|||
"dependencies": {
|
||||
"bcrypt": "^3.0.6",
|
||||
"config": "^3.2.2",
|
||||
"flags": "^0.1.3",
|
||||
"irc": "^0.5.2",
|
||||
"mysql": "^2.17.1",
|
||||
"node-media-server": ">=2.1.3 <3.0.0",
|
||||
"toml": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.7.5"
|
||||
"@types/node": "^12.7.5",
|
||||
"typescript": "^3.6.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import * as db from "./database"
|
||||
import * as flags from "flags";
|
||||
import * as config from "config"
|
||||
|
||||
db.run(config.database, config.bcrypt);
|
||||
|
||||
flags.defineString('add', '', 'User to add');
|
||||
flags.defineString('remove', '', 'User to remove');
|
||||
flags.defineString('mkstreamer', '', 'Give a stream key to a user');
|
||||
flags.defineString('rmstreamer', '', 'Remove a stream key from a user');
|
||||
flags.defineString('password', '', 'password to hash');
|
||||
flags.defineBoolean('admin');
|
||||
flags.defineBoolean('streamer');
|
||||
|
||||
flags.parse();
|
||||
|
||||
if(flags.get('add') !== ''){
|
||||
db.addUser(flags.get('add'), flags.get('password'), flags.get('streamer'), flags.get('admin')).then((result) => {
|
||||
if(result) console.log("User added successfully.");
|
||||
else console.log("Could not add user. Is the password field empty?");
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
if(flags.get('remove') !== ''){
|
||||
db.rmUser(flags.get('remove')).then((result) => {
|
||||
if(result) console.log("User removed successfully.");
|
||||
else console.log("Could not remove user.");
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
if(flags.get('mkstreamer') !== ''){
|
||||
db.addStreamKey(flags.get('mkstreamer')).then((result) => {
|
||||
if(result) console.log("Key added successfully.");
|
||||
else console.log("Could not add key.");
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
if(flags.get('rmstreamer') !== ''){
|
||||
db.rmStreamKey(flags.get('rmstreamer')).then((result) => {
|
||||
if(result) console.log("Key removed successfully.");
|
||||
else console.log("Could not remove key.");
|
||||
process.exit();
|
||||
});
|
||||
}
|
|
@ -3,23 +3,7 @@ import * as ircd from "./ircd";
|
|||
import * as db from "./database";
|
||||
const config = require('config');
|
||||
|
||||
/*var dbcfg: object;
|
||||
var servercfg: object;
|
||||
var bcryptcfg: object;
|
||||
var satyrcfg: object;
|
||||
var ircdcfg: object;
|
||||
|
||||
|
||||
function init(): void{
|
||||
dbcfg = config.get('database');
|
||||
bcryptcfg = config.get('bcrypt');
|
||||
servercfg = config.get('server');
|
||||
satyrcfg = config.get('satyr');
|
||||
ircdcfg = config.get('ircd');
|
||||
}*/
|
||||
|
||||
function run(): void{
|
||||
//init();
|
||||
const dbcfg = config.database;
|
||||
const bcryptcfg = config.bcrypt;
|
||||
const satyr: object = {
|
||||
|
|
|
@ -1,26 +1,67 @@
|
|||
import * as mysql from "mysql";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import * as crypto from "crypto";
|
||||
import { resolve } from "url";
|
||||
var raw: any;
|
||||
var cryptoconfig: object;
|
||||
var cryptoconfig: any;
|
||||
|
||||
function run (db: object, bcrypt: object){
|
||||
raw = mysql.createPool(db);
|
||||
cryptoconfig = bcrypt;
|
||||
}
|
||||
|
||||
function streamKeyAuth(key: string){
|
||||
;
|
||||
async function addUser(name: string, password: string, streamer: boolean, admin: boolean){
|
||||
//does not respect registration setting in config
|
||||
if(password === '') return false;
|
||||
let key: string = ' ';
|
||||
if (streamer) key = await genKey();
|
||||
let hash: string = await bcrypt.hash(password, cryptoconfig.saltRounds);
|
||||
let dupe = await query('select * from users where username=\''+name+'\'');
|
||||
if(dupe[0]) return false;
|
||||
//INSERT INTO users (username, password_hash, stream_key, record_flag, is_mod) VALUES ('name', 'hash', 'key', 0, admin);
|
||||
let q: string = 'INSERT INTO users (username, password_hash, stream_key, record_flag, is_mod) VALUES (\''+name+'\', \''+hash+'\', \''+key+'\', 0, '+admin+')';
|
||||
await query(q);
|
||||
return true;
|
||||
}
|
||||
|
||||
async function rmUser(name: string){
|
||||
let exist = await query('select * from users where username=\''+name+'\'');
|
||||
if(!exist[0]) return false;
|
||||
await query('delete from users where username=\''+name+'\' limit 1');
|
||||
return true;
|
||||
}
|
||||
|
||||
async function genKey(){
|
||||
let key: string = crypto.randomBytes(10).toString('hex');
|
||||
let result = await query('select * from users where stream_key=\''+key+'\'');
|
||||
if(result[0]) return await genKey();
|
||||
else return key;
|
||||
}
|
||||
|
||||
async function addStreamKey(name: string){
|
||||
let exist = await query('select * from users where username=\''+name+'\'');
|
||||
if(!exist[0]) return false;
|
||||
let key = await genKey();
|
||||
await query('update users set stream_key=\''+key+'\' where username=\''+name+'\' limit 1');
|
||||
return true;
|
||||
}
|
||||
|
||||
async function rmStreamKey(name: string){
|
||||
let exist = await query('select * from users where username=\''+name+'\'');
|
||||
if(!exist[0]) return false;
|
||||
await query('update users set stream_key=\'\' where username=\''+name+'\' limit 1');
|
||||
return true;
|
||||
}
|
||||
|
||||
async function query(query: string){
|
||||
return new Promise(resolve => raw.query(query, (error, results, fields) => {
|
||||
if(error) throw error;
|
||||
resolve(results);
|
||||
}));
|
||||
}
|
||||
|
||||
async function validatePassword(username: string, password: string){
|
||||
raw.connect();
|
||||
return raw.query('select password_hash from users where username=\''+username+'\' limit 1', (error, results, fields) => {
|
||||
if (error) { throw error; }
|
||||
return bcrypt.compare(password, results[0].password_hash, (err, result) =>{
|
||||
if (err) { throw err; }
|
||||
return result;
|
||||
});
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
export { streamKeyAuth, validatePassword, raw, run };
|
||||
export { query, raw, run, addUser, rmUser, addStreamKey, rmStreamKey };
|
|
@ -1,7 +1,6 @@
|
|||
import * as NodeMediaServer from "node-media-server";
|
||||
import { mkdir } from "fs";
|
||||
import * as db from "./database";
|
||||
//import { transcode } from "buffer"; why is this here?
|
||||
const { exec } = require('child_process');
|
||||
|
||||
function boot (mediaconfig: any, satyrconfig: any) {
|
||||
|
@ -20,20 +19,20 @@ function boot (mediaconfig: any, satyrconfig: any) {
|
|||
return false;
|
||||
}
|
||||
if(app === mediaconfig.trans.tasks[0].app) {
|
||||
if(session.ip.includes('127.0.0.1') || session.ip === '::1') {
|
||||
//only allow publish to public endpoint from localhost
|
||||
//this is NOT a comprehensive way of doing this, but I'm ignoring it
|
||||
//until satyr releases and someone opens an issue
|
||||
if(session.ip.includes('127.0.0.1') || session.ip === '::1') {
|
||||
console.log("[NodeMediaServer] Local publish, stream:",`${id} ok.`);
|
||||
}
|
||||
else{
|
||||
console.log("[NodeMediaServer] Non-local Publish to public endpoint, rejecting stream:",id);
|
||||
session.reject();
|
||||
return false;
|
||||
}
|
||||
console.log("[NodeMediaServer] Public endpoint, checking record flag.");
|
||||
//if this stream is from the public endpoint, stream
|
||||
db.raw.query('select username from users where username=\''+key+'\' and record_flag=true limit 1', (error, results, fields) => {
|
||||
if (error) {throw error;}
|
||||
//if this stream is from the public endpoint, check if we should be recording
|
||||
return db.query('select username from users where username=\''+key+'\' and record_flag=true limit 1').then((results) => {
|
||||
if(results[0].username && satyrconfig.record){
|
||||
console.log('[NodeMediaServer] Initiating recording for stream:',id);
|
||||
mkdir(mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks[0].app+'/'+results[0].username, { recursive : true }, (err) => {
|
||||
|
@ -50,8 +49,8 @@ function boot (mediaconfig: any, satyrconfig: any) {
|
|||
else {
|
||||
console.log('[NodeMediaServer] Skipping recording for stream:',id);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
if(app !== satyrconfig.privateEndpoint){
|
||||
//app isn't at public endpoint if we've reached this point
|
||||
|
@ -62,8 +61,7 @@ function boot (mediaconfig: any, satyrconfig: any) {
|
|||
//if the url is formatted correctly and the user is streaming to the correct private endpoint
|
||||
//grab the username from the database and redirect the stream there if the key is valid
|
||||
//otherwise kill the session
|
||||
db.raw.query('select username from users where stream_key=\''+key+'\' limit 1', (error, results, fields) => {
|
||||
if (error) {throw error;}
|
||||
db.query('select username from users where stream_key=\''+key+'\' limit 1').then((results) => {
|
||||
if(results[0]){
|
||||
exec('ffmpeg -analyzeduration 0 -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key+' -vcodec copy -acodec copy -crf 18 -f flv rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+mediaconfig.trans.tasks[0].app+'/'+results[0].username);
|
||||
console.log('[NodeMediaServer] Stream key okay for stream:',id);
|
||||
|
|
Reference in New Issue