[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated (1fe2687a -> a105222b)
From: |
gnunet |
Subject: |
[libeufin] branch master updated (1fe2687a -> a105222b) |
Date: |
Tue, 13 Jun 2023 14:57:27 +0200 |
This is an automated email from the git hooks/post-receive script.
ms pushed a change to branch master
in repository libeufin.
from 1fe2687a Creating missing Sandbox table.
new 22a2824f DB migration building blocks.
new a105222b indentation
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
Makefile | 15 +-
contrib/indent-sql-sh | 39 +++
contrib/libeufin-load-sql | 91 +++++++
database-versioning/nexus-0001.sql | 241 +++++++++++++++++
database-versioning/sandbox-0001.sql | 250 ++++++++++++++++++
database-versioning/versioning.sql | 293 +++++++++++++++++++++
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 4 +-
util/src/main/kotlin/DB.kt | 12 +
.../Errors.kt => util/src/main/kotlin/exec.kt | 34 ++-
9 files changed, 953 insertions(+), 26 deletions(-)
create mode 100755 contrib/indent-sql-sh
create mode 100755 contrib/libeufin-load-sql
create mode 100644 database-versioning/nexus-0001.sql
create mode 100644 database-versioning/sandbox-0001.sql
create mode 100644 database-versioning/versioning.sql
copy nexus/src/main/kotlin/tech/libeufin/nexus/Errors.kt =>
util/src/main/kotlin/exec.kt (58%)
diff --git a/Makefile b/Makefile
index 6fdbfaff..1d96dac8 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ include build-system/config.mk
escaped_pwd = $(shell pwd | sed 's/\//\\\//g')
all: assemble
-install: install-nexus install-sandbox install-cli
+install: install-nexus install-sandbox install-cli install-db-versioning
git-archive-all =
./build-system/taler-build-scripts/archive-with-submodules/git_archive_all.py
git_tag=$(shell git describe --tags)
gradle_version=$(shell ./gradlew -q libeufinVersion)
@@ -35,7 +35,6 @@ get-spa:
deb: exec-arch copy-spa
@dpkg-buildpackage -rfakeroot -b -uc -us
-
.PHONY: install-sandbox
install-sandbox:
@./gradlew -q -Pprefix=$(prefix) sandbox:installToPrefix; cd ..
@@ -49,6 +48,13 @@ install-cli:
@./gradlew -q replaceVersionCli
@install -D cli/bin/libeufin-cli $(prefix)/bin
+.PHONY: install-db-versioning
+install-db-versioning:
+ $(eval LOAD_SQL_SCRIPT_NAME := libeufin-load-sql)
+ @sed "s|__STATIC_PATCHES_LOCATION__|$(prefix)/share/libeufin/sql|" <
contrib/$(LOAD_SQL_SCRIPT_NAME) > build/$(LOAD_SQL_SCRIPT_NAME)
+ @install -D database-versioning/*.sql -t $(prefix)/share/libeufin/sql
+ @install -D build/$(LOAD_SQL_SCRIPT_NAME) -t $(prefix)/bin
+
.PHONY: assemble
assemble:
@./gradlew assemble
@@ -61,8 +67,3 @@ check:
check-cli:
@cd ./cli/tests && ./circuit_test.sh
@cd ./cli/tests && ./debit_test.sh
-
-
-# .PHONY: parse
-# parse:
-# @cd parsing-tests; py.test -s checks.py
diff --git a/contrib/indent-sql-sh b/contrib/indent-sql-sh
new file mode 100755
index 00000000..d702859d
--- /dev/null
+++ b/contrib/indent-sql-sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+set -eu
+
+# This script indents the output of Exposed SQL logger.
+
+# Usage: ./indent.sh filename
+
+# Remove leading "^SQL: " that Exposed uses.
+crop_leading_sql () {
+ sed 's/^SQL: //'
+}
+
+# Inserts new line & two spaces before the first "("
+# and last ")", and before each comma. Only triggers on
+# "CREATE TABLE"-lines.
+indent_create_table () {
+ sed '/^CREATE/s/, /,/g' \
+ | sed '/^CREATE/s/\(,\|)$\)/\n \1/g' \
+ | sed '/^CREATE/s/(/\n (/'
+}
+
+
+# Inserts new line & two spaces before each "ALTER TABLE"
+# statement
+indent_alter_table () {
+ sed 's/^ALTER TABLE \(.*\)/ALTER TABLE\n \1/'
+}
+
+# Inserts a blank line after between each CREATE/ALTER TABLE statement.
+blank_line_after_statement () {
+ sed '/^CREATE TABLE/s/\(.*\)/\n\1/' \
+ | sed '/^ALTER TABLE/s/\(.*\)/\n\1/'
+}
+
+crop_leading_sql < $1 \
+ | indent_create_table \
+ | indent_alter_table \
+ | blank_line_after_statement
diff --git a/contrib/libeufin-load-sql b/contrib/libeufin-load-sql
new file mode 100755
index 00000000..eaf3e534
--- /dev/null
+++ b/contrib/libeufin-load-sql
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+set -eu
+
+# The only CLI argument is 'nexus' or 'sandbox',
+# indicating which service will get its database prepared.
+
+fail () {
+ echo $1
+ exit 1
+}
+
+run_sql_file () {
+ # -q doesn't hide all the output, hence the
+ # redirection to /dev/null.
+ psql -d $DB_CONNECTION \
+ -q \
+ -f $1 \
+ --set ON_ERROR_STOP=1 > /dev/null
+}
+
+# The real check happens (by the caller)
+# by checking the returned text.
+check_patch_applied () {
+ psql -d $DB_CONNECTION \
+ -t \
+ -c "SELECT applied_by FROM _v.patches WHERE patch_name = '$1' LIMIT 1"
+}
+
+# Iterates over the .sql migration files and applies
+# the new ones.
+iterate_over_patches () {
+ if test "$1" != sandbox -a "$1" != nexus; then
+ fail "iterate_over_patches: only 'sandbox' and 'nexus' are acceptable
arguments."
+ fi
+ component="$1"
+ cd $PATCHES_LOCATION
+ for patch_filename in $(ls -1 -v $component-[0-9][0-9][0-9][0-9].sql); do
+ patch_name=$(echo $patch_filename | cut -f1 -d.)
+ echo Checking patch: "$patch_name"
+ maybe_applied=$(check_patch_applied "$patch_name")
+ if test -n "$maybe_applied"; then continue; fi
+ # patch not applied, apply it.
+ echo Patch $patch_name not applied, applying it.
+ run_sql_file $patch_filename
+ done
+ cd - > /dev/null # cd to previous location.
+}
+while getopts ":d:l:h" OPTION; do
+ case "$OPTION" in
+ d)
+ DB_CONNECTION="$OPTARG"
+ ;;
+ l)
+ PATCHES_LOCATION="$OPTARG"
+ ;;
+ s)
+ SERVICE="${OPTARG:-}"
+ ;;
+ h)
+ echo Usage: libeufin-load-sql OPTIONS
+ echo
+ echo 'Supported options:'
+ echo " -s SERVICE -- specify 'sandbox' or 'nexus', according to which
set of tables are to be setup. If missing both sets will be setup on the same
database."
+ echo ' -d DB_CONN -- required. Pass DB_CONN as the postgres
connection string. Passed verbatim to Psql'
+ echo ' -l LOC -- required. Pass LOC as the SQL files location.
Typically $prefix/share/libeufin/sql'
+ echo ' -h -- print this help'
+ exit 0
+ ;;
+ ?)
+ fail 'Unrecognized command line option'
+ ;;
+ esac
+done
+
+# Checking required options.
+if test -z "${PATCHES_LOCATION:-}"; then
+ # This value is substituted by GNU make at installation time.
+ PATCHES_LOCATION=__STATIC_PATCHES_LOCATION__
+fi
+if test -z "${DB_CONNECTION:-}"; then
+ fail "Required option '-d' was missing."
+fi
+
+run_sql_file "$PATCHES_LOCATION/versioning.sql"
+if test -z "${SERVICE:-}"; then # both table sets.
+ iterate_over_patches sandbox
+ iterate_over_patches nexus
+ exit 0
+fi
+iterate_over_patches $SERVICE # helper checks the argument sanity.
diff --git a/database-versioning/nexus-0001.sql
b/database-versioning/nexus-0001.sql
new file mode 100644
index 00000000..c18a909f
--- /dev/null
+++ b/database-versioning/nexus-0001.sql
@@ -0,0 +1,241 @@
+-- Compatible with LibEuFin version: 1fe2687aaf696c8566367fe7ed082f1d78e6b78d
+
+BEGIN;
+
+SELECT _v.register_patch('nexus-0001', NULL, NULL);
+
+CREATE TABLE IF NOT EXISTS nexususers
+ (id BIGSERIAL PRIMARY KEY
+ ,username TEXT NOT NULL
+ ,"password" TEXT NOT NULL
+ ,superuser BOOLEAN NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS nexusbankconnections
+ (id BIGSERIAL PRIMARY KEY
+ ,"connectionId" TEXT NOT NULL
+ ,"type" TEXT NOT NULL
+ ,dialect TEXT NULL
+ ,"user" BIGINT NOT NULL
+ ,CONSTRAINT fk_nexusbankconnections_user_id FOREIGN KEY ("user") REFERENCES
nexususers(id) ON DELETE RESTRICT ON UPDATE RESTRICT
+ );
+
+CREATE TABLE IF NOT EXISTS xlibeufinbankusers
+ (id BIGSERIAL PRIMARY KEY
+ ,username TEXT NOT NULL
+ ,"password" TEXT NOT NULL
+ ,"baseUrl" TEXT NOT NULL
+ ,"nexusBankConnection" BIGINT NOT NULL
+ ,CONSTRAINT fk_xlibeufinbankusers_nexusbankconnection_id FOREIGN KEY
("nexusBankConnection") REFERENCES nexusbankconnections(id) ON DELETE RESTRICT
ON UPDATE RESTRICT
+ );
+
+CREATE TABLE IF NOT EXISTS nexusscheduledtasks
+ (id BIGSERIAL PRIMARY KEY
+ ,"resourceType" TEXT NOT NULL
+ ,"resourceId" TEXT NOT NULL
+ ,"taskName" TEXT NOT NULL
+ ,"taskType" TEXT NOT NULL
+ ,"taskCronspec" TEXT NOT NULL
+ ,"taskParams" TEXT NOT NULL
+ ,"nextScheduledExecutionSec" BIGINT NULL
+ ,"lastScheduledExecutionSec" BIGINT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS nexusbankaccounts
+ (id BIGSERIAL PRIMARY KEY
+ ,"bankAccountId" TEXT NOT NULL
+ ,"accountHolder" TEXT NOT NULL
+ ,iban TEXT NOT NULL
+ ,"bankCode" TEXT NOT NULL
+ ,"defaultBankConnection" BIGINT NULL
+ ,"lastStatementCreationTimestamp" BIGINT NULL
+ ,"lastReportCreationTimestamp" BIGINT NULL
+ ,"lastNotificationCreationTimestamp" BIGINT NULL
+ ,"highestSeenBankMessageSerialId" BIGINT NOT NULL
+ ,pain001counter BIGINT DEFAULT 1 NOT NULL
+ ,CONSTRAINT fk_nexusbankaccounts_defaultbankconnection_id FOREIGN KEY
("defaultBankConnection") REFERENCES nexusbankconnections(id) ON DELETE
RESTRICT ON UPDATE RESTRICT
+ );
+
+ALTER TABLE
+ nexusbankaccounts ADD CONSTRAINT nexusbankaccounts_bankaccountid_unique
UNIQUE ("bankAccountId");
+
+CREATE TABLE IF NOT EXISTS nexusbanktransactions
+ (id BIGSERIAL PRIMARY KEY
+ ,"accountTransactionId" TEXT NOT NULL
+ ,"bankAccount" BIGINT NOT NULL
+ ,"creditDebitIndicator" TEXT NOT NULL
+ ,currency TEXT NOT NULL
+ ,amount TEXT NOT NULL
+ ,status VARCHAR(16) NOT NULL
+ ,"updatedBy" BIGINT NULL
+ ,"transactionJson" TEXT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS paymentinitiations
+ (id BIGSERIAL PRIMARY KEY
+ ,"bankAccount" BIGINT NOT NULL
+ ,"preparationDate" BIGINT NOT NULL
+ ,"submissionDate" BIGINT NULL
+ ,"sum" TEXT NOT NULL
+ ,currency TEXT NOT NULL
+ ,"endToEndId" TEXT NOT NULL
+ ,"paymentInformationId" TEXT NOT NULL
+ ,"instructionId" TEXT NOT NULL
+ ,subject TEXT NOT NULL
+ ,"creditorIban" TEXT NOT NULL
+ ,"creditorBic" TEXT NULL
+ ,"creditorName" TEXT NOT NULL
+ ,submitted BOOLEAN DEFAULT false NOT NULL
+ ,invalid BOOLEAN NULL
+ ,"messageId" TEXT NOT NULL
+ ,"rawConfirmation" BIGINT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS nexusebicssubscribers
+ (id BIGSERIAL PRIMARY KEY
+ ,"ebicsURL" TEXT NOT NULL
+ ,"hostID" TEXT NOT NULL
+ ,"partnerID" TEXT NOT NULL
+ ,"userID" TEXT NOT NULL
+ ,"systemID" TEXT NULL
+ ,"signaturePrivateKey" bytea NOT NULL
+ ,"encryptionPrivateKey" bytea NOT NULL
+ ,"authenticationPrivateKey" bytea NOT NULL
+ ,"bankEncryptionPublicKey" bytea NULL
+ ,"bankAuthenticationPublicKey" bytea NULL
+ ,"nexusBankConnection" BIGINT NOT NULL
+ ,"ebicsIniState" VARCHAR(16) NOT NULL
+ ,"ebicsHiaState" VARCHAR(16) NOT NULL
+ ,CONSTRAINT fk_nexusebicssubscribers_nexusbankconnection_id FOREIGN KEY
("nexusBankConnection") REFERENCES nexusbankconnections(id) ON DELETE RESTRICT
ON UPDATE RESTRICT
+ );
+
+CREATE TABLE IF NOT EXISTS nexusbankbalances
+ (id BIGSERIAL PRIMARY KEY
+ ,balance TEXT NOT NULL
+ ,"creditDebitIndicator" TEXT NOT NULL
+ ,"bankAccount" BIGINT NOT NULL
+ ,"date" TEXT NOT NULL
+ ,CONSTRAINT fk_nexusbankbalances_bankaccount_id FOREIGN KEY ("bankAccount")
REFERENCES nexusbankaccounts(id) ON DELETE RESTRICT ON UPDATE RESTRICT
+ );
+
+CREATE TABLE IF NOT EXISTS anastasisincomingpayments
+ (id BIGSERIAL PRIMARY KEY
+ ,payment BIGINT NOT NULL
+ ,subject TEXT NOT NULL
+ ,"timestampMs" BIGINT NOT NULL
+ ,"incomingPaytoUri" TEXT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS talerincomingpayments
+ (id BIGSERIAL PRIMARY KEY
+ ,payment BIGINT NOT NULL
+ ,"reservePublicKey" TEXT NOT NULL
+ ,"timestampMs" BIGINT NOT NULL
+ ,"incomingPaytoUri" TEXT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS facades
+ (id BIGSERIAL PRIMARY KEY
+ ,"facadeName" TEXT NOT NULL
+ ,"type" TEXT NOT NULL
+ ,creator BIGINT NOT NULL
+ ,CONSTRAINT fk_facades_creator_id FOREIGN KEY (creator) REFERENCES
nexususers(id) ON DELETE RESTRICT ON UPDATE RESTRICT
+ );
+
+ALTER TABLE
+ facades ADD CONSTRAINT facades_facadename_unique UNIQUE ("facadeName");
+
+CREATE TABLE IF NOT EXISTS talerrequestedpayments
+ (id BIGSERIAL PRIMARY KEY
+ ,facade BIGINT NOT NULL
+ ,payment BIGINT NOT NULL
+ ,"requestUid" TEXT NOT NULL
+ ,amount TEXT NOT NULL
+ ,"exchangeBaseUrl" TEXT NOT NULL
+ ,wtid TEXT NOT NULL
+ ,"creditAccount" TEXT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS facadestate
+ (id BIGSERIAL PRIMARY KEY
+ ,"bankAccount" TEXT NOT NULL
+ ,"bankConnection" TEXT NOT NULL
+ ,currency TEXT NOT NULL
+ ,"reserveTransferLevel" TEXT NOT NULL
+ ,facade BIGINT NOT NULL
+ ,"highestSeenMessageSerialId" BIGINT DEFAULT 0 NOT NULL
+ ,CONSTRAINT fk_facadestate_facade_id FOREIGN KEY (facade) REFERENCES
facades(id) ON DELETE CASCADE ON UPDATE RESTRICT
+ );
+
+CREATE TABLE IF NOT EXISTS talerinvalidincomingpayments
+ (id BIGSERIAL PRIMARY KEY
+ ,payment BIGINT NOT NULL
+ ,"timestampMs" BIGINT NOT NULL
+ ,refunded BOOLEAN DEFAULT false NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS nexusbankmessages
+ (id BIGSERIAL PRIMARY KEY
+ ,"bankConnection" BIGINT NOT NULL
+ ,message bytea NOT NULL
+ ,"messageId" TEXT NULL
+ ,"fetchLevel" VARCHAR(16) NOT NULL
+ ,errors BOOLEAN DEFAULT false NOT NULL
+ ,CONSTRAINT fk_nexusbankmessages_bankconnection_id FOREIGN KEY
("bankConnection") REFERENCES nexusbankconnections(id) ON DELETE RESTRICT ON
UPDATE RESTRICT
+ );
+
+CREATE TABLE IF NOT EXISTS offeredbankaccounts
+ (id BIGSERIAL PRIMARY KEY
+ ,"offeredAccountId" TEXT NOT NULL
+ ,"bankConnection" BIGINT NOT NULL
+ ,iban TEXT NOT NULL
+ ,"bankCode" TEXT NOT NULL
+ ,"holderName" TEXT NOT NULL
+ ,imported BIGINT NULL
+ ,CONSTRAINT fk_offeredbankaccounts_bankconnection_id FOREIGN KEY
("bankConnection") REFERENCES nexusbankconnections(id) ON DELETE RESTRICT ON
UPDATE RESTRICT
+ ,CONSTRAINT fk_offeredbankaccounts_imported_id FOREIGN KEY (imported)
REFERENCES nexusbankaccounts(id) ON DELETE RESTRICT ON UPDATE RESTRICT
+ );
+
+ALTER TABLE
+ offeredbankaccounts ADD CONSTRAINT
offeredbankaccounts_offeredaccountid_bankconnection_unique UNIQUE
("offeredAccountId", "bankConnection");
+
+CREATE TABLE IF NOT EXISTS nexuspermissions
+ (id BIGSERIAL PRIMARY KEY
+ ,"resourceType" TEXT NOT NULL
+ ,"resourceId" TEXT NOT NULL
+ ,"subjectType" TEXT NOT NULL
+ ,"subjectName" TEXT NOT NULL
+ ,"permissionName" TEXT NOT NULL
+ );
+
+ALTER TABLE
+ nexuspermissions ADD CONSTRAINT
nexuspermissions_resourcetype_resourceid_subjecttype_subjectnam UNIQUE
("resourceType", "resourceId", "subjectType", "subjectName", "permissionName");
+
+ALTER TABLE
+ nexusbanktransactions ADD CONSTRAINT fk_nexusbanktransactions_bankaccount_id
FOREIGN KEY ("bankAccount") REFERENCES nexusbankaccounts(id) ON DELETE RESTRICT
ON UPDATE RESTRICT;
+
+ALTER TABLE
+ nexusbanktransactions ADD CONSTRAINT fk_nexusbanktransactions_updatedby_id
FOREIGN KEY ("updatedBy") REFERENCES nexusbanktransactions(id) ON DELETE
RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ paymentinitiations ADD CONSTRAINT fk_paymentinitiations_bankaccount_id
FOREIGN KEY ("bankAccount") REFERENCES nexusbankaccounts(id) ON DELETE RESTRICT
ON UPDATE RESTRICT;
+
+ALTER TABLE
+ paymentinitiations ADD CONSTRAINT fk_paymentinitiations_rawconfirmation_id
FOREIGN KEY ("rawConfirmation") REFERENCES nexusbanktransactions(id) ON DELETE
RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ anastasisincomingpayments ADD CONSTRAINT
fk_anastasisincomingpayments_payment_id FOREIGN KEY (payment) REFERENCES
nexusbanktransactions(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ talerincomingpayments ADD CONSTRAINT fk_talerincomingpayments_payment_id
FOREIGN KEY (payment) REFERENCES nexusbanktransactions(id) ON DELETE RESTRICT
ON UPDATE RESTRICT;
+
+ALTER TABLE
+ talerrequestedpayments ADD CONSTRAINT fk_talerrequestedpayments_facade_id
FOREIGN KEY (facade) REFERENCES facades(id) ON DELETE RESTRICT ON UPDATE
RESTRICT;
+
+ALTER TABLE
+ talerrequestedpayments ADD CONSTRAINT fk_talerrequestedpayments_payment_id
FOREIGN KEY (payment) REFERENCES paymentinitiations(id) ON DELETE RESTRICT ON
UPDATE RESTRICT;
+
+ALTER TABLE
+ talerinvalidincomingpayments ADD CONSTRAINT
fk_talerinvalidincomingpayments_payment_id FOREIGN KEY (payment) REFERENCES
nexusbanktransactions(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+COMMIT
diff --git a/database-versioning/sandbox-0001.sql
b/database-versioning/sandbox-0001.sql
new file mode 100644
index 00000000..b6ed53ef
--- /dev/null
+++ b/database-versioning/sandbox-0001.sql
@@ -0,0 +1,250 @@
+-- Compatible with LibEuFin version: 1fe2687aaf696c8566367fe7ed082f1d78e6b78d
+
+BEGIN;
+
+SELECT _v.register_patch('sandbox-0001', NULL, NULL);
+
+CREATE TABLE IF NOT EXISTS demobankconfigs
+ (id BIGSERIAL PRIMARY KEY
+ ,hostname TEXT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS bankaccounts
+ (id SERIAL PRIMARY KEY
+ ,iban TEXT NOT NULL
+ ,bic TEXT DEFAULT 'SANDBOXX' NOT NULL
+ ,"label" TEXT NOT NULL
+ ,"owner" TEXT NOT NULL
+ ,"isPublic" BOOLEAN DEFAULT false NOT NULL
+ ,"demoBank" BIGINT NOT NULL
+ ,"lastTransaction" BIGINT NULL
+ ,"lastFiatSubmission" BIGINT NULL
+ ,"lastFiatFetch" TEXT DEFAULT '0' NOT NULL
+ );
+
+ALTER TABLE
+ bankaccounts ADD CONSTRAINT accountLabelIndex UNIQUE ("label");
+
+CREATE TABLE IF NOT EXISTS bankaccounttransactions
+ (id BIGSERIAL PRIMARY KEY
+ ,"creditorIban" TEXT NOT NULL
+ ,"creditorBic" TEXT NULL
+ ,"creditorName" TEXT NOT NULL
+ ,"debtorIban" TEXT NOT NULL
+ ,"debtorBic" TEXT NULL
+ ,"debtorName" TEXT NOT NULL
+ ,subject TEXT NOT NULL
+ ,amount TEXT NOT NULL
+ ,currency TEXT NOT NULL
+ ,"date" BIGINT NOT NULL
+ ,"accountServicerReference" TEXT NOT NULL
+ ,"pmtInfId" TEXT NULL
+ ,"EndToEndId" TEXT NULL
+ ,direction TEXT NOT NULL
+ ,account INT NOT NULL
+ ,demobank BIGINT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS cashoutsubmissions
+ (id BIGSERIAL PRIMARY KEY
+ ,"localTransaction" BIGINT NOT NULL
+ ,"maybeNexusResponse" TEXT NULL
+ ,"submissionTime" BIGINT NULL
+ );
+
+ALTER TABLE
+ cashoutsubmissions ADD CONSTRAINT cashoutsubmissions_localtransaction_unique
UNIQUE ("localTransaction");
+
+CREATE TABLE IF NOT EXISTS demobankconfigpairs
+ (id BIGSERIAL PRIMARY KEY
+ ,"demobankName" TEXT NOT NULL
+ ,"configKey" TEXT NOT NULL
+ ,"configValue" TEXT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicssubscribers
+ (id SERIAL PRIMARY KEY
+ ,"userID" TEXT NOT NULL
+ ,"partnerID" TEXT NOT NULL
+ ,"systemID" TEXT NULL
+ ,"hostID" TEXT NOT NULL
+ ,"signatureKey" INT NULL
+ ,"encryptionKey" INT NULL
+ ,"authorizationKey" INT NULL
+ ,"nextOrderID" INT NOT NULL
+ ,"state" INT NOT NULL
+ ,"bankAccount" INT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicssubscriberpublickeys
+ (id SERIAL PRIMARY KEY
+ ,"rsaPublicKey" bytea NOT NULL
+ ,"state" INT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicshosts
+ (id SERIAL PRIMARY KEY
+ ,"hostID" TEXT NOT NULL
+ ,"ebicsVersion" TEXT NOT NULL
+ ,"signaturePrivateKey" bytea NOT NULL
+ ,"encryptionPrivateKey" bytea NOT NULL
+ ,"authenticationPrivateKey" bytea NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicsdownloadtransactions
+ ("transactionID" TEXT NOT NULL
+ ,"orderType" TEXT NOT NULL
+ ,host INT NOT NULL
+ ,subscriber INT NOT NULL
+ ,"encodedResponse" TEXT NOT NULL
+ ,"transactionKeyEnc" bytea NOT NULL
+ ,"numSegments" INT NOT NULL
+ ,"segmentSize" INT NOT NULL
+ ,"receiptReceived" BOOLEAN NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicsuploadtransactions
+ ("transactionID" TEXT NOT NULL
+ ,"orderType" TEXT NOT NULL
+ ,"orderID" TEXT NOT NULL
+ ,host INT NOT NULL
+ ,subscriber INT NOT NULL
+ ,"numSegments" INT NOT NULL
+ ,"lastSeenSegment" INT NOT NULL
+ ,"transactionKeyEnc" bytea NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicsuploadtransactionchunks
+ ("transactionID" TEXT NOT NULL
+ ,"chunkIndex" INT NOT NULL
+ ,"chunkContent" bytea NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS ebicsordersignatures
+ (id SERIAL PRIMARY KEY
+ ,"orderID" TEXT NOT NULL
+ ,"orderType" TEXT NOT NULL
+ ,"partnerID" TEXT NOT NULL
+ ,"userID" TEXT NOT NULL
+ ,"signatureAlgorithm" TEXT NOT NULL
+ ,"signatureValue" bytea NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS bankaccountfreshtransactions
+ (id BIGSERIAL PRIMARY KEY
+ ,"transaction" BIGINT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS bankaccountreports
+ (id SERIAL PRIMARY KEY
+ ,"reportId" TEXT NOT NULL
+ ,"creationTime" BIGINT NOT NULL
+ ,"xmlMessage" TEXT NOT NULL
+ ,"bankAccount" INT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS bankaccountstatements
+ (id SERIAL PRIMARY KEY
+ ,"statementId" TEXT NOT NULL
+ ,"creationTime" BIGINT NOT NULL
+ ,"xmlMessage" TEXT NOT NULL
+ ,"bankAccount" INT NOT NULL
+ ,"balanceClbd" TEXT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS talerwithdrawals
+ (id BIGSERIAL PRIMARY KEY
+ ,wopid uuid NOT NULL
+ ,amount TEXT NOT NULL
+ ,"selectionDone" BOOLEAN DEFAULT false NOT NULL
+ ,aborted BOOLEAN DEFAULT false NOT NULL
+ ,"confirmationDone" BOOLEAN DEFAULT false NOT NULL
+ ,"reservePub" TEXT NULL
+ ,"selectedExchangePayto" TEXT NULL
+ ,"walletBankAccount" INT NOT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS demobankcustomers
+ (id BIGSERIAL PRIMARY KEY
+ ,username TEXT NOT NULL
+ ,"passwordHash" TEXT NOT NULL
+ ,"name" TEXT NULL
+ ,email TEXT NULL
+ ,phone TEXT NULL
+ ,cashout_address TEXT NULL
+ );
+
+CREATE TABLE IF NOT EXISTS cashoutoperations
+ (id BIGSERIAL PRIMARY KEY
+ ,uuid uuid NOT NULL
+ ,"amountDebit" TEXT NOT NULL
+ ,"amountCredit" TEXT NOT NULL
+ ,"buyAtRatio" TEXT NOT NULL
+ ,"buyInFee" TEXT NOT NULL
+ ,"sellAtRatio" TEXT NOT NULL
+ ,"sellOutFee" TEXT NOT NULL
+ ,subject TEXT NOT NULL
+ ,"creationTime" BIGINT NOT NULL
+ ,"confirmationTime" BIGINT NULL
+ ,"tanChannel" INT NOT NULL
+ ,account TEXT NOT NULL
+ ,"cashoutAddress" TEXT NOT NULL
+ ,tan TEXT NOT NULL
+ ,status INT DEFAULT 1 NOT NULL
+ );
+
+ALTER TABLE
+ bankaccounts ADD CONSTRAINT fk_bankaccounts_demobank_id FOREIGN KEY
("demoBank") REFERENCES demobankconfigs(id) ON DELETE RESTRICT ON UPDATE
RESTRICT;
+
+ALTER TABLE
+ bankaccounts ADD CONSTRAINT fk_bankaccounts_lasttransaction_id FOREIGN KEY
("lastTransaction") REFERENCES bankaccounttransactions(id) ON DELETE RESTRICT
ON UPDATE RESTRICT;
+
+ALTER TABLE
+ bankaccounts ADD CONSTRAINT fk_bankaccounts_lastfiatsubmission_id FOREIGN
KEY ("lastFiatSubmission") REFERENCES bankaccounttransactions(id) ON DELETE
RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ bankaccounttransactions ADD CONSTRAINT fk_bankaccounttransactions_account_id
FOREIGN KEY (account) REFERENCES bankaccounts(id) ON DELETE CASCADE ON UPDATE
RESTRICT;
+
+ALTER TABLE
+ bankaccounttransactions ADD CONSTRAINT
fk_bankaccounttransactions_demobank_id FOREIGN KEY (demobank) REFERENCES
demobankconfigs(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ cashoutsubmissions ADD CONSTRAINT fk_cashoutsubmissions_localtransaction_id
FOREIGN KEY ("localTransaction") REFERENCES bankaccounttransactions(id) ON
DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ ebicssubscribers ADD CONSTRAINT fk_ebicssubscribers_signaturekey_id FOREIGN
KEY ("signatureKey") REFERENCES ebicssubscriberpublickeys(id) ON DELETE
RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ ebicssubscribers ADD CONSTRAINT fk_ebicssubscribers_encryptionkey_id FOREIGN
KEY ("encryptionKey") REFERENCES ebicssubscriberpublickeys(id) ON DELETE
RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ ebicssubscribers ADD CONSTRAINT fk_ebicssubscribers_authorizationkey_id
FOREIGN KEY ("authorizationKey") REFERENCES ebicssubscriberpublickeys(id) ON
DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ ebicssubscribers ADD CONSTRAINT fk_ebicssubscribers_bankaccount_id FOREIGN
KEY ("bankAccount") REFERENCES bankaccounts(id) ON DELETE CASCADE ON UPDATE
RESTRICT;
+
+ALTER TABLE
+ ebicsdownloadtransactions ADD CONSTRAINT
fk_ebicsdownloadtransactions_host_id FOREIGN KEY (host) REFERENCES
ebicshosts(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ ebicsdownloadtransactions ADD CONSTRAINT
fk_ebicsdownloadtransactions_subscriber_id FOREIGN KEY (subscriber) REFERENCES
ebicssubscribers(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ ebicsuploadtransactions ADD CONSTRAINT fk_ebicsuploadtransactions_host_id
FOREIGN KEY (host) REFERENCES ebicshosts(id) ON DELETE RESTRICT ON UPDATE
RESTRICT;
+
+ALTER TABLE
+ ebicsuploadtransactions ADD CONSTRAINT
fk_ebicsuploadtransactions_subscriber_id FOREIGN KEY (subscriber) REFERENCES
ebicssubscribers(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+ALTER TABLE
+ bankaccountfreshtransactions ADD CONSTRAINT
fk_bankaccountfreshtransactions_transaction_id FOREIGN KEY ("transaction")
REFERENCES bankaccounttransactions(id) ON DELETE CASCADE ON UPDATE RESTRICT;
+
+ALTER TABLE
+ bankaccountreports ADD CONSTRAINT fk_bankaccountreports_bankaccount_id
FOREIGN KEY ("bankAccount") REFERENCES bankaccounts(id) ON DELETE RESTRICT ON
UPDATE RESTRICT;
+
+ALTER TABLE
+ bankaccountstatements ADD CONSTRAINT fk_bankaccountstatements_bankaccount_id
FOREIGN KEY ("bankAccount") REFERENCES bankaccounts(id) ON DELETE RESTRICT ON
UPDATE RESTRICT;
+
+ALTER TABLE
+ talerwithdrawals ADD CONSTRAINT fk_talerwithdrawals_walletbankaccount_id
FOREIGN KEY ("walletBankAccount") REFERENCES bankaccounts(id) ON DELETE
RESTRICT ON UPDATE RESTRICT;
+
+COMMIT;
diff --git a/database-versioning/versioning.sql
b/database-versioning/versioning.sql
new file mode 100644
index 00000000..98e7f661
--- /dev/null
+++ b/database-versioning/versioning.sql
@@ -0,0 +1,293 @@
+-- LICENSE AND COPYRIGHT
+--
+-- Copyright (C) 2010 Hubert depesz Lubaczewski
+--
+-- This program is distributed under the (Revised) BSD License:
+-- L<http://www.opensource.org/licenses/bsd-license.php>
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- * Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- * Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- * Neither the name of Hubert depesz Lubaczewski's Organization
+-- nor the names of its contributors may be used to endorse or
+-- promote products derived from this software without specific
+-- prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE
+-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY,
+-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE
+-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+-- Code origin:
https://gitlab.com/depesz/Versioning/blob/master/install.versioning.sql
+--
+--
+-- # NAME
+--
+-- **Versioning** - simplistic take on tracking and applying changes to
databases.
+--
+-- # DESCRIPTION
+--
+-- This project strives to provide simple way to manage changes to
+-- database.
+--
+-- Instead of making changes on development server, then finding
+-- differences between production and development, deciding which ones
+-- should be installed on production, and finding a way to install them -
+-- you start with writing diffs themselves!
+--
+-- # INSTALLATION
+--
+-- To install versioning simply run install.versioning.sql in your database
+-- (all of them: production, stage, test, devel, ...).
+--
+-- # USAGE
+--
+-- In your files with patches to database, put whole logic in single
+-- transaction, and use \_v.\* functions - usually \_v.register_patch() at
+-- least to make sure everything is OK.
+--
+-- For example. Let's assume you have patch files:
+--
+-- ## 0001.sql:
+--
+-- ```
+-- create table users (id serial primary key, username text);
+-- ```
+--
+-- ## 0002.sql:
+--
+-- ```
+-- insert into users (username) values ('depesz');
+-- ```
+-- To change it to use versioning you would change the files, to this
+-- state:
+--
+-- 0000.sql:
+--
+-- ```
+-- BEGIN;
+-- select _v.register_patch('000-base', NULL, NULL);
+-- create table users (id serial primary key, username text);
+-- COMMIT;
+-- ```
+--
+-- ## 0002.sql:
+--
+-- ```
+-- BEGIN;
+-- select _v.register_patch('001-users', ARRAY['000-base'], NULL);
+-- insert into users (username) values ('depesz');
+-- COMMIT;
+-- ```
+--
+-- This will make sure that patch 001-users can only be applied after
+-- 000-base.
+--
+-- # AVAILABLE FUNCTIONS
+--
+-- ## \_v.register_patch( TEXT )
+--
+-- Registers named patch, or dies if it is already registered.
+--
+-- Returns integer which is id of patch in \_v.patches table - only if it
+-- succeeded.
+--
+-- ## \_v.register_patch( TEXT, TEXT[] )
+--
+-- Same as \_v.register_patch( TEXT ), but checks is all given patches (given
as
+-- array in second argument) are already registered.
+--
+-- ## \_v.register_patch( TEXT, TEXT[], TEXT[] )
+--
+-- Same as \_v.register_patch( TEXT, TEXT[] ), but also checks if there are no
conflicts with preexisting patches.
+--
+-- Third argument is array of names of patches that conflict with current one.
So
+-- if any of them is installed - register_patch will error out.
+--
+-- ## \_v.unregister_patch( TEXT )
+--
+-- Removes information about given patch from the versioning data.
+--
+-- It doesn't remove objects that were created by this patch - just removes
+-- metainformation.
+--
+-- ## \_v.assert_user_is_superuser()
+--
+-- Make sure that current patch is being loaded by superuser.
+--
+-- If it's not - it will raise exception, and break transaction.
+--
+-- ## \_v.assert_user_is_not_superuser()
+--
+-- Make sure that current patch is not being loaded by superuser.
+--
+-- If it is - it will raise exception, and break transaction.
+--
+-- ## \_v.assert_user_is_one_of(TEXT, TEXT, ... )
+--
+-- Make sure that current patch is being loaded by one of listed users.
+--
+-- If ```current_user``` is not listed as one of arguments - function will
raise
+-- exception and break the transaction.
+
+BEGIN;
+
+-- This file adds versioning support to database it will be loaded to.
+-- It requires that PL/pgSQL is already loaded - will raise exception
otherwise.
+-- All versioning "stuff" (tables, functions) is in "_v" schema.
+
+-- All functions are defined as 'RETURNS SETOF INT4' to be able to make them
to RETURN literally nothing (0 rows).
+-- >> RETURNS VOID<< IS similar, but it still outputs "empty line" in psql
when calling.
+CREATE SCHEMA IF NOT EXISTS _v;
+COMMENT ON SCHEMA _v IS 'Schema for versioning data and functionality.';
+
+CREATE TABLE IF NOT EXISTS _v.patches (
+ patch_name TEXT PRIMARY KEY,
+ applied_tsz TIMESTAMPTZ NOT NULL DEFAULT now(),
+ applied_by TEXT NOT NULL,
+ requires TEXT[],
+ conflicts TEXT[]
+);
+COMMENT ON TABLE _v.patches IS 'Contains information about what
patches are currently applied on database.';
+COMMENT ON COLUMN _v.patches.patch_name IS 'Name of patch, has to be unique
for every patch.';
+COMMENT ON COLUMN _v.patches.applied_tsz IS 'When the patch was applied.';
+COMMENT ON COLUMN _v.patches.applied_by IS 'Who applied this patch
(PostgreSQL username)';
+COMMENT ON COLUMN _v.patches.requires IS 'List of patches that are required
for given patch.';
+COMMENT ON COLUMN _v.patches.conflicts IS 'List of patches that conflict
with given patch.';
+
+CREATE OR REPLACE FUNCTION _v.register_patch( IN in_patch_name TEXT, IN
in_requirements TEXT[], in_conflicts TEXT[], OUT versioning INT4 ) RETURNS
setof INT4 AS $$
+DECLARE
+ t_text TEXT;
+ t_text_a TEXT[];
+ i INT4;
+BEGIN
+ -- Thanks to this we know only one patch will be applied at a time
+ LOCK TABLE _v.patches IN EXCLUSIVE MODE;
+
+ SELECT patch_name INTO t_text FROM _v.patches WHERE patch_name =
in_patch_name;
+ IF FOUND THEN
+ RAISE EXCEPTION 'Patch % is already applied!', in_patch_name;
+ END IF;
+
+ t_text_a := ARRAY( SELECT patch_name FROM _v.patches WHERE patch_name =
any( in_conflicts ) );
+ IF array_upper( t_text_a, 1 ) IS NOT NULL THEN
+ RAISE EXCEPTION 'Versioning patches conflict. Conflicting patche(s)
installed: %.', array_to_string( t_text_a, ', ' );
+ END IF;
+
+ IF array_upper( in_requirements, 1 ) IS NOT NULL THEN
+ t_text_a := '{}';
+ FOR i IN array_lower( in_requirements, 1 ) .. array_upper(
in_requirements, 1 ) LOOP
+ SELECT patch_name INTO t_text FROM _v.patches WHERE patch_name =
in_requirements[i];
+ IF NOT FOUND THEN
+ t_text_a := t_text_a || in_requirements[i];
+ END IF;
+ END LOOP;
+ IF array_upper( t_text_a, 1 ) IS NOT NULL THEN
+ RAISE EXCEPTION 'Missing prerequisite(s): %.', array_to_string(
t_text_a, ', ' );
+ END IF;
+ END IF;
+
+ INSERT INTO _v.patches (patch_name, applied_tsz, applied_by, requires,
conflicts ) VALUES ( in_patch_name, now(), current_user, coalesce(
in_requirements, '{}' ), coalesce( in_conflicts, '{}' ) );
+ RETURN;
+END;
+$$ language plpgsql;
+COMMENT ON FUNCTION _v.register_patch( TEXT, TEXT[], TEXT[]) IS 'Function to
register patches in database. Raises exception if there are conflicts,
prerequisites are not installed or the migration has already been installed.';
+
+CREATE OR REPLACE FUNCTION _v.register_patch( TEXT, TEXT[] ) RETURNS setof
INT4 AS $$
+ SELECT _v.register_patch( $1, $2, NULL );
+$$ language sql;
+COMMENT ON FUNCTION _v.register_patch( TEXT, TEXT[] ) IS 'Wrapper to allow
registration of patches without conflicts.';
+CREATE OR REPLACE FUNCTION _v.register_patch( TEXT ) RETURNS setof INT4 AS $$
+ SELECT _v.register_patch( $1, NULL, NULL );
+$$ language sql;
+COMMENT ON FUNCTION _v.register_patch( TEXT ) IS 'Wrapper to allow
registration of patches without requirements and conflicts.';
+
+CREATE OR REPLACE FUNCTION _v.unregister_patch( IN in_patch_name TEXT, OUT
versioning INT4 ) RETURNS setof INT4 AS $$
+DECLARE
+ i INT4;
+ t_text_a TEXT[];
+BEGIN
+ -- Thanks to this we know only one patch will be applied at a time
+ LOCK TABLE _v.patches IN EXCLUSIVE MODE;
+
+ t_text_a := ARRAY( SELECT patch_name FROM _v.patches WHERE in_patch_name =
ANY( requires ) );
+ IF array_upper( t_text_a, 1 ) IS NOT NULL THEN
+ RAISE EXCEPTION 'Cannot uninstall %, as it is required by: %.',
in_patch_name, array_to_string( t_text_a, ', ' );
+ END IF;
+
+ DELETE FROM _v.patches WHERE patch_name = in_patch_name;
+ GET DIAGNOSTICS i = ROW_COUNT;
+ IF i < 1 THEN
+ RAISE EXCEPTION 'Patch % is not installed, so it can''t be
uninstalled!', in_patch_name;
+ END IF;
+
+ RETURN;
+END;
+$$ language plpgsql;
+COMMENT ON FUNCTION _v.unregister_patch( TEXT ) IS 'Function to unregister
patches in database. Dies if the patch is not registered, or if unregistering
it would break dependencies.';
+
+CREATE OR REPLACE FUNCTION _v.assert_patch_is_applied( IN in_patch_name TEXT )
RETURNS TEXT as $$
+DECLARE
+ t_text TEXT;
+BEGIN
+ SELECT patch_name INTO t_text FROM _v.patches WHERE patch_name =
in_patch_name;
+ IF NOT FOUND THEN
+ RAISE EXCEPTION 'Patch % is not applied!', in_patch_name;
+ END IF;
+ RETURN format('Patch %s is applied.', in_patch_name);
+END;
+$$ language plpgsql;
+COMMENT ON FUNCTION _v.assert_patch_is_applied( TEXT ) IS 'Function that can
be used to make sure that patch has been applied.';
+
+CREATE OR REPLACE FUNCTION _v.assert_user_is_superuser() RETURNS TEXT as $$
+DECLARE
+ v_super bool;
+BEGIN
+ SELECT usesuper INTO v_super FROM pg_user WHERE usename = current_user;
+ IF v_super THEN
+ RETURN 'assert_user_is_superuser: OK';
+ END IF;
+ RAISE EXCEPTION 'Current user is not superuser - cannot continue.';
+END;
+$$ language plpgsql;
+COMMENT ON FUNCTION _v.assert_user_is_superuser() IS 'Function that can be
used to make sure that patch is being applied using superuser account.';
+
+CREATE OR REPLACE FUNCTION _v.assert_user_is_not_superuser() RETURNS TEXT as $$
+DECLARE
+ v_super bool;
+BEGIN
+ SELECT usesuper INTO v_super FROM pg_user WHERE usename = current_user;
+ IF v_super THEN
+ RAISE EXCEPTION 'Current user is superuser - cannot continue.';
+ END IF;
+ RETURN 'assert_user_is_not_superuser: OK';
+END;
+$$ language plpgsql;
+COMMENT ON FUNCTION _v.assert_user_is_not_superuser() IS 'Function that can be
used to make sure that patch is being applied using normal (not superuser)
account.';
+
+CREATE OR REPLACE FUNCTION _v.assert_user_is_one_of(VARIADIC
p_acceptable_users TEXT[] ) RETURNS TEXT as $$
+DECLARE
+BEGIN
+ IF current_user = any( p_acceptable_users ) THEN
+ RETURN 'assert_user_is_one_of: OK';
+ END IF;
+ RAISE EXCEPTION 'User is not one of: % - cannot continue.',
p_acceptable_users;
+END;
+$$ language plpgsql;
+COMMENT ON FUNCTION _v.assert_user_is_one_of(TEXT[]) IS 'Function that can be
used to make sure that patch is being applied by one of defined users.';
+
+COMMIT;
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 1f16da78..b20ba00f 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -379,7 +379,9 @@ class Serve : CliktCommand("Run sandbox HTTP server") {
)
exitProcess(1)
}
- execThrowableOrTerminate {
dbCreateTables(getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME)) }
+ execThrowableOrTerminate {
+ dbCreateTables(getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME))
+ }
// Refuse to operate without a 'default' demobank.
val demobank = getDemobank("default")
if (demobank == null) {
diff --git a/util/src/main/kotlin/DB.kt b/util/src/main/kotlin/DB.kt
index 90065529..d8ac3fbe 100644
--- a/util/src/main/kotlin/DB.kt
+++ b/util/src/main/kotlin/DB.kt
@@ -25,6 +25,7 @@ import logger
import net.taler.wallet.crypto.Base32Crockford
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.transactions.TransactionManager
+import org.jetbrains.exposed.sql.transactions.transaction
import org.postgresql.jdbc.PgConnection
fun Transaction.isPostgres(): Boolean {
@@ -217,4 +218,15 @@ class PostgresListenHandle(val channelName: String) {
conn.close()
return false
}
+}
+
+fun getDatabaseName(): String {
+ var maybe_db_name: String? = null
+ transaction {
+ this.exec("SELECT current_database() AS database_name;") { oneLineRes
->
+ if (oneLineRes.next())
+ maybe_db_name = oneLineRes.getString("database_name")
+ }
+ }
+ return maybe_db_name ?: throw internalServerError("Could not find current
DB name")
}
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Errors.kt
b/util/src/main/kotlin/exec.kt
similarity index 58%
copy from nexus/src/main/kotlin/tech/libeufin/nexus/Errors.kt
copy to util/src/main/kotlin/exec.kt
index 0cc340e8..c29d5b04 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Errors.kt
+++ b/util/src/main/kotlin/exec.kt
@@ -1,35 +1,33 @@
/*
* This file is part of LibEuFin.
- * Copyright (C) 2020 Taler Systems S.A.
- *
+ * Copyright (C) 2019 Stanisci and Dold.
+
* LibEuFin is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3, or
* (at your option) any later version.
- *
+
* LibEuFin is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
* Public License for more details.
- *
+
* You should have received a copy of the GNU Affero General Public
* License along with LibEuFin; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.nexus
+package tech.libeufin.util
-import io.ktor.http.HttpStatusCode
-import tech.libeufin.util.LibeufinErrorCode
-
-data class NexusError(
- val statusCode: HttpStatusCode,
- val reason: String,
- val code: LibeufinErrorCode? = null
- ) :
- Exception("$reason (HTTP status $statusCode)")
-
-fun NexusAssert(condition: Boolean, errorMsg: String): Boolean {
- if (! condition) throw NexusError(HttpStatusCode.InternalServerError,
errorMsg)
- return true
+/**
+ * Wrapper around the ProcessBuilder API. It executes a
+ * command and throws exception if the result is not zero.
+ */
+fun execCommand(cmd: List<String>) {
+ val result: Int = ProcessBuilder(cmd)
+ .redirectOutput(ProcessBuilder.Redirect.INHERIT)
+ .redirectError(ProcessBuilder.Redirect.INHERIT)
+ .start()
+ .waitFor()
+ if (result != 0) throw internalServerError("Command '$cmd' failed.")
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libeufin] branch master updated (1fe2687a -> a105222b),
gnunet <=