diff --git a/authws.js b/authws.js new file mode 100644 index 0000000..dcb5cf7 --- /dev/null +++ b/authws.js @@ -0,0 +1,137 @@ +// Generated by LiveScript 1.6.0 +(function(){ + var bulma, h, AuthWS; + bulma = require("./bulma.ls"); + h = require('maquette').h; + AuthWS = function(socketUrl){ + var self, requestTypes, responseTypes, key, value; + self = {}; + requestTypes = { + "get-token": 0, + "add-user": 1, + "get-user": 2, + "get-user-by-credentials": 3, + "mod-user": 4, + "register": 5, + "get-extra": 6, + "set-extra": 7, + "update-password": 8, + "list-users": 9 + }; + responseTypes = { + "error": 0, + "token": 1, + "user": 2, + "user-added": 3, + "user-edited": 4, + "extra": 5, + "extra-updated": 6, + "users-list": 7 + }; + self.userOnSocketError = []; + self.userOnSocketClose = []; + self.callbacks = {}; + for (key in responseTypes) { + value = responseTypes[key]; + self.callbacks[value] = []; + } + self.addEventListener = function(type, callback){ + var ref$; + type = responseTypes[type]; + return (ref$ = self.callbacks)[type] = ref$[type].concat([callback]); + }; + self.openSocket = function(){ + self.socket = new WebSocket(socketUrl); + self.socket.onerror = function(event){ + var i$, ref$, len$, f; + for (i$ = 0, len$ = (ref$ = self.userOnSocketError).length; i$ < len$; ++i$) { + f = ref$[i$]; + f(event); + } + return self.socket.close(); + }; + self.socket.onclose = function(event){ + var i$, ref$, len$, f, results$ = []; + for (i$ = 0, len$ = (ref$ = self.userOnSocketClose).length; i$ < len$; ++i$) { + f = ref$[i$]; + results$.push(f(event)); + } + return results$; + }; + return self.socket.onmessage = function(event){ + var message, i$, ref$, len$, f, results$ = []; + message = JSON.parse(event.data); + for (i$ = 0, len$ = (ref$ = self.callbacks[message.mtype]).length; i$ < len$; ++i$) { + f = ref$[i$]; + results$.push(f(JSON.parse(message.payload))); + } + return results$; + }; + }; + self.reopen = function(){ + self.socket.close(); + return self.openSocket(); + }; + self.openSocket(); + self.send = function(type, opts){ + return self.socket.send(JSON.stringify({ + mtype: type, + payload: opts + })); + }; + self.getToken = function(login, password){ + return self.send(requestTypes['get-token'], JSON.stringify({ + login: login, + password: password + })); + }; + self.getUserByCredentials = function(login, password){ + return self.send(requestTypes['get-user-by-credentials'], JSON.stringify({ + login: login, + password: password + })); + }; + self.login = function(login, password){ + self.getToken(login, password); + return self.getUserByCredentials(login, password); + }; + self.getUser = function(uid){ + return self.send(requestTypes['get-user'], JSON.stringify({ + uid: uid + })); + }; + self.register = function(login, password){ + return self.send(requestTypes['register'], JSON.stringify({ + login: login, + password: password + })); + }; + self.getExtra = function(token, name){ + return self.send(requestTypes['get-extra'], JSON.stringify({ + token: token, + name: name + })); + }; + self.setExtra = function(token, name, extra){ + return self.send(requestTypes['set-extra'], JSON.stringify({ + token: token, + name: name, + extra: extra + })); + }; + self.updatePassword = function(login, oldPassword, newPassword){ + return self.send(requestTypes['update-password'], JSON.stringify({ + login: login, + old_password: oldPassword, + new_password: newPassword + })); + }; + self.listUsers = function(token){ + return self.send(requestTypes['list-users'], JSON.stringify({ + token: token + })); + }; + return self; + }; + module.exports = AuthWS; +}).call(this); diff --git a/bulma.js b/bulma.js new file mode 100644 index 0000000..49d9224 --- /dev/null +++ b/bulma.js @@ -0,0 +1,39 @@ +// Generated by LiveScript 1.6.0 +(function(){ + var h; + h = require('maquette').h; + module.exports = { + box: function(args, children){ + return h('div.box', args, children); + }, + title: function(level, args, label){ + if (!label) { + label = args; + args = {}; + } + return h("div.title.is-" + level, args, [label]); + }, + label: function(args, label){ + if (!label) { + label = args; + args = {}; + } + return h('label.label', args, [label]); + }, + input: function(args, children){ + return h('input.input', args, children); + }, + field: function(args, children){ + return h('div.field', args, children); + }, + modal: function(args, content){ + return h('div.modal', args, [h('div.modal-background', args.background), h('div.modal-content', [args.content])]); + }, + form: function(method, url, content){ + return h('form.form', { + action: url, + method: method + }, content); + } + }; +}).call(this); diff --git a/index.js b/index.js new file mode 100644 index 0000000..5115d8f --- /dev/null +++ b/index.js @@ -0,0 +1,67 @@ +// Generated by LiveScript 1.6.0 +(function(){ + var maquette, createProjector, h, projector, bulma, AuthWS, LoginForm, UserConfigurationPanel, UserAdminPanel, model, authwsUrl; + maquette = require("maquette"); + createProjector = maquette.createProjector, h = maquette.h; + projector = createProjector(); + bulma = require("./bulma.ls"); + AuthWS = require("./authws.ls"); + LoginForm = require("./login-form.ls"); + UserConfigurationPanel = require("./user-configuration-panel.ls"); + UserAdminPanel = require("./user-admin-panel.ls"); + model = { + token: void 8 + }; + authwsUrl = "ws://localhost:9999/auth.JSON"; + document.addEventListener('DOMContentLoaded', function(){ + var userConfigPanel, userAdminPanel, loginForm; + userConfigPanel = void 8; + userAdminPanel = void 8; + loginForm = LoginForm({ + enableRegistration: true, + authwsUrl: authwsUrl, + onLogin: function(user, token){ + model.user = user; + model.token = token; + if (false) { + userAdminPanel = UserAdminPanel({ + authwsUrl: authwsUrl, + user: model.user, + token: model.token, + onModelUpdate: function(){ + return projector.scheduleRender(); + }, + onLogout: function(){ + model.token = void 8; + return model.user = void 8; + } + }); + } else { + userConfigPanel = UserConfigurationPanel({ + authwsUrl: authwsUrl, + user: model.user, + token: model.token, + onModelUpdate: function(){ + return projector.scheduleRender(); + }, + onLogout: function(){ + model.token = void 8; + return model.user = void 8; + } + }); + } + return projector.scheduleRender(); + }, + onError: function(error){ + return projector.scheduleRender(); + } + }); + return projector.append(document.body, function(){ + return h('div.body', [model.token === void 8 + ? h('div.section.hero.is-fullheight', [h('div.hero-body', [h('div.container', [h('div.columns', [h('div.column', []), h('div.column.is-3', [loginForm.render()]), h('div.column', [])])])])]) + : userConfigPanel + ? h('div.section', [h('div.container', [userConfigPanel.render()])]) + : userAdminPanel ? h('div.section', [h('div.container', [userAdminPanel.render()])]) : void 8]); + }); + }); +}).call(this); diff --git a/login-form.js b/login-form.js new file mode 100644 index 0000000..2498490 --- /dev/null +++ b/login-form.js @@ -0,0 +1,179 @@ +// Generated by LiveScript 1.6.0 +(function(){ + var maquette, h, bulma, AuthWS, LoginForm; + maquette = require("maquette"); + h = maquette.h; + bulma = require("./bulma.ls"); + AuthWS = require("./authws.ls"); + LoginForm = function(args){ + var self, authWs; + args || (args = {}); + self = { + onLogin: args.onLogin || function(){}, + onError: args.onError || function(){}, + scheduleRender: args.scheduleRender || function(){}, + currentView: "login", + enableRegistration: args.enableRegistration || false, + registrating: false, + input: { + login: "", + password: "", + repeatPassword: "" + }, + lockedInput: true, + error: void 8, + authwsUrl: args.authwsUrl || (location.protocol === 'https' ? 'wss' : 'ws') + '://' + location.hostname + ":9999/auth.JSON" + }; + authWs = AuthWS(self.authwsUrl); + authWs.socket.onopen = function(){ + console.log("socket is open"); + self.lockedInput = false; + return self.scheduleRender(); + }; + authWs.userOnSocketError.push(function(){ + self.error = "socket error"; + return self.onError.apply(this, arguments); + }); + authWs.addEventListener('token', function(message){ + self.error = void 8; + self.token = message.token; + self.lockedInput = false; + if (self.user) { + return self.onLogin(self.user, self.token); + } + }); + authWs.addEventListener('user', function(message){ + self.error = void 8; + self.user = message.user; + if (self.token) { + return self.onLogin(self.user, self.token); + } + }); + authWs.addEventListener('user-added', function(message){ + var ref$, login, password; + ref$ = { + login: self.input.login, + password: self.input.password + }, login = ref$.login, password = ref$.password; + console.log("user added, duh"); + self.user = message.user; + return authWs.getToken(login, password); + }); + authWs.addEventListener('error', function(message){ + if (message.reason === "user not found") { + return; + } + self.error = message.reason; + self.lockedInput = false; + return self.onError(message.reason); + }); + self.render = function(){ + if (self.error === "socket error") { + return h('div.notification.is-danger', [h('div.title.is-4', ["WebSocket error!"]), h('p', ["Cannot connect to authd."])]); + } + return h('form.form.login-form', { + key: self, + onsubmit: function(e){ + var ref$, login, password; + ref$ = { + login: self.input.login, + password: self.input.password + }, login = ref$.login, password = ref$.password; + self.lockedInput = true; + if (self.registrating) { + authWs.register(login, password); + } else { + authWs.getToken(login, password); + authWs.getUserByCredentials(login, password); + } + return e.preventDefault(); + } + }, [ + h('div.field', { + key: 'login' + }, [ + bulma.label("Login"), bulma.input({ + type: "text", + id: "login", + name: "login", + classes: { + "is-danger": self.error === "invalid credentials" + }, + disabled: self.lockedInput, + oninput: function(e){ + return self.input.login = e.target.value; + } + }) + ]), h('div.field', { + key: 'password' + }, [ + bulma.label("Password"), bulma.input({ + type: "password", + id: "password", + name: "password", + classes: { + "is-danger": self.error === "invalid credentials" + }, + oninput: function(e){ + return self.input.password = e.target.value; + }, + disabled: self.lockedInput + }) + ]), self.registrating ? h('div.field', { + key: 'password-repeat' + }, [ + bulma.label("Password (reapeat)"), bulma.input({ + type: 'password', + id: 'password-repeat', + name: 'password-repeat', + classes: { + "is-danger": self.input.password !== self.input.repeatPassword + }, + disabled: self.lockedInput, + oninput: function(e){ + return self.input.repeatPassword = e.target.value; + } + }) + ]) : void 8, self.error ? h('div.field', { + key: 'error-notification' + }, [h('div.notification.is-danger', [self.error])]) : void 8, self.registrating + ? h('div.field.is-grouped', { + key: 'login-button' + }, [self.input.login === "" + ? h('button.button.is-static.is-fullwidth', { + type: 'submit' + }, ["(empty login)"]) + : self.input.password !== self.input.repeatPassword + ? h('button.button.is-static.is-fullwidth', { + type: 'submit' + }, ["(passwords don’t match)"]) + : self.input.password === "" + ? h('button.button.is-static.is-fullwidth', { + type: 'submit' + }, ["(empty password)"]) + : h('button.button.is-success.is-fullwidth', { + type: 'submit' + }, ["Register!"])]) + : h('div.field.is-grouped', { + key: 'login-button' + }, [h('button.button.is-fullwidth.is-success', { + type: 'submit' + }, ["Log in!"])]), h('div.field.level', { + key: 'extra-buttons' + }, [self.enableRegistration ? h('div.level-right', [self.registrating + ? h('a.link', { + onclick: function(e){ + return self.registrating = false; + } + }, ["Log in"]) + : h('a.link', { + onclick: function(e){ + return self.registrating = true; + } + }, ["Create account!"])]) : void 8]) + ]); + }; + return self; + }; + module.exports = LoginForm; +}).call(this); diff --git a/main.bundle.js b/main.bundle.js new file mode 100644 index 0000000..e42db8e --- /dev/null +++ b/main.bundle.js @@ -0,0 +1,1582 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i startsWith + if (eventHandlerInterceptor) { + propValue = eventHandlerInterceptor(propName, propValue, domNode, properties); // intercept eventhandlers + } + if (propName === 'oninput') { + /* tslint:disable no-this-keyword no-invalid-this only-arrow-functions no-void-expression */ + (function () { + // record the evt.target.value, because IE and Edge sometimes do a requestAnimationFrame between changing value and running oninput + var oldPropValue = propValue; + propValue = function (evt) { + oldPropValue.apply(this, [evt]); + evt.target['oninput-value'] = evt.target.value; // may be HTMLTextAreaElement as well + }; + }()); + /* tslint:enable */ + } + domNode[propName] = propValue; + } + } + else if (projectionOptions.namespace === NAMESPACE_SVG) { + if (propName === 'href') { + domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue); + } + else { + // all SVG attributes are read-only in DOM, so... + domNode.setAttribute(propName, propValue); + } + } + else if (type === 'string' && propName !== 'value' && propName !== 'innerHTML') { + domNode.setAttribute(propName, propValue); + } + else { + domNode[propName] = propValue; + } + } + }; + for (var i = 0; i < propCount; i++) { + _loop_1(i); + } + }; + var addChildren = function (domNode, children, projectionOptions) { + if (!children) { + return; + } + for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { + var child = children_1[_i]; + createDom(child, domNode, undefined, projectionOptions); + } + }; + var initPropertiesAndChildren = function (domNode, vnode, projectionOptions) { + addChildren(domNode, vnode.children, projectionOptions); // children before properties, needed for value property of