Skip to content

Commit

Permalink
Merge pull request #592 from zaucker/SelfService
Browse files Browse the repository at this point in the history
Self service
  • Loading branch information
zaucker authored Nov 28, 2024
2 parents 6452667 + e42124e commit 405f0cd
Show file tree
Hide file tree
Showing 56 changed files with 1,191 additions and 395 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.mise.toml
*.tar.gz
.precomp/
tmp/
t/test-data/.secret
Expand All @@ -15,5 +17,16 @@ 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/
thirdparty/bin/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
- 6.4.1, 2024-11-22, [email protected]
- New Self Service for account creation and password reset

- 6.4.0, 2023-06-22, [email protected]

- Allow absolute path for --technical-file
Expand Down
34 changes: 10 additions & 24 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,33 +1,19 @@
# Copyright (C) 2020 Fritz Zaucker
# Copyright (C) 2023 Fritz Zaucker

AUTOMAKE_OPTIONS = foreign
AUTOMAKE_OPTIONS = foreign

SUBDIRS = etc frontend
# SUBDIRS = thirdparty etc frontend
SUBDIRS = thirdparty frontend

PUB := $(shell find -L public -type d \( -name ".??*" -o -name transpiled \) -prune -o -not -name "*db.json" -a -not -name "*.map" -a -not -name "*~" -a -not -name transpiled -a -not -name "*.tmp" -a -type f -print )
SHARE := $(shell test -d share && find -L share -type d -name ".??*" -prune -o -not -name ".*" -a -not -name "*~" -a -not -name "*.tmp" -a -not -name '*.sql' -a -not -wholename '*/Docu/*' -a -not -wholename '*/Docu' -a -not -wholename '*/_Attic' -a -not -wholename '*/_Attic/*' -a -type f -print)

PERLTESTS := $(shell find -L t -name "*.t")
PM := $(shell find -L lib -name "*.pm")
TEMPL := $(shell test -d templates && find -L templates -type f -name "*.ep")
SHARE := $(shell test -d share && find -L share -type d -name ".??*" -prune -o -not -name ".*" -a -not -name "*~" -a -not -name "*.tmp" -a -not -path "share/Models/Experimental/*" -a -type f -print)

#EXTRA_DIST = META6.json COPYRIGHT LICENSE CHANGES AUTHORS bootstrap $(PUB) $(POD) $(TEMPL) $(SHARE)
PERLTESTS := $(shell find t -name "*.t")
PM := $(shell find lib -name "*.pm")

EXTRA_DIST = META6.json COPYRIGHT bin lib/Agrammon bootstrap $(PUB) $(SHARE) # $(PERLTESTS)
# EXTRA_DIST = VERSION cpanfile COPYRIGHT LICENSE CHANGELOG AUTHORS bootstrap $(PUB) $(wildcard t/*.t) $(POD) $(TEMPL) $(PERLTESTS) $(SHARE) Dockerfile

YEAR := $(shell date +%Y)
DATE := $(shell date +%Y-%m-%d)
EXTRA_DIST = META6.json README.md VERSION cpanfile COPYRIGHT CHANGELOG.md bootstrap $(PUB) $(wildcard t/*.t) $(POD) $(TEMPL) $(PERLTESTS) $(SHARE) bin lib

datadir = $(prefix)
nobase_data_DATA = $(PUB) $(TEMPL) $(SHARE)

README.md COPYRIGHT:
$(PERL) -i -p -e 's/(#VERSION#|\d+\.\d+\.\d+[^.\s]*)/$(PACKAGE_VERSION)/g;s/(#YEAR#|20[1-9]\d)/$(YEAR)/g;s/(#DATE#|20[1-9]\d-[01]\d-[0-3]\d)/$(DATE)/g;' $@


LANGUAGES := $(shell $(PERL) -e 'use JSON::PP qw(decode_json); print join(" ", map {"share/".$$_.".po"} @{decode_json(join("",<>))->{locales}})' frontend/compile.json)

test:
prove -j8 -e 'raku -Ilib' t

unit-test:
AGRAMMON_UNIT_TEST=1 prove -j8 -e 'raku -Ilib' t
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
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.3.0
6.4.1
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
8 changes: 6 additions & 2 deletions bin/agrammon.raku
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/usr/bin/env perl6

#!/usr/bin/env raku
# unbuffered output
$*OUT.out-buffer = False;
$*ERR.out-buffer = False;
use lib $*PROGRAM.resolve.parent(2) ~ '/lib';
use lib:from<Perl5> $*PROGRAM.resolve.parent(2) ~ '/Inline/perl5';
use Agrammon::UI::CommandLine;
11 changes: 7 additions & 4 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (C) 2020 Oetiker+Partner AG

AC_INIT([agrammon],m4_esyscmd([jq '.version' < META6.json | tr -d '""' ]),[[email protected]])
AC_PREREQ([2.59])
AC_INIT([agrammon], m4_esyscmd(jq '.version' < META6.json | tr -d '""' | tr -d '\n'),[[email protected]])
AC_PREREQ([2.71])
AC_CONFIG_AUX_DIR(conftools)

MJ_CLASS=Agrammon
Expand Down 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 Expand Up @@ -129,8 +132,7 @@ else
fi

AC_ARG_ENABLE(pkgonly,
AC_HELP_STRING([--enable-pkgonly],
[Skip all checking]))
AS_HELP_STRING([--enable-pkgonly],[Skip all checking]))
AC_SUBST(enable_pkgonly)

actual_prefix=$prefix
Expand All @@ -154,6 +156,7 @@ AC_CONFIG_FILES([
Makefile
etc/Makefile
frontend/Makefile
thirdparty/Makefile
])

AC_SUBST(VERSION)
Expand Down
1 change: 1 addition & 0 deletions cpanfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requires 'Excel::Writer::XLSX';
7 changes: 6 additions & 1 deletion dev/META6.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Agrammon",
"description": "Simulation model for calculating ammonia and Nx/NOx emissions from agriculture.",
"version": "6.4.0",
"version": "6.4.1",
"perl": "6.*",
"authors": [
"Fritz Zaucker <[email protected]>",
Expand All @@ -11,16 +11,20 @@
"depends": [
"Cro::Core",
"Cro::HTTP",
"Cro::HTTP::Log::File",
"Cro::HTTP::Session::Pg",
"Cro::OpenAPI::RoutesFromDefinition:ver<1.0.4+>",
"Cro::WebApp::Template",
"Cro::APIToken",
"Cro::APIToken::Store::Pg",
"Cro::HTTP::Log::File",
"Crypt::Random",
"Crypt::Random::Extra",
"Data::Dump::Tree",
"DB::Pg",
"Digest::SHA1::Native",
"Email::MIME",
"Inline::Perl5",
"IO::Path::ChildSecure",
"IO::String",
"LibXML:ver<0.7.9+>",
Expand All @@ -29,6 +33,7 @@
"OO::Monitors",
"Shell::Command",
"Spreadsheet::XLSX:ver<0.2.4+>",
"Temp::Path",
"Text::CSV",
"YAMLish",
"Cro::APIToken",
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
1 change: 0 additions & 1 deletion frontend/source-sha

This file was deleted.

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();
}
}
});
Loading

0 comments on commit 405f0cd

Please sign in to comment.