This commit is contained in:
Midgard 2020-03-25 17:05:25 +01:00
parent f275a03b93
commit fcbb561d62
Signed by: midgard
GPG key ID: 511C112F1331BBB4
3 changed files with 150 additions and 77 deletions

View file

@ -3,9 +3,18 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Battermost</title>
<title>Bettermost</title>
</head>
<body>
<form>
<table>
<tr><th>Server</th><td><input type="text" id="server" value="http://localhost:8080"/></td></tr>
<tr><th>Username</th><td><input type="text" id="username"/></td></tr>
<tr><th>Password</th><td><input type="password" id="password"/></td></tr>
</table>
<input type="submit" onclick="this.disabled = true; this.value = 'Logging in...'; logIn(); return false" value="Log in"/>
</form>
<script type="text/javascript" src="xhr.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
</html>

125
main.js
View file

@ -1,84 +1,57 @@
//async function postJson(url, data = {}, options = {}) {
//const response = await fetch(url, {
//method: "POST",
//mode: "no-cors",
//credentials: "include",
//headers: { "Content-Type": "application/json" },
//redirect: "follow",
//referrerPolicy: "no-referrer",
//body: JSON.stringify(data),
//...options
//});
////return await response.json();
//return response;
//}
"use strict";
//var endpoint = "https://mattermost.zeus.gent/api/v4"; // Must not end with slash
var endpoint = "http://localhost:8080"; // Must not end with slash
var username = "fill me in";
var password = "fill me in";
function byId(id, nullOk=false) {
const el = document.getElementById(id);
if (!el && !nullOk) {
console.error(`No element #${id}`);
}
return el;
}
class MattermostApi {
constructor(endpoint) {
this.endpoint = endpoint;
}
function scopeToArg(f) {
return function(...rest) {
return f(this, ...rest);
async validateToken(token) {
const response = await ajax.getJson(`${this.endpoint}/users/me`, {
headers: {
"Token": `Authorization: Bearer ${token}`
}
});
return response.ok;
}
logIn(username, password) {
return ajax.postJson(`${this.endpoint}/users/login`, {
"login_id": username,
"password": password
})
.then(response => {
let token = response.getHeader("Token");
window.localStorage.setItem("token", token);
return response;
})
.then(response => {
document.body.innerHTML = "";
const pre = document.createElement("pre");
pre.innerText = JSON.stringify(response.json, null, 2);
document.body.appendChild(pre);
return response;
})
.catch(error => {
console.error(error);
document.body.innerText = `An error occurred: ${error}`;
});
}
}
function postJson(url, data={}, options={}) {
const prom = new Promise((resolve, reject) => {
let oReq = new XMLHttpRequest();
oReq.addEventListener("load", scopeToArg(resolve));
oReq.addEventListener("abort", scopeToArg(reject));
oReq.addEventListener("error", scopeToArg(reject));
oReq.addEventListener("timeout", scopeToArg(reject));
oReq.open("POST", url);
oReq.send(JSON.stringify(data));
function logIn() {
let endpoint = byId("server").value;
if (!endpoint.endsWith("/")) endpoint += "/";
endpoint += "api/v4";
});
return prom;
let api = new MattermostApi(endpoint);
api.logIn(byId("username").value, byId("password").value);
}
var token = null;
function printIt(response) {
console.log(response);
if (response.status == 0) {
document.body.innerText = "Network error";
return;
}
if (200 <= response.status && response.status < 300) {
try {
const json = JSON.parse(response.response);
document.body.innerHTML = "";
const pre = document.createElement("pre");
pre.innerText = "Received " + JSON.stringify(json, null, 2);
document.body.appendChild(pre);
token = response.getResponseHeader("token");
window.localStorage.setItem("token", token);
return token;
} catch(e) {
document.body.innerText = "The server did not reply with a valid JSON object. Make sure the server URL points to a Mattermost instance that is working correctly.";
}
} else {
console.log(response.getAllResponseHeaders());
try {
const json = JSON.parse(response.response);
document.body.innerText = "Failed to log in: " + json.message;
} catch(e) {
document.body.innerText = "Error: " + response.statusText;
}
}
}
postJson(`${endpoint}/api/v4/users/login`, {
"login_id": username,
"password": password
})
.then(printIt, printIt)
.then(token => console.log(token));

91
xhr.js Normal file
View file

@ -0,0 +1,91 @@
const ajax = (function() { "use strict";
class NetworkError extends Error {}
class UnexpectedMimeError extends Error {}
class InvalidJsonError extends Error {}
const MIME_JSON = "application/json";
/**
* Wrap a function so that it receives `this` as first argument.
*/
function thisToArg(f) {
return function(...rest) {
return f(this, ...rest);
}
}
function xhrInitForPromise(resolve, reject, url, method, headers) {
const t_resolve = thisToArg(resolve),
t_reject = thisToArg(reject);
let xhr = new XMLHttpRequest();
xhr.addEventListener("load", t_resolve);
xhr.addEventListener("error", t_resolve);
xhr.addEventListener("abort", t_reject);
xhr.addEventListener("timeout", t_reject);
xhr.open(method, url);
for (let header of Object.getOwnPropertyNames(headers)) {
xhr.setRequestHeader(header, headers[header]);
}
return xhr;
}
function xhrParseJsonResponse(xhr) {
if (xhr.status == 0) {
console.error(xhr);
throw new NetworkError("Failed to connect to server");
}
if (!xhr.responseText) {
const json = null;
} else {
const contentType = xhr.getResponseHeader("Content-Type");
if (contentType != MIME_JSON) {
throw new UnexpectedMimeError(`Server did not reply with JSON but with ${contentType}`);
}
try {
const json = JSON.parse(xhr.responseText);
} catch(e) {
throw new InvalidJsonError();
}
}
return {
ok: 200 <= xhr.status && xhr.status < 300,
status: xhr.status,
statusText: xhr.statusText,
getHeader: xhr.getResponseHeader,
json,
xhr,
};
}
function getJson(url, options={}) {
if (!options.headers) options.headers = {};
options.headers["Accept"] = MIME_JSON;
return new Promise((resolve, reject) => {
let xhr = xhrInitForPromise(resolve, reject, url, "GET", options.headers);
xhr.send();
}).then(xhrParseJsonResponse);
}
function postJson(url, data={}, options={}) {
if (!options.headers) options.headers = {};
options.headers["Content-Type"] = MIME_JSON;
options.headers["Accept"] = MIME_JSON;
return new Promise((resolve, reject) => {
let xhr = xhrInitForPromise(resolve, reject, url, "POST", options.headers);
xhr.send(JSON.stringify(data));
}).then(xhrParseJsonResponse);
}
return {
NetworkError, UnexpectedMimeError, InvalidJsonError,
getJson, postJson
};
})();