satyr/src/api.ts
knotteye 25cf8a37a2 Big Commit!
Seriously, this one is pretty massive. Satyr now has proper sessions in the browser (like a real website), and a lot of changes were made.

API Endpoints were changed from requiring a username and password to requiring a valid JsonWebToken, obtained from /api/login
Satyr will generate a PEM format key for JWT signing and verification on startup if it can't find one at config/jwt.pem
This file was added to .gitignore
Two new depencies: cookie-parser and jose, for reading and signing JWTs.

Refactored http.ts into mutiple functions, with a couple helper functions related to cookies and JWT decoding and verification. Socket.IO chat will also automatically log in users with a valid JWT.

Refactor api.ts to reflect new requirements from endpoints.

Minor bugfix in server.ts so we don't throw an uncaught exception when rejecting a stream with an invalid key.

Transcode options readded to default.toml. They do nothing and they are not sane defaults. Both of those things are in the todo list.
2019-12-03 19:51:14 -06:00

64 lines
2.5 KiB
TypeScript

import * as db from "./database"
import { unregisterUser } from "./irc";
var config: any;
function init(conf: object){
config = conf;
}
async function register(name: string, password: string, confirm: string) {
if(!config.registration) return {"error":"registration disabled"};
if(name.includes(';') || name.includes(' ') || name.includes('\'')) return {"error":"illegal characters"};
if(password !== confirm) return {"error":"mismatched passwords"};
for(let i=0;i<config.restrictedNames.length;i++){
if (name === config.restrictedNames[i]) return {"error":"restricted name"};
}
let r: boolean = await db.addUser(name, password);
if(r) {
let k = await db.query('select stream_key from users where username='+db.raw.escape(name));
return k;
}
return {"error":""};
}
async function update(fields: object){
if(!fields['title'] && !fields['bio'] && (fields['rec'] !== 'true' && fields['rec'] !== 'false')) return {"error":"no valid fields specified"};
let qs: string = "";
let f: boolean = false;
if(fields['title']) {qs += ' user_meta.title='+db.raw.escape(fields['title']);f = true;}
if(fields['bio']) {
if(f) qs+=',';
qs += ' user_meta.about='+db.raw.escape(fields['bio']);
f=true;
}
if(typeof(fields['rec']) === 'boolean' || typeof(fields['rec']) === 'number') {
if(f) qs+=',';
qs += ' users.record_flag='+db.raw.escape(fields['rec']);
}
await db.query('UPDATE users,user_meta SET'+qs+' WHERE users.username='+db.raw.escape(fields['name'])+' AND user_meta.username='+db.raw.escape(fields['name']));
return {"success":""};
}
async function changepwd(name: string, password: string, newpwd: string){
if(!name || !password || !newpwd) return {"error":"Insufficient parameters"};
let auth: boolean = await db.validatePassword(name, password);
if(!auth) return {"error":"Username or Password Incorrect"};
let newhash: string = await db.hash(newpwd);
await db.query('UPDATE users set password_hash='+db.raw.escape(newhash)+'where username='+db.raw.escape(name)+' limit 1');
return {"success":""};
}
async function changesk(name: string){
let key: string = await db.genKey();
await db.query('UPDATE users set stream_key='+db.raw.escape(key)+'where username='+db.raw.escape(name)+' limit 1');
return {"success":key};
}
async function login(name: string, password: string){
if(!name || !password) return {"error":"Insufficient parameters"};
let auth: boolean = await db.validatePassword(name, password);
if(!auth) return {"error":"Username or Password Incorrect"};
return false;
}
export { init, register, update, changepwd, changesk, login };