1
0
mirror of https://github.com/falk-werner/webfuse synced 2024-10-27 20:34:10 +00:00
falk-werner_webfuse/example/daemon/www/js/webfuse/client.js
Falk Werner 87f34fa768 feat(authentication): provide an authentication mechanism (#19)
* moves server into session

* renames jsonrpc server to jsonrpc proxy

* moves server into session

* renames jsonrpc server to jsonrpc proxy

* adds json rpc server

* removes obsolete proxy from protocol

* changes interface of jsonrpc_proxy_onresult to accept previously parsed messages

* adds infrastructure to process incoming requests; fixes invalid read of ill formatted responses

* adds description of authentication request

* adds authentication request

* adds userdb for authentication purposes

* removes debug code: console.log()

* fixes cmake build error (missing openssl symbols)

* fixes typo

* replaces ASCII art by UML diagram

* renames BAD_NOACCESS to BAD_ACCESS_DENIED

* fixes style

* adds docu of authentication

* ignored false positives of flawfinder

* fixes style issues

* fixes javascript style issues
2019-04-01 22:15:12 +02:00

151 lines
3.7 KiB
JavaScript

import { BadState } from "./bad_state.js";
export class Client {
static get _PROTOCOL() { return "fs"; }
constructor(provider) {
this._provider = provider;
this._ws = null;
this.onopen = () => { };
this.onclose = () => { };
this.onerror = () => { };
}
connectTo(url) {
this.disconnect();
this._ws = new WebSocket(url, Client._PROTOCOL);
this._ws.onopen = this.onopen;
this._ws.onclose = this.onclose;
this._ws.onerror = this.onerror;
this._ws.onmessage = (message) => {
this._onmessage(message);
};
}
authenticate(type, credentials) {
const request = {
"method": "authenticate",
"params": [type, credentials],
"id": 42
};
this._ws.send(JSON.stringify(request));
}
disconnect() {
if (this._ws) {
this._ws.close();
this._ws = null;
}
}
isConnected() {
return ((this._ws) && (this._ws.readyState === WebSocket.OPEN));
}
_onmessage(message) {
try {
const request = JSON.parse(message.data);
const method = request.method;
const id = request.id;
const params = request.params;
if ("string" !== typeof(method)) {
throw new Error("parse error: missing field: \"method\"");
}
if (!params) {
throw new Error("parse error: missing field: \"params\"");
}
if ("number" === typeof(request.id)) {
this._invoke(method, params, id);
}
else {
this._notify(method, params);
}
}
catch (ex) {
// swallow
}
}
_invoke(method, params, id) {
this._invokeAsync(method, params).
then((result) => {
const response = { result, id };
this._ws.send(JSON.stringify(response));
}).
catch((ex) => {
const code = ex.code || BadState.BAD;
const response = {error: {code}, id};
this._ws.send(JSON.stringify(response));
});
}
async _invokeAsync(method, params) {
switch(method)
{
case "lookup":
return this._lookup(params);
case "getattr":
return this._getattr(params);
case "readdir":
return this._readdir(params);
case "open":
return this._open(params);
case "read":
return this._read(params);
default:
throw new BadState(BadState.NOT_IMPLEMENTED);
}
}
_notify(method, params) {
switch(method) {
case 'close':
this._close(params);
break;
default:
throw new Error(`Invalid method: "${method}"`);
}
}
async _lookup([parent, name]) {
return this._provider.lookup(parent, name);
}
async _getattr([inode]) {
return this._provider.getattr(inode);
}
async _readdir([inode]) {
return this._provider.readdir(inode);
}
async _open([inode, mode]) {
return this._provider.open(inode, mode);
}
_close([inode, handle, mode]) {
this._provider.close(inode, handle, mode);
}
async _read([inode, handle, offset, length]) {
const data = await this._provider.read(inode, handle, offset, length);
if ("string" === typeof(data)) {
return {
data: btoa(data),
format: "base64",
count: data.length
};
}
else {
throw new BadState(BadState.BAD);
}
}
}