Ukelonn: en webapplikasjon for ukelønn
Tanken er at ungene skal kunne registrere jobber de gjør i hjemmet og at foreldrene kan registrere utbetalinger av ukelønn og andre måter lønna blir betalt på (f.eks. utlegg/lån og ekstra datapakker til mobil).
Webapplikasjonen er skrevet for å bli kjørt i en OSGi runtime, og er ment å være responsive slik at den er lett å kjøre på mobiltelefoner og nettbrett.
Status
file:https://travis-ci.org/steinarb/ukelonn.svg?branch=master file:https://coveralls.io/repos/steinarb/ukelonn/badge.svg
SonarCloud
file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=lines#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=bugs#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=new_bugs#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=vulnerabilities#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=new_vulnerabilities#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=code_smells#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=new_code_smells#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=coverage#.svg file:https://sonarcloud.io/api/badges/measure?key=no.priv.bang.ukelonn%3Aparent&metric=new_coverage#.svg
Lisens
Lisensen er Apache Public License v 2.0 fordi denne er kompatibel med Affero GPL v 3.0.
Se fila LICENSE for teksten på lisensen.
Hva ligger på de forskjellige branchene
I øyeblikket er det fire hoved-brancher:
- master
Dette er branchen som er i produksjon. Hver push av denne branchen forårsaker [[https://travis-ci.org/steinarb/ukelonn][et bygg på travis-ci]] (dette er den eneste branchen med en [[https://github.com/steinarb/ukelonn/blob/master/.travis.yml][.travis.yml]]-fil) med snapshot deploy til et eget maven-repository, som er [[Oppsett av webappen på en server med debian GNU/linux][det som brukes til å installere applikasjonen i karaf-instansen på produksjonsserveren]]. Det som ligger på master er i øyeblikket en litt eldre versjon av using-vaadin.
- using-vaadin
Denne branchen bruker [[https://vaadin.com/home][vaadin]] og er den mest komplette.
Her brukes Vaadins [[https://vaadin.com/docs/-/part/touchkit/mobile-components.html][Mobile User Interface Components]] for å få noe som ser "app-aktig" ut, iallefall på registrering av jobber, gjort av ungene.
Admin-grensesnittet er også blitt mer mobilt men vil trives bedre på en tablet enn på en mobil (det er mer som skal vises fram).
Denne branchen er i skrivende stund "i produksjon" i heimen (i den litt eldre versjonen som ligger på master).
Denne branchen bruker [[http://ops4j.github.io/pax/web/SNAPSHOT/User-Guide.html#whiteboard-extender][Pax web whiteboard extender]] der servlet'er og filtre blir publisert som OSGi-servicer som blir plukket opp av pax web. For å lage servicene som plukkes opp av Pax Web, brukes OSGi Declarative Services (DS).
- using-primefaces
Denne branchen bruker [[https://en.wikipedia.org/wiki/JavaServer_Faces][JSF]] med [[http://www.primefaces.org/][primefaces]] og var den første som var ferdig.
Jeg støtte på [[https://github.com/primefaces/primefaces/issues/1864][en bug]] i primefaces mobile som gjorde at versjonen som kjører nå ikke er så pen (siden jeg ikke kunne bruke primefaces mobile så måtte jeg gjøre et triks med å blåse opp fontene for at ting ikke skulle være uleselig på mobil, så sluttresultatet så litt rart ut). Branchen bygger fortsatt og har fått alle databasendringene men har mest historisk interesse idag
- using-rendersnake
Denne branchen er ment å være "back to basic" og bruke [[http://rendersnake.org/][rendersnake]] sammen med en REST-ful backend, men den er i skrivende stund ikke forbi "hello world"-stadiet. Når det blir jobb på denne så blir det nok ikke rendersnake. Det blir nok antagelig et eller annet JS-rammeverk på frontend og REST-tjenster på backend
Jeg har også plan om å lage en branch med en versjon som bruker spark med angular.js istedenfor primefaces, men denne er foreløpig på plan-stadiet. Spark er allerede en OSGi-bundle, så det burde la seg gjøre å få den til å spille i Karaf på en sånn måte at jeg kan beholde database-laget (der all business-intelligensen er), mens jeg fjerner alt som har med servlets å gjøre. Har gjort et forsøk på å dra spark inn i karaf men har ikke lykkes ennå. Forhåpentligvis kan jeg også beholde Shiro for å håndtere autentisering og autorisasjon.
Utsjekk og kjapp test av programvaren
Dette trengs for å laste og teste ut denne programvaren
- Installer det som trengs:
- På debian/ubuntu/mint/etc., logg inn som root og gi følgende kommandoer for å installere alle avhengighetene:
#+BEGIN_EXAMPLE
apt-get update
apt-get install git maven openjdk-8-jdk
#+END_EXAMPLE
- git: https://git-scm.com/download/win
- Java SDK 1.8:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
- Apache maven:
- Download: https://maven.apache.org/download.cgi
- Install: https://maven.apache.org/install.html
- Run: https://maven.apache.org/run.html
- Gjør en klon av git-arkivene som trengs for å bygge applikasjonen (kommandoer for bash (funker også i git bash på windows)):
#+BEGIN_EXAMPLE
mkdir -p ~/git
cd ~/git
git clone https://github.com/sbang/jsr330activator.git
git clone https://github.com/steinarb/ukelonn.git
#+END_EXAMPLE
- Åpne et kommandolinje-vindu og skriv følgende kommandoer for å bygge koden (fortsatt kommandoer for bash:
#+BEGIN_EXAMPLE
cd ~/git/jsr330activator
mvn clean install
cd ../ukelonn
git checkout using-vaadin
mvn clean install
cd karaf
mvn clean install karaf:run
#+END_EXAMPLE
- Koble en nettleser mot http://localhost:8181/ukelonn/
- For en vanlig bruker, brukernavn/passord: jad/1ad
- Vanlig bruker kan registrere nye jobber og sjekke saldo
- For en administrator-bruker, brukernavn/passord: admin/admin
- Administrator-bruker kan registrere utbetalinger, legge inn nye jobbtyper og endre eksisterende, legge inn nye utbetalinger og justere på eksisterende, og legge inn brukere og endre på eksisterende brukere
- Når man er ferdig med å teste så kan webappen stoppes med Ctrl-C
NB! Databasen som brukes av "mvn karaf:run" er en ordentlig SQL-database med ekte data. Men databasen kjører kun i minnet, så ingen endringer blir persistert når prosesssen stoppes.
Beskrivelse av koden
(Beskriver versjonen fra using-vaadin)
Prosjektet er et maven-prosjekt med følgende struktur:
pom.xml
Dette er topp-prosjektet som definerer alle versjoner av programvare som brukes og alle versjoner av avhengigheter og felles-oppsett for plugins.
ukelonn.api/pom.xml
Dette er en OSGi-bundle som definerer to OSGi-servicer: UkelonnService og UkelonnDatabase
ukelonn.bundle/pom.xml
Dette er selve webapplikasjonen. Siden dette er en Vaadin-applikasjon som bruker servlet API, så er dette en WAR og ikke en JAR, men det er også en OSGi-bundle som krever en UkelonnDatabase service og som eksponerer en UkelonnService service
ukelonn.bundle.db.liquibase/pom.xml
Denne bundle'n inneholder skjemaet for ukelonn-webappen som et liquibase changeset som ressurser og kode som laster ressursen fra lokal classpath og kjører dem mot databasen
ukelonn.bundle.db.test/pom.xml
Dette er en ikke-persistent SQL-database i minnet som setter opp forventet skjema og fyller opp databasen med test-data (dataene fylles opp som liquibase changesets så det er ok å starte denne basen mange ganger uten at det blir duplikat i dataene)
Dette er en fullt funksjonell database, men ingenting blir persistert mellom kjøringer. Den brukes til test både av webappen i gogoshell og brukes som en vanlig jar-fil i enhetstestene i ukelonn.bundle
ukelonn.bundle.db.postgresql/pom.xml
Dette er en OSGi-bundle som forventer å finne en PostgreSQL-base som brukeren som kjører webappen har rettigheter til og som har en database "ukelonn".
Databasen "ukelonn" vil få riktig skjema og en admin-bruker ved første gangs kjøring.
ukelonn.tests/pom.xml
Dette er en Pax Exam integrasjonstest som sjekker at OSGi-bundlene starter og at de tilbyr riktig service.
ukelonn.gogoshell/pom.xml
Dette er en POM for å starte webappen kjørende i gogoshell. Dvs. en fullt funksjonell OSGi-kontainer som blir startet på nytt hver gang maven starter den
karaf/pom.xml
Dette er en POM som lager en "feature"-fil for [[http://karaf.apache.org/][Apache karaf]]
ukelonn.rebundled/pom.xml
Hver gang man trenger en avhengighet som ikke er en OSGi-bundle kan man "rebundle" avhengigheten ved å lage et nytt underprosjekt av dette prosjektet.
Apache Karaf har muligheter til å auto-bundle jar-filer ved lasting, men integrasjonstestene i ukelonn.tests og gogoshell-kjøring av prosjektet trenger begge avhengigheter som OSGi-bundler.
Vaadin TouchKit og noen av avhengighetene til TouchKit var /ikke/ bundler og måtte rebundles. Men selve Vaadin og avhengighetene var allerede bundlet.
Kjøring på apache karaf med derby
For å teste og debugge, så kan man kjøre med samme database som enhetstestene og integrasjonstestene bruker. Derby-databasen kjører i minnet og blir satt opp med faste data ved hjelp av liquibase, hver gang den blir startet.
Dette trengs for å bygge og kjøre programvaren
- Installer det som trengs:
- git: https://git-scm.com/download/win
- Java SDK 1.8: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
- Apache maven:
- Download: https://maven.apache.org/download.cgi
- Install: https://maven.apache.org/install.html
- Run: https://maven.apache.org/run.html
- Gjør en klon av git-repositoriet
#+BEGIN_EXAMPLE
mkdir %HOME%\git
cd %HOME%\git
git clone https://github.com/steinarb/ukelonn.git
#+END_EXAMPLE
- Åpne et kommandolinje-vindu og skriv følgende kommandoer:
#+BEGIN_EXAMPLE
cd %HOME%\git\ukelonn
mvn clean install
#+END_EXAMPLE
- [http://karaf.apache.org/download.html][Last ned Karaf 4.1.2]], pakk ut den nedlastede distribusjonen og start karaf fra kommandlinja
- Gjør ukelonn-webapplikasjonen tilgjengelig for karaf, som "karaf features", hentet fra maven:
#+BEGIN_EXAMPLE
feature:repo-add mvn:no.priv.bang.ukelonn/karaf/LATEST/xml/features
#+END_EXAMPLE
- Installer webapplikasjonen:
#+BEGIN_EXAMPLE
feature:install ukelonn-db-derby-test
feature:install ukelonn
#+END_EXAMPLE
- Koble en nettleser mot http://localhost:8181/ukelonn/
- For en vanlig bruker, brukernavn/passord: jad/1ad
- Vanlig bruker kan registrere nye jobber og sjekke saldo
- For en administrator-bruker, brukernavn/passord: on/ola12
- Administrator-bruker kan registrere utbetalinger, legge inn nye jobbtyper og endre eksisterende, legge inn nye utbetalinger og justere på eksisterende, og legge inn brukere og endre på eksisterende brukere
Kjøring på apache karaf med PostgreSQL
Derbydatabasen i Kjøring på apache karaf med derby gjør det mulig å kjøre alt i webappen. Men ettersom den kun kjører i minnet så er den ikke noe særlig å lagre data i.
For å faktisk bruke webappen så må man ha en database og database-systemet jeg har valgt er PostgreSQL.
PostgreSQL er gratis og fri software og er lett å installere
- På windows, last ned installeren og kjør den
- På debian GNU/linux, gi følgende kommando som root:
#+BEGIN_EXAMPLE
apt-get install postgresql
#+END_EXAMPLE
Å finne ut av hvordan det gjøres på andre system overlates til leseren... men det er neppe hverken veldig forskjellig fra eksemplene over, eller mer enn et googlesøk unna.
Litt om PostgreSQL, denne webappen og sikkerhet
OSGi-servicen som implementerer kobling mot PostgreSQL hardkoder en kobling mot localhost på default-porten til PostgreSQL (dvs. port 5432) og har ikke noe brukernavn eller passord lagret i seg.
Dette betyr:
- PostgreSQL-serveren må kjøre på samme datamaskin som webappen kjøres på (jeg kjører selv alt på en enkelt "Virtual Private Server" (VPS) hos Bytemark så dette er ikke restriksjon som plager meg)
- Det må være en PostgreSQL-bruker med samme navn som brukernavnet som webappen kjøres som, dvs. når jeg kjører karaf som min egen bruker "sb", så må jeg ha en postgresql-bruker "sb":
#+BEGIN_EXAMPLE
/bin/sudo -s /bin/bash postgres createuser sb
#+END_EXAMPLE
og når jeg kjører karaf som brukeren "karaf" (dvs. når jeg kjører karaf som en service installert med apt-get på debian GNU/linux), så må jeg ha en postgresql-bruker "karaf":
#+BEGIN_EXAMPLE
/bin/sudo -s /bin/bash postgres createuser karaf
#+END_EXAMPLE
- PostgreSQL-serveren må ha en database som heter "ukelonn" og som er eid av brukeren karaf kjøres som, lagd f.eks. slik:
#+BEGIN_EXAMPLE
/bin/sudo -s /bin/bash postgres createdb -O sb ukelonn
#+END_EXAMPLE
- Autentisering av oppkoblingen må gjøres på en måte som ikke trenger et passord lagret i OSGi-servicen, dvs. en av disse:
- [https://www.postgresql.org/docs/9.6/static/auth-methods.html#AUTH-TRUST][Trust authentication]] dvs. PostgreSQL stoler på at klienten er brukeren som den sier at den er. Ikke veldig sikkert, men greit nok for å teste mot PostgreSQL under utvikling
- [https://www.postgresql.org/docs/9.6/static/auth-methods.html#AUTH-IDENT][Ident authentication]] stol på at svaret på port 113 ("ident", RFC 1413) om hvilken bruker som har åpnet en forbindelse på en gitt port. Dette er måten jeg bruker på GNU/linux og er rimelig grei, så lenge jeg kjører alt på en og samme server
- [https://www.postgresql.org/docs/9.6/static/auth-methods.html#AUTH-PEER][Peer authentication]] Spør OSet om brukeren til prosessen som kobler seg til (fungerer kun for lokale forbindelser som f.eks. unix sockets, og unix sockets støttes ikke av PostgreSQL JDBC-driver)
- [https://www.postgresql.org/docs/9.6/static/auth-methods.html#GSSAPI-AUTH][GSSAPI Authentication]] bruker kerberos og er notorisk vanskelig å sette opp og få til å fungere (men veldig fint når det er på plass)
Oppsettet videre antar "trust authentication" for kjøring mot PostgreSQL under utvikling og "ident authentication" for kjøring på en debian-server.
Kjøring av webappen mot postgres lokalt på utviklingsmaskinen
Dette krever at man har en lokal PostgreSQL-installasjon med følgende innstillinger:
- En database med navn "ukelonn" der brukeren karaf kjører med har alle rettigheter (i eksempelet under er dette min egen bruker "sb"):
#+BEGIN_EXAMPLE
/usr/bin/sudo -u postgres createuser sb
/usr/bin/sudo -u postgres createdb -O sb ukelonn
#+END_EXAMPLE
(kommandoeksempler fra debian, kommandoer kjørt som root)
- [https://www.postgresql.org/docs/9.6/static/auth-methods.html#AUTH-TRUST][Sett opp autentiseringsmetode trust i PostgreSQL]]
Oppsett av webappen på en server med debian GNU/linux
Framgangsmåte:
- Klon og bygg webapplikasjonen (kommandoeksemplene er fra bash på GNU/linux):
#+BEGIN_EXAMPLE
mkdir -p ~/git
cd ~/git
git clone https://github.com/sbang/jsr330activator.git
git clone https://github.com/steinarb/ukelonn.git
cd ~/git/jsr330activator
mvn clean install
cd ~/git/ukelonn
mvn clean install
#+END_EXAMPLE
- [http://karaf.apache.org/download.html][Last ned Karaf 4.1.2]], pakk ut den nedlastede distribusjonen og start karaf fra kommandlinja (karaf vil da kjøre som din egen bruker som stemmer med PostgreSQL-oppsettet i starten av dette avsnittet):
#+BEGIN_EXAMPLE
cd /tmp
wget http://www.apache.org/dyn/closer.lua/karaf/4.1.2/apache-karaf-4.1.2.tar.gz
cd ~
tar xvfz /tmp/apache-karaf-4.1.2.tar.gz
cd apache-karaf-4.1.2
bin/karaf
#+END_EXAMPLE
- Gjør ukelonn-webapplikasjonen tilgjengelig for karaf, som "karaf features", hentet fra maven:
#+BEGIN_EXAMPLE
feature:repo-add mvn:no.priv.bang.ukelonn/karaf/LATEST/xml/features
#+END_EXAMPLE
- Installer webapplikasjonen:
#+BEGIN_EXAMPLE
feature:install ukelonn-db-postgresql
feature:install ukelonn
#+END_EXAMPLE
- Koble en nettleser mot http://localhost:8181/ukelonn/
- Admin-bruker, brukernavn/passord: admin/admin
- Denne brukeren blir satt opp når man først kobler seg opp mot en tom PostgreSQL-database: Da sørger liquibase for at skjemaet (tabeller og views) blir satt opp og for at en admin-bruker og noen transaksjonstyper blir lagt inn
- Administrator-bruker kan registrere utbetalinger, legge inn nye jobbtyper og endre eksisterende, legge inn nye utbetalinger og justere på eksisterende, og legge inn brukere og endre på eksisterende brukere
- En grei måte å starte på, er:
- Endre passord på admin-brukeren
- Lage en ny vanlig bruker
NB! Har ikke med oppsett av brannmur og oppsett av nginx eller apache med revers-proxy.
(Normalt så vil port 8181 som webappen opererer på være sperret av brannmur på en webserver som står på internett, så man må sette opp en revers-proxy fra nginx eller apache (som lytter på portene 80 og 443) til karaf som lytter på localhost:8181)
Prosedyre (alle kommandolinje-eksempler gjort i bash, logget inn som root):
- Legg til nøkkel for apt-repo'et som inneholder karaf
#+BEGIN_EXAMPLE
wget -O - https://apt.bang.priv.no/apt_pub.gpg | apt-key add -
#+END_EXAMPLE
- Legg til følgende linjer i /etc/apt/sources.list :
#+BEGIN_EXAMPLE
# APT archive for apache karaf
deb http://apt.bang.priv.no/public stable main
#+END_EXAMPLE
- Installer nødvendig software:
#+BEGIN_EXAMPLE
apt-get update
apt-get install openjdk-8-jdk postgresql karaf
#+END_EXAMPLE
- Sett opp bruker og database i PostgreSQL:
#+BEGIN_EXAMPLE
/usr/bin/sudo -u postgres createuser karaf
/usr/bin/sudo -u postgres createdb -O karaf ukelonn
#+END_EXAMPLE
(kommandoen blir her kjørt som bruker postgres som ikke kan logges inn til (derfor "-s /bin/bash"), men har de riktige rettighetene til å sette opp ting i postgres)
- Ta ssh inn til karaf:
#+BEGIN_EXAMPLE
ssh -p 8101 karaf@localhost
#+END_EXAMPLE
(passord "karaf" (uten anførselstegn))
- I karaf kommando-skall, legg til maven-repo som holder snapshots av ukelonn, bygd fra travis CI-bygg av det som blir pushet til master:
#+BEGIN_EXAMPLE
config:edit org.ops4j.pax.url.mvn
config:property-append org.ops4j.pax.url.mvn.repositories ", https://maven.bang.priv.no/repository/@id=ukelonn@snapshots, http://maven.vaadin.com/vaadin-addons@id=vaadin"
config:property-set org.ops4j.pax.url.mvn.globalUpdatePolicy always
config:update
#+END_EXAMPLE
- I karaf kommando-skall, gi følgende kommandoer:
#+BEGIN_EXAMPLE
feature:repo-add mvn:no.priv.bang.ukelonn/karaf/LATEST/xml/features
feature:install ukelonn-db-postgresql
feature:install ukelonn
#+END_EXAMPLE
Nå kjører webappen mot http://localhost:8181/ukelonn/ og databasen har blitt satt opp med admin-bruker, med brukernavn/passord: admin/admin.
Det kan være lurt å starte med å endre passordet her så fort som mulig.
Det kan også være lurt å sette opp en nattlig backup av denne databasen til en annen maskin.
Merk: Nye snapshots blir bygd og deployet til dette maven-repoet hver gang noe blir pushet til master på github.
For å oppdatere til nyeste snapshot, ta "ssh -p 8101 karaf@localhost" og gi følgende kommandoer:
bundle:update no.priv.bang.ukelonn.api; bundle:update no.priv.bang.ukelonn.db.liquibase; bundle:update no.priv.bang.ukelonn.db.postgresql; bundle:update no.priv.bang.ukelonn
(Merk: Man kan ikke bruke "bundle:watch *" etter å ha installert -snapshot-versjoner fra et maven-repository man når med http, fordi "hundle:watch *" fungerer kun for automatisk oppdatering av snapshot-versjoner installert i det lokale maven-repoet i ~karaf/.m2/repository/ )
Koble webapp mot database på en annen maskin
Uansett hvilken setting man bruker PostgreSQL i (utvikler-oppsett eller oppsett på server), så er det mulig å peke på en PostgreSQL-database som kjører på en annen server.
Framgangsmåte:
- Sørg for at PostgreSQL godtar tilkoblinger fra alle nettverksadresser (ut av boksen på debian, så godtar PostgreSQL kun tilkoblinger fra localhost):
- su til bruker postgres for å få riktig eierskap på filene
#+BEGIN_EXAMPLE
su - postgres
#+END_EXAMPLE
- Endre fila /etc/postgresql/9.6/main/postgresql.conf, utkommenter linja med listen_address line og endre den til den ser sånn ut
#+BEGIN_SRC conf
listen_addresses = '*' # what IP address(es) to listen on;
#+END_SRC
- Endre fila /etc/postgresql/9.6/main/pg_hba.conf, og legg til følgende linjer
#+BEGIN_SRC conf
# IPv4 network connection allow password authentication
host all all 0.0.0.0/0 md5
#+END_SRC
- Logg ut som bruker postgres (bare root kan ta omstart av postgresql):
#+BEGIN_EXAMPLE
exit
#+END_EXAMPLE
- Ta omstart av postgresql
#+BEGIN_EXAMPLE
systemctl restart postgresql
#+END_EXAMPLE
- Fra karaf-konsollet, gi følgende kommandoer:
#+BEGIN_EXAMPLE
config:edit no.priv.bang.ukelonn.bundle.db.postgresql.PGUkelonnDatabaseProvider
config:property-set ukelonn.db.jdbc.url "jdbc:postgresql://lorenzo.hjemme.lan/ukelonn
config:property-set ukelonn.db.jdbc.user "karaf"
config:property-set ukelonn.db.jdbc.password "karaf"
config:update
#+END_EXAMPLE