Skip to content

Commit

Permalink
Add SelfService account creation and password reset
Browse files Browse the repository at this point in the history
  • Loading branch information
zaucker committed Nov 22, 2024
1 parent 1ca29f8 commit 6ede27f
Show file tree
Hide file tree
Showing 38 changed files with 842 additions and 317 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.mise.toml
.precomp/
tmp/
t/test-data/.secret
Expand All @@ -15,12 +16,15 @@ aclocal.m4
etc/*.cfg
etc/*.yaml
etc/*.secret
Inline/
public/
conftools/
test/rest/
thirdparty/build.log
thirdparty/cache
thirdparty/carton/
thirdparty/latest-build
thirdparty/sources
thirdparty/touch
thirdparty/lib/
thirdparty/work/
Expand Down
1 change: 0 additions & 1 deletion .tool-versions

This file was deleted.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Load a database dump (auto creation not yet implemented)

## Installation Web App

apt install libnsl-dev

Install npm and jq from your distro and then run

mkdir -p public # first time only
Expand Down
7 changes: 7 additions & 0 deletions bin/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dist_bin_SCRIPTS = $(MJ_SCRIPT).raku

# make sure we have all Raku dependencies
# pre-compile
install-exec-hook:
zef --/test --deps-only install ..
PERL5LIB=$(prefix)/Inline/perl5 raku -I$(libdir) -c $(bindir)/$(MJ_SCRIPT).raku
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ if test -x "$NODE"; then
v13*)
AC_MSG_RESULT(ok v13)
;;
v22*)
AC_MSG_RESULT(ok v22)
;;
*)
AC_MSG_RESULT(no);
NODE=old-node
Expand Down
1 change: 1 addition & 0 deletions dev/META6.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"Cro::APIToken::Store::Pg",
"Cro::HTTP::Log::File",
"Crypt::Random",
"Crypt::Random::Extra",
"Data::Dump::Tree",
"DB::Pg",
"Digest::SHA1::Native",
Expand Down
1 change: 1 addition & 0 deletions frontend/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ clean: node_modules
$(NPX) qx compile --target=build --feedback=false --erase --update-po-files
mkdir -p ../public/$(QX_CLASS)
cp -p compiled/build/$(QX_CLASS)/*.js ../public/$(QX_CLASS)
cp -p compiled/build/$(QX_CLASS)/*.js.map ../public/$(QX_CLASS)
cp -p compiled/build/index.html ../public
cp -pa compiled/build/resource ../public
touch $@
Expand Down
88 changes: 40 additions & 48 deletions frontend/source/class/agrammon/Application.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ qx.Class.define('agrammon.Application', {
main: function() {
this.base(arguments);

var rv = -1; // Return value assumes failure.
let rv = -1; // Return value assumes failure.
if (navigator.appName == 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
let ua = navigator.userAgent;
let re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null) {
rv = parseFloat( RegExp.$1 );
}
Expand All @@ -37,24 +37,24 @@ qx.Class.define('agrammon.Application', {
qx.log.appender.Console;
}

var param, params = this.__getParams();
for (var i=0; i<params.length; i++) {
let param, params = this.__getParams();
for (let i=0; i<params.length; i++) {
if (params[i] != null) {
param = params[i].split("=");
}
if (param[0] == 'lang') {
if (param[0] == 'lang') {
qx.locale.Manager.getInstance().setLocale(param[1]);
}
}
}

var that = this;
let that = this;

this.__rpc = agrammon.io.remote.Rpc.getInstance();

qx.event.message.Bus.subscribe('agrammon.main.logout', this.__logout, this);
qx.event.message.Bus.subscribe('agrammon.main.login', this.__login, this);

var root = this.getRoot();
let root = this.getRoot();
root.setBlockerColor("#bfbfbf");
root.setBlockerOpacity(0.5);

Expand All @@ -70,8 +70,9 @@ qx.Class.define('agrammon.Application', {

let loginDialog =
new agrammon.module.user.Login(this.tr("Please authenticate yourself"));
this.__loginDialog = loginDialog;

for (var id in qx.core.Id.getInstance().getRegisteredObjects()) {
for (let id in qx.core.Id.getInstance().getRegisteredObjects()) {
this.debug('Id=', id);
}

Expand All @@ -80,27 +81,27 @@ qx.Class.define('agrammon.Application', {
}

// the base layout of the page.
var main = new qx.ui.container.Composite(new qx.ui.layout.VBox());
let main = new qx.ui.container.Composite(new qx.ui.layout.VBox());
main.set({ padding: 5 });

root.add(main, { edge: 0 });

var title = new qx.ui.basic.Label().set({
let title = new qx.ui.basic.Label().set({
value : 'AGRAMMON', // will be overwritten from config
font : qx.bom.Font.fromString('14px bold sans-serif'),
textColor : '#808080'
});

var output = new agrammon.module.output.Output(false);
var reference = new agrammon.module.output.Output(true);
let output = new agrammon.module.output.Output(false);
let reference = new agrammon.module.output.Output(true);

var propEditor = new agrammon.module.input.PropTable('InputTable');
var navbar = new agrammon.module.input.NavBar(propEditor);
let propEditor = new agrammon.module.input.PropTable('InputTable');
let navbar = new agrammon.module.input.NavBar(propEditor);

var mainMenu;
let mainMenu;

var results;
var getCfgFunc = qx.lang.Function.bind(function(data, exc, id) {
let results;
let getCfgFunc = qx.lang.Function.bind(function(data, exc, id) {
if (exc == null) {
this.debug('getCfgFunc(): title=' +data.title.en);
this.debug('getCfgFunc(): version=' +data.version);
Expand All @@ -111,9 +112,9 @@ qx.Class.define('agrammon.Application', {
if (data.guiVariant != 'Regional') {
results = new agrammon.module.output.Results(output);
}
var input = new agrammon.module.input.Input(propEditor, navbar, results);
var tabview = new agrammon.module.Main(input, output, reference);
var editMenu = new agrammon.ui.menu.NavMenu(navbar);
let input = new agrammon.module.input.Input(propEditor, navbar, results);
let tabview = new agrammon.module.Main(input, output, reference);
let editMenu = new agrammon.ui.menu.NavMenu(navbar);
mainMenu = new agrammon.ui.menu.MainMenu(tabview, title, editMenu);

main.add(mainMenu);
Expand Down Expand Up @@ -141,11 +142,12 @@ qx.Class.define('agrammon.Application', {
this.__rpc.callAsync( getCfgFunc, 'get_cfg');

this.__authenticate = function(data, exc, id) {
// console.log('Application.__authenticate():', data, exc, id);
if (exc == null) {
var username = data.username;
var role = data.role;
var news = data.news;
var lastLogin = String(data.lastLogin);
let username = data.username;
let role = data.role;
let news = data.news;
let lastLogin = String(data.lastLogin);
qx.event.message.Bus.dispatchByName(
'agrammon.info.setUser',
{ username : username, role : role }
Expand Down Expand Up @@ -194,30 +196,23 @@ qx.Class.define('agrammon.Application', {
__authenticate: null,
__retry: null,
__rpc: null,

__supports_html5_storage: function() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
},
__loginDialog: null,

close : function(e) {
this.base(arguments);
this.debug('Application.close()');
console.log('Application.close()');
// Prompt user
// return "AGRAMMON: Do you really want to close the application?";
},

terminate : function(e) {
this.base(arguments);
this.debug('Application.terminate()');
console.log('Application.terminate()');
},

__getParams : function() {
var params = "";
var urlParams = window.location.search;
let params = "";
let urlParams = window.location.search;
if (urlParams.length > 0) {
urlParams = urlParams.substr(1, urlParams.length);
if (params != null) {
Expand All @@ -228,31 +223,28 @@ qx.Class.define('agrammon.Application', {
},

__login: function(msg) {
var userData = msg.getData();
let userData = msg.getData();
this.__retry = userData.retry;
this.debug('__login(' + userData.username + ')');
if (this.__supports_html5_storage() && userData.remember) {
localStorage.setItem('agrammonUsername', userData.username);
localStorage.setItem('agrammonPassword', userData.password);
localStorage.setItem('agrammonRemember', userData.remember);
}
if (userData.sudoUsername === undefined) {
userData.sudoUsername = null;
}
this.__rpc.callAsync(this.__authenticate, 'auth', userData);
},

__logout: function() {
// console.log('Application.__logout()');
this.__rpc.callAsync( qx.lang.Function.bind(this.__logoutFunc,this), 'logout');
qx.event.message.Bus.dispatchByName('agrammon.NavBar.clearTree', null);
qx.event.message.Bus.dispatchByName('agrammon.input.select');
},

__logoutFunc: function(data, exc, id) {
// console.log('Application.__logoutFunc():', data, exc, id);
if (exc == null || exc == 403) {
if (data.sudoUser) {
var infoOnly = true;
var dialog = new agrammon.ui.dialog.Confirm(
if (data && data.sudoUser) {
let infoOnly = true;
let dialog = new agrammon.ui.dialog.Confirm(
this.tr("End change user"),
this.tr("Returning from %1 to %2", data.sudoUser, data.username),
qx.lang.Function.bind(function() {
Expand All @@ -270,7 +262,7 @@ qx.Class.define('agrammon.Application', {
else {
alert(exc);
}
new agrammon.module.user.Login(this.tr("Please authenticate yourself")).open();
this.__loginDialog.open();
}
}
});
32 changes: 18 additions & 14 deletions frontend/source/class/agrammon/io/remote/Rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ qx.Class.define('agrammon.io.remote.Rpc', {
* @param data {Map} the data to send.
*/
callAsync : function(handler, methodName, data) {
var req = new qx.io.request.Xhr(methodName, "POST");
let req = new qx.io.request.Xhr(methodName, "POST");
if (data != null) {
req.setRequestData(data);
req.setRequestHeader("Content-Type", "application/json");
Expand All @@ -60,8 +60,8 @@ qx.Class.define('agrammon.io.remote.Rpc', {
this.__pending = { methodName : methodName, data : data, handler : handler };
}
req.addListener("statusError", function(e) {
var req = e.getTarget();
this.handleStatusError(req, methodName);
let req = e.getTarget();
this.handleStatusError(req, methodName, handler, data);
}, this);
let that = this;
req.addListener("success", function(e) {
Expand All @@ -84,18 +84,19 @@ qx.Class.define('agrammon.io.remote.Rpc', {
req.send();
},

handleStatusError : function(req, methodName) {
var response = req.getResponse();
var status = req.getStatus();
var statusText = req.getStatusText();
console.error('Rpc.callAsync('+methodName+'): status=', status, ':', statusText, ', response=', response);
handleStatusError : function(req, methodName, handler, data) {
let response = req.getResponse();
let status = req.getStatus();
let statusText = req.getStatusText();
console.log('Rpc.callAsync('+methodName+'): status=', status, ':', statusText, ', response=', response);
let username = agrammon.Info.getInstance().getUserName();
if (response && response.error) {
var params = [
let params = [
qx.locale.Manager.tr("Error") + ' ' + status,
response.error,
'error',
];
if (!agrammon.Info.getInstance().getUserName()) {
if (!username) {
params.push( { msg: 'agrammon.main.logout', data: null} );
}
// no results
Expand All @@ -107,18 +108,21 @@ qx.Class.define('agrammon.io.remote.Rpc', {
else {
let retry = true;
let sudo = null;
let title;
let title = qx.locale.Manager.tr("Please authenticate yourself");
switch (status) {
case 404:
case 401:
title = qx.locale.Manager.tr("%1: Session expired: please login again", status);
if (username) {
title = qx.locale.Manager.tr("%1: Session expired: please login again", status);
}
break;
default:
title = qx.locale.Manager.tr("Error %1: %2 - please login again", status, statusText);
break;
}
new agrammon.module.user.Login(title, sudo, retry).open();
}
handler(data);
},

/* A variant of the asyncCall method which pops up error messages
Expand All @@ -132,9 +136,9 @@ qx.Class.define('agrammon.io.remote.Rpc', {
* @return {var} the method call reference.
*/
callAsyncSmart : function(handler, methodName) {
var origHandler = handler;
let origHandler = handler;

var superHandler = function(ret, exc, id) {
let superHandler = function(ret, exc, id) {
if (exc) {
agrammon.ui.dialog.MsgBox.getInstance().exc(exc);
} else {
Expand Down
4 changes: 2 additions & 2 deletions frontend/source/class/agrammon/module/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ qx.Class.define('agrammon.module.Main',
this.__selectInput, this);
this.set({padding:0});

var report = new agrammon.module.output.Reports(output, reference);
let report = new agrammon.module.output.Reports(output, reference);
this.add(input);
this.add(report);

// Thomas Kupper: not needed
// var graph = new agrammon.module.output.Graphs(output, reference);
// let graph = new agrammon.module.output.Graphs(output, reference);
// this.add(graph);

}, // construct
Expand Down
Loading

0 comments on commit 6ede27f

Please sign in to comment.