Parcourir la source

better admin stuff

master
mortie il y a 7 ans
Parent
révision
efa3c805c0
4 fichiers modifiés avec 176 ajouts et 144 suppressions
  1. 4
    3
      js/admin.js
  2. 14
    2
      js/fileserver.js
  3. 156
    139
      web/admin/lib.js
  4. 2
    0
      web/admin/view.js

+ 4
- 3
js/admin.js Voir le fichier

var token = crypto.randomBytes(16).toString("hex"); var token = crypto.randomBytes(16).toString("hex");
var id = sessTokens.length; var id = sessTokens.length;
sessTokens[id] = token; sessTokens[id] = token;
respond(null, token);


// Time out after 30 minutes // Time out after 30 minutes
setTimeout(() => { setTimeout(() => {
tokens[id] = undefined;
sessTokens[id] = undefined;
}, 30 * 60 * 1000); }, 30 * 60 * 1000);

respond(null, token);
} }
function validateToken(req) { function validateToken(req) {
var token = req.headers["session-token"]; var token = req.headers["session-token"];


// Verify token // Verify token
if (!validateToken(req)) if (!validateToken(req))
return respond("Invalid token");
return respond("EINVALTOKEN");


var fn = methods[name]; var fn = methods[name];
if (!fn) { if (!fn) {

+ 14
- 2
js/fileserver.js Voir le fichier



var files = {}; var files = {};
function file(wpath, fpath) { function file(wpath, fpath) {
if (typeof fpath === "object")
return files[wpath] = fpath;

if (fpath === undefined) if (fpath === undefined)
fpath = wpath; fpath = wpath;




exports.canServe = canServe; exports.canServe = canServe;
function canServe(parts) { function canServe(parts) {
return files[parts.pathname] !== undefined;
return files[parts.pathname] || files[parts.pathname + "/"];
} }


exports.serve = serve; exports.serve = serve;
function serve(parts, res) { function serve(parts, res) {
res.end(files[parts.pathname]);
var f = files[parts.pathname];

if (!f && files[parts.pathname + "/"]) {
res.writeHead(302, {
location: parts.pathname+"/"
});
res.end();
} else {
res.end(f);
}
} }

+ 156
- 139
web/admin/lib.js Voir le fichier

var sessToken = "";
(function() {

window.apiLogin = apiLogin;
window.api = api;
window.elem = elem;
window.uploadEl = uploadEl;
window.async = async;
window.debounce = debounce;
window.error = error;
window.$$ = $$;

var sessToken = "";

function apiLogin(pass, cb) {
var extraHeads = [ [ "Session-Pass", pass ] ];

api("login", {}, (err, token) => {
if (token) {
sessToken = token;
cb(true);
} else {
cb(false);
}
}, extraHeads);
}

function argstr(args) {
return "?" + Object.keys(args).map(function(key) {
return encodeURIComponent(key)+"="+encodeURIComponent(args[key]);
}).join("&");
}


function apiLogin(pass, cb) {
var extraHeads = [ [ "Session-Pass", pass ] ];
function api(method, args, cb, extraHeads) {
var heads = new Headers();
heads.append("Session-Token", sessToken);
if (extraHeads)
extraHeads.forEach(h => heads.append(h[0], h[1]));

var opts = {
method: "POST",
headers: heads
};
fetch("/admin/api/"+method+argstr(args), opts)
.then(response => response.json())
.then(res => {
if (res.err && res.err === "EINVALTOKEN")
setView("login");
else
cb(res.err, res.obj)
});
}


api("login", {}, (err, token) => {
if (token) {
sessToken = token;
cb(true);
} else {
cb(false);
function elem(tag, props, children) {
var e;
if (tag instanceof HTMLElement)
e = tag;
else
e = document.createElement(tag);

if (props) {
for (var i in props) {
e[i] = props[i];
}
} }
}, extraHeads);
}

function argstr(args) {
return "?" + Object.keys(args).map(function(key) {
return encodeURIComponent(key)+"="+encodeURIComponent(args[key]);
}).join("&");
}

function api(method, args, cb, extraHeads) {
var heads = new Headers();
heads.append("Session-Token", sessToken);
if (extraHeads)
extraHeads.forEach(h => heads.append(h[0], h[1]));

var opts = {
method: "POST",
headers: heads
};
fetch("/admin/api/"+method+argstr(args), opts)
.then(response => response.json())
.then(res => cb(res.err, res.obj));
}

function elem(tag, props, children) {
var e;
if (tag instanceof HTMLElement)
e = tag;
else
e = document.createElement(tag);

if (props) {
for (var i in props) {
e[i] = props[i];

if (children) {
for (var i in children) {
e.appendChild(children[i]);
}
} }
}


if (children) {
for (var i in children) {
e.appendChild(children[i]);
e.appendTo = function(p) {
p.appendChild(e);
return e;
} }
}


e.appendTo = function(p) {
p.appendChild(e);
return e;
}
e.on = function(name, fn) {
e.addEventListener(name, function(evt) {
fn.call(e, evt);
}, false);
return e;
}


e.on = function(name, fn) {
e.addEventListener(name, function(evt) {
fn.call(e, evt);
}, false);
return e;
}
e.addClass = function(name) {
if (e.className.indexOf(name) !== -1)
return e;


e.addClass = function(name) {
if (e.className.indexOf(name) !== -1)
e.className += " "+name;
return e; return e;
}


e.className += " "+name;
return e;
}
e.removeClass = function(name) {
e.className = e.className
.replace(name, "")
.trim()
.replace(/ +/, "");
return e;
}

e.clear = function() {
var fc;
while (fc = e.firstChild)
e.removeChild(fc);
return e;
}


e.removeClass = function(name) {
e.className = e.className
.replace(name, "")
.trim()
.replace(/ +/, "");
return e; return e;
} }


e.clear = function() {
var fc;
while (fc = e.firstChild)
e.removeChild(fc);
return e;
var uploadElId = 0;
function uploadEl(args, cb) {
var id = uploadElId++;
var frame;
var form;
var fileEl;
return form = elem("form", {
className: "uploader",
action: "/admin/api/slide_file_upload"+argstr(args),
method: "post",
enctype: "multipart/form-data",
target: "upload-form-"+id
}, [
frame = elem("iframe", {
style: "display: none",
name: "upload-form-"+id
}).on("load", cb),

fileEl = elem("input", {
type: "file",
style: "display: none",
name: "file"
}).on("change", () => {
form.submit();
}),

elem("button", {
innerHTML: "Upload",
type: "button"
}).on("click", () => {
fileEl.click();
})
]);
} }


return e;
}

var uploadElId = 0;
function uploadEl(args, cb) {
var id = uploadElId++;
var frame;
var form;
var fileEl;
return form = elem("form", {
className: "uploader",
action: "/admin/api/slide_file_upload"+argstr(args),
method: "post",
enctype: "multipart/form-data",
target: "upload-form-"+id
}, [
frame = elem("iframe", {
style: "display: none",
name: "upload-form-"+id
}).on("load", cb),

fileEl = elem("input", {
type: "file",
style: "display: none",
name: "file"
}).on("change", () => {
form.submit();
}),

elem("button", {
innerHTML: "Upload",
type: "button"
}).on("click", () => {
fileEl.click();
})
]);
}

function async(n, cb) {
var args = [];
return function(arg) {
args.push(arg);

n -= 1;
if (n === 0)
cb(args);
function async(n, cb) {
var args = [];
return function(arg) {
args.push(arg);

n -= 1;
if (n === 0)
cb(args);
}
} }
}


function debounce(fn, ms) {
if (ms === undefined)
ms = 300;
function debounce(fn, ms) {
if (ms === undefined)
ms = 300;


var timeout;
return function() {
var timeout;
return function() {


if (timeout)
clearTimeout(timeout);
if (timeout)
clearTimeout(timeout);


timeout = setTimeout(function() {
fn();
timeout = null;
}, ms);
}
}
timeout = setTimeout(function() {
fn();
timeout = null;
}, ms);
}
}


function error(msg) {
alert(msg);
}
function error(msg) {
alert(msg);
}


var $$ = function() {
return elem(document.querySelector.apply(document, arguments));
}
function $$() {
return elem(document.querySelector.apply(document, arguments));
}
})();

+ 2
- 0
web/admin/view.js Voir le fichier

(function() { (function() {


window.setView = setView;

var root = $$("#root"); var root = $$("#root");


var views = { var views = {

Chargement…
Annuler
Enregistrer