A middleware and alternative web GUI to access Maconomy. It is mainly intended as a programming exercise but is actually somewhat easier to work with than the main Maconomy GUI.
Point you browser at https://micronomy.init.se/ and log in with your B3 Maconomy credentials, or with the "Logga in med Microsoft" button if single sign-on is available - see Single sign-on below. Both methods work side by side.
To run it locally you can either install Rakudo and the required modules or make sure you have a working Docker installation and build and run the Dockerfile. The browser will complain about the fake certificate in use when running locally but that's expected. Just running
./micronomy.sh docker
could be enough.
Technically there's nothing stopping you from connecting the micronomy service to some other Maconomy backend but only the B3 Maconomy has been tested.
Time is expected to be filled in as decimal hours; eg. "an hour and a
half" should be entered as 1.5. The sums shown beneath the time
records are read from the API; no time calculations are done in
Micronomy.
To directly switch to a specific week you can add ?date=YYYY-MM-DD
in the browsers address field. Note that weeks on month borders will
be divided into A and B as in Maconomy.
Adding or removing the projects shown currently has to be done in Maconomy. Note though, that you can specify in Maconomy that the same records should be shown on consecutive weeks too.
Hitting enter while entering times is equivalent to pressing the
"Spara" button; ie. it saves the entered times into the database. To
switch to next or previous week you can press the appropriate buttons
or Ctrl-Right or Ctrl-Left respectively. The arrow keys can be
used to navigate between the time fields. Hitting Escape will
unfocus any time field and Ctrl-Down will re-focus the same field.
When a week is completely filled in, it should be submitted by pressing the "Avlämna" button. As in Maconomy, there's nothing stopping you from re-submitting an already submitted week but if you change an already billed week, the changes will probably be ignored by the billing system. So don't do that without consulting with you manager first.
For scripting or terminal-only use there's also a CLI client in
cli/ that talks to the Maconomy iAccess API directly (it
does not go through the Micronomy web service). See
cli/README.md for build instructions and usage, but
in short:
micronomy login
micronomy get
micronomy set --row 0 --day 1 --hours 8.5
micronomy submit
If you find any bugs or even want to fix one you can go to https://github.com/krakan/micronomy/issues/. If the bug you've found isn't there already, please report a new issue. To contribute code you'll have to fork the code to you own Github account and commit your code there and then make a pull request against the main repository.
You're also welcome to add some of the missing features already reported as issues. Follow the same procedure as for bugs.
Start with eg. a basic Debian and then run the following:
sudo apt update
sudo apt install -y libssl-dev git perl curl rsync certbot nginx tmux
curl https://rakubrew.org/install-on-perl.sh | bash
eval "$($HOME/.rakubrew/bin/rakubrew init Bash)"
rakubrew download
rakubrew build zef
zef install --serial Cro::WebApp URI::Encode Digest::MD5 MIME::Base64
Basing this on Debian is of course optional - any platform that can
run rakudo should work but then the above installation commands will
be different.
After the server is set up, clone this repo to it and run
export MICRONOMY_PORT=443
export MICRONOMY_HOST=0.0.0.0
raku -I lib service.raku
There is also a script micronomy.sh that handles Let's Encrypt renewal
and forwards the service's log output to syslog (tagged micronomy, so
eg. grep micronomy: /var/log/syslog). You'll most likely need to
customize it before using it.
To split that output into its own log file instead of leaving it mixed into the general syslog, install the provided rsyslog and logrotate config on the server:
sudo cp resources/rsyslog-micronomy.conf /etc/rsyslog.d/10-micronomy.conf
sudo cp resources/logrotate-micronomy /etc/logrotate.d/micronomy
sudo systemctl restart rsyslog
This routes messages tagged micronomy to /var/log/micronomy.log
(and stops them from also going to the general syslog), with weekly
rotation keeping 8 compressed generations.
Unfortunately, there seems to be some problem with SSL that under some
circumstances makes HTTPS connections hang indefinitely. In that case
one can use the resources/nginx.conf file to let Nginx handle the SSL
termination and then run Micronomy on an unprivileged port - eg.:
sudo sed -Ei "s:^( *ssl_certificate) .*:\1 $MICRONOMY_TLS_CERT;:" resources/nginx.conf
sudo sed -Ei "s:^( *ssl_certificate_key) .*:\1 $MICRONOMY_TLS_KEY;:" resources/nginx.conf
sudo cp resources/nginx.conf /etc/nginx/sites-enabled/default
sudo systemctl restart nginx
./micronomy.sh --port 8080
If the Maconomy tenant has an OpenID Connect provider configured -
B3's has Azure AD (Entra ID) - the login page offers a "Logga in med
Microsoft" button alongside the password form. Micronomy asks Maconomy
what it supports on every login page (cached for an hour) and only
shows the button when the x-oidc-code scheme is actually advertised,
so a tenant without SSO, or one where it is temporarily unavailable,
simply gets the password form. The demo/demo account is unaffected.
Micronomy never handles a client secret and never talks to the identity
provider's token endpoint. It redirects the browser to the provider,
receives an authorization code back, and hands that code to Maconomy,
which performs the exchange itself and returns the same
Maconomy-Reconnect token a password login would have produced. In
outline:
- anonymous
GET maconomy-api/auth/b3withAccept: application/vnd.deltek.maconomy.authentication+jsonreturns the available schemes andopenIDProviders[0].links.authorization-url.template {redirect-uri}in that template is replaced with Micronomy's own callback URL, and the browser is sent there with a randomstate- the provider redirects back to the callback with
?code=...&state=...; the state has to match theoidcStatecookie set in step 2 GET maconomy-api/auth/b3withAuthorization: X-OIDC-Code <base64("<redirect-uri>:code")>- note the angle brackets, which is how Maconomy finds the separator in a string that contains colons of its own - returns the session token
The callback URL must match a redirect URI registered with the identity
provider byte for byte. Micronomy derives it from the request Host
(assuming https unless X-Forwarded-Proto says otherwise, since Nginx
terminates TLS), which works for a plain deployment, but set it
explicitly when anything in front of the service makes that guess wrong:
export MICRONOMY_CALLBACK_URL=https://micronomy.init.se/login/oidc/callback
That same URL has to be added to the app registration's allowed redirect URIs on the provider side, and Maconomy has to be able to map the verified identity to a Maconomy employee, or the exchange in step 4 will fail. Both are administrative tasks outside this repository.
The session cookie set by an SSO login is SameSite=Lax rather than the
password login's Strict: the browser arrives at the callback from the
provider, across sites, and a Strict cookie would be withheld from the
redirect that follows. Lax still keeps the cookie off every cross-site
POST, and every state change in Micronomy is a POST.
The notes from working the protocol out - including what the web client's
own JavaScript does, and the open questions for B3 IT - are in git
history: git show 845ef9c:sso-oidc-investigation.md and
git show 845ef9c:sso-oidc-todo.md.
Sample systemd unit files are provided to run Micronomy unattended:
micronomy.servicerunsmicronomy.sh --port 8080and restarts it automatically.memfree.servicerunsmemfree.sh, which monitors free memory and forces garbage collection (or killsrakuoutright) if it drops too low; this works around a memory leak in long-running Raku processes.wait-for-restart.servicerunsmicronomy.sh wait-for-restart, a small helper that lets Nginx return a friendly "please wait" response while the main process is restarting instead of a connection error.
Copy the ones you need to /etc/systemd/system/, adjust the paths and
User to match your setup, then enable them with eg.
sudo systemctl enable --now micronomy.service.