Merge branch 'invite-codes' into 'develop'
Invite codes See merge request knotteye/satyr!26merge-requests/26/merge
commit
99879fd91e
|
@ -91,7 +91,9 @@ Register a new user.
|
|||
|
||||
**Authentication**: no
|
||||
|
||||
**Parameters**: Username, password, confirm
|
||||
**Parameters**: Username, password, confirm, invite(optional)
|
||||
|
||||
Invite is an optional invite code to bypass disabled registration.
|
||||
|
||||
**Response**: If successful, returns a json object with the users stream key. Otherwise returns `{error: "error reason"}`
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"name": "satyr",
|
||||
"version": "0.9.3",
|
||||
"version": "0.9.4",
|
||||
"description": "A livestreaming server.",
|
||||
"license": "AGPL-3.0",
|
||||
"author": "knotteye",
|
||||
"scripts": {
|
||||
"start": "ts-node src/index.ts",
|
||||
"user": "ts-node src/cli.ts",
|
||||
"cli": "ts-node src/cli.ts",
|
||||
"setup": "sh install/setup.sh",
|
||||
"migrate": "ts-node src/migrate.ts"
|
||||
"migrate": "ts-node src/migrate.ts",
|
||||
"invite": "ts-node src/cli.ts --invite"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
24
src/api.ts
24
src/api.ts
|
@ -1,9 +1,10 @@
|
|||
import * as db from "./database";
|
||||
import * as base64id from "base64id";
|
||||
import { config } from "./config";
|
||||
import {unlink} from "fs";
|
||||
|
||||
async function register(name: string, password: string, confirm: string): Promise<object> {
|
||||
if(!config['satyr']['registration']) return {"error":"registration disabled"};
|
||||
async function register(name: string, password: string, confirm: string, invite?: boolean): Promise<object> {
|
||||
if(!config['satyr']['registration'] && !invite) 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['satyr']['restrictedNames'].length;i++){
|
||||
|
@ -97,4 +98,21 @@ async function getConfig(username: string, all?: boolean): Promise<object>{
|
|||
return t;
|
||||
}
|
||||
|
||||
export { register, update, changepwd, changesk, login, updateChat, deleteVODs, getConfig };
|
||||
async function genInvite(): Promise<string>{
|
||||
var invitecode: string = base64id.generateId();
|
||||
await db.query('INSERT INTO invites (code) VALUES (\"'+invitecode+'\")');
|
||||
return invitecode;
|
||||
}
|
||||
|
||||
async function validInvite(code: string): Promise<boolean>{
|
||||
if(typeof(code) !== "string" || code === "") return false;
|
||||
var result = await db.query('SELECT code FROM invites WHERE code='+db.raw.escape(code));
|
||||
if(!result[0] || result[0]['code'] !== code) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
async function useInvite(code: string): Promise<void>{
|
||||
if(validInvite(code)) await db.query('DELETE FROM invites WHERE code='+db.raw.escape(code));
|
||||
}
|
||||
|
||||
export { register, update, changepwd, changesk, login, updateChat, deleteVODs, getConfig, genInvite, useInvite, validInvite };
|
13
src/cli.ts
13
src/cli.ts
|
@ -1,4 +1,5 @@
|
|||
import * as db from "./database"
|
||||
import * as db from "./database";
|
||||
import * as api from "./api";
|
||||
import * as flags from "flags";
|
||||
|
||||
db.init();
|
||||
|
@ -6,6 +7,7 @@ db.init();
|
|||
flags.defineString('adduser', '', 'User to add');
|
||||
flags.defineString('rmuser', '', 'User to remove');
|
||||
flags.defineString('password', '', 'password to hash');
|
||||
flags.defineBoolean('invite', false, 'generate invite code');
|
||||
|
||||
flags.parse();
|
||||
|
||||
|
@ -24,3 +26,12 @@ if(flags.get('rmuser') !== ''){
|
|||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
if(flags.get('invite')){
|
||||
var config = require("./config").config;
|
||||
api.genInvite().then((r: string) => {
|
||||
console.log('invite code: '+r);
|
||||
console.log('Direct the user to https://'+config['satyr']['domain']+'/invite/'+r);
|
||||
process.exit();
|
||||
});
|
||||
}
|
|
@ -16,7 +16,7 @@ const config: Object = {
|
|||
domain: '',
|
||||
registration: false,
|
||||
email: null,
|
||||
restrictedNames: [ 'live', 'user', 'users', 'register', 'login' ],
|
||||
restrictedNames: [ 'live', 'user', 'users', 'register', 'login', 'invite' ],
|
||||
rootredirect: '/users/live',
|
||||
version: process.env.npm_package_version,
|
||||
}, localconfig['satyr']),
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import * as db from "../database";
|
||||
|
||||
async function run () {
|
||||
await db.query('CREATE TABLE IF NOT EXISTS invites(code VARCHAR(150))');
|
||||
await db.query('INSERT INTO db_meta (version) VALUES (2)');
|
||||
}
|
||||
|
||||
export { run }
|
23
src/http.ts
23
src/http.ts
|
@ -224,6 +224,23 @@ async function initAPI() {
|
|||
});
|
||||
});
|
||||
app.post('/api/register', (req, res) => {
|
||||
if("invite" in req.body){
|
||||
api.validInvite(req.body.invite).then((v) => {
|
||||
if(v){
|
||||
api.register(req.body.username, req.body.password, req.body.confirm, true).then((result) => {
|
||||
if(result[0]) return genToken(req.body.username).then((t) => {
|
||||
res.cookie('Authorization', t, {maxAge: 604800000, httpOnly: true, sameSite: 'Lax'});
|
||||
res.json(result);
|
||||
api.useInvite(req.body.invite);
|
||||
return;
|
||||
});
|
||||
res.json(result);
|
||||
});
|
||||
}
|
||||
else res.json({error: "invalid invite code"});
|
||||
});
|
||||
}
|
||||
else
|
||||
api.register(req.body.username, req.body.password, req.body.confirm).then( (result) => {
|
||||
if(result[0]) return genToken(req.body.username).then((t) => {
|
||||
res.cookie('Authorization', t, {maxAge: 604800000, httpOnly: true, sameSite: 'Lax'});
|
||||
|
@ -486,6 +503,12 @@ async function initSite(openReg) {
|
|||
}
|
||||
else res.render('login.njk',njkconf);
|
||||
});
|
||||
app.get('/invite/:code', (req, res) => {
|
||||
if(tryDecode(req.cookies.Authorization)) {
|
||||
res.redirect('/profile');
|
||||
}
|
||||
else res.render('invite.njk',Object.assign({icode: req.params.code}, njkconf));
|
||||
});
|
||||
app.get('/register', (req, res) => {
|
||||
if(tryDecode(req.cookies.Authorization) || !openReg) {
|
||||
res.redirect(njkconf.rootredirect);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "base.njk" %}
|
||||
{% block content %}
|
||||
<h3>You've been invited to {{ sitename }}</h3><span style="font-size: small;">Already registered? Log in <a href="/login">here</a>.</br></br></span>
|
||||
<!--<div id="jscontainer" style="height: 100%;">
|
||||
<div id="jschild" style="width: 50%;height: 100%;text-align: left;margin: 20px;">-->
|
||||
<form action="/api/register" method="POST" target="responseFrame">
|
||||
Username: </br><input type="text" name="username" style="min-width: 300px" placeholder="e.g. lain"/></br>
|
||||
Password: </br><input type="password" name="password" style="min-width: 300px"/></br>
|
||||
Confirm: </br><input type="password" name="confirm" style="min-width: 300px"/></br></br>
|
||||
<input type="hidden" name="invite" style="min-width: 300px" value="{{icode}}"/>
|
||||
<input type="submit" value="Submit">
|
||||
</form></br>
|
||||
|
||||
<!--</div>
|
||||
<div id="jschild" style="width: 50%;height: 100%;text-align: left;margin: 20px;">-->
|
||||
{% include "tos.html" %}</br>
|
||||
<iframe name="responseFrame" border="0" frameborder="0" style="display: inline;"></iframe>
|
||||
<!--</div>
|
||||
</div>-->
|
||||
{% endblock %}
|
Reference in New Issue