Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self service #592

Merged
merged 22 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading