Add API handling of invite codes, add web page for inviting users.
parent
9605ff8c92
commit
67de11e66b
13
src/api.ts
13
src/api.ts
|
@ -3,8 +3,8 @@ import * as base64id from "base64id";
|
||||||
import { config } from "./config";
|
import { config } from "./config";
|
||||||
import {unlink} from "fs";
|
import {unlink} from "fs";
|
||||||
|
|
||||||
async function register(name: string, password: string, confirm: string): Promise<object> {
|
async function register(name: string, password: string, confirm: string, invite?: boolean): Promise<object> {
|
||||||
if(!config['satyr']['registration']) return {"error":"registration disabled"};
|
if(!config['satyr']['registration'] && !invite) return {"error":"registration disabled"};
|
||||||
if(name.includes(';') || name.includes(' ') || name.includes('\'')) return {"error":"illegal characters"};
|
if(name.includes(';') || name.includes(' ') || name.includes('\'')) return {"error":"illegal characters"};
|
||||||
if(password !== confirm) return {"error":"mismatched passwords"};
|
if(password !== confirm) return {"error":"mismatched passwords"};
|
||||||
for(let i=0;i<config['satyr']['restrictedNames'].length;i++){
|
for(let i=0;i<config['satyr']['restrictedNames'].length;i++){
|
||||||
|
@ -104,12 +104,15 @@ async function genInvite(): Promise<string>{
|
||||||
return invitecode;
|
return invitecode;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function useInvite(code: string): Promise<boolean>{
|
async function validInvite(code: string): Promise<boolean>{
|
||||||
if(typeof(code) !== "string" || code === "") return false;
|
if(typeof(code) !== "string" || code === "") return false;
|
||||||
var result = await db.query('SELECT code FROM invites WHERE code='+db.raw.escape(code));
|
var result = await db.query('SELECT code FROM invites WHERE code='+db.raw.escape(code));
|
||||||
if(!result[0] || result[0]['code'] !== code) return false;
|
if(!result[0] || result[0]['code'] !== code) return false;
|
||||||
await db.query('DELETE FROM invites WHERE code='+db.raw.escape(code));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { register, update, changepwd, changesk, login, updateChat, deleteVODs, getConfig, genInvite, useInvite };
|
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 };
|
|
@ -16,7 +16,7 @@ const config: Object = {
|
||||||
domain: '',
|
domain: '',
|
||||||
registration: false,
|
registration: false,
|
||||||
email: null,
|
email: null,
|
||||||
restrictedNames: [ 'live', 'user', 'users', 'register', 'login' ],
|
restrictedNames: [ 'live', 'user', 'users', 'register', 'login', 'invite' ],
|
||||||
rootredirect: '/users/live',
|
rootredirect: '/users/live',
|
||||||
version: process.env.npm_package_version,
|
version: process.env.npm_package_version,
|
||||||
}, localconfig['satyr']),
|
}, localconfig['satyr']),
|
||||||
|
|
27
src/http.ts
27
src/http.ts
|
@ -224,6 +224,21 @@ async function initAPI() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
app.post('/api/register', (req, res) => {
|
app.post('/api/register', (req, res) => {
|
||||||
|
if("invite" in req.body){
|
||||||
|
if(api.validInvite(req.body.invite)){
|
||||||
|
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) => {
|
api.register(req.body.username, req.body.password, req.body.confirm).then( (result) => {
|
||||||
if(result[0]) return genToken(req.body.username).then((t) => {
|
if(result[0]) return genToken(req.body.username).then((t) => {
|
||||||
res.cookie('Authorization', t, {maxAge: 604800000, httpOnly: true, sameSite: 'Lax'});
|
res.cookie('Authorization', t, {maxAge: 604800000, httpOnly: true, sameSite: 'Lax'});
|
||||||
|
@ -486,6 +501,18 @@ async function initSite(openReg) {
|
||||||
}
|
}
|
||||||
else res.render('login.njk',njkconf);
|
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('/invite', (req, res) => {
|
||||||
|
if(tryDecode(req.cookies.Authorization)) {
|
||||||
|
res.redirect('/profile');
|
||||||
|
}
|
||||||
|
else res.render('invite.njk',Object.assign({icode: ""}, njkconf));
|
||||||
|
});
|
||||||
app.get('/register', (req, res) => {
|
app.get('/register', (req, res) => {
|
||||||
if(tryDecode(req.cookies.Authorization) || !openReg) {
|
if(tryDecode(req.cookies.Authorization) || !openReg) {
|
||||||
res.redirect(njkconf.rootredirect);
|
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>
|
||||||
|
Invite Code: </br><input type="text" name="invite" style="min-width: 300px" value="{{icode}}"/></br></br>
|
||||||
|
<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