db-migration #10

Merged
hsh-michaelhoennig merged 74 commits from db-migration into master 2024-01-23 15:11:24 +01:00
14 changed files with 109 additions and 32 deletions
Showing only changes of commit 2f5acd4171 - Show all commits

View File

@ -1,3 +1,6 @@
export HSADMINNG_POSTGRES_ADMIN_USERNAME=admin
export HSADMINNG_POSTGRES_RESTRICTED_USERNAME=restricted
gradleWrapper () { gradleWrapper () {
if [ ! -f gradlew ]; then if [ ! -f gradlew ]; then
echo "No 'gradlew' found. Maybe you are not in the root dir of a gradle project?" echo "No 'gradlew' found. Maybe you are not in the root dir of a gradle project?"

View File

@ -39,10 +39,10 @@ public class HsOfficeContactEntity implements Stringifyable, HasUuid {
private String postalAddress; private String postalAddress;
@Column(name = "emailaddresses", columnDefinition = "json") @Column(name = "emailaddresses", columnDefinition = "json")
private String emailAddresses; private String emailAddresses; // TODO: check if we can really add multiple. format: ["eins@...", "zwei@..."]
@Column(name = "phonenumbers", columnDefinition = "json") @Column(name = "phonenumbers", columnDefinition = "json")
private String phoneNumbers; private String phoneNumbers; // TODO: check if we can really add multiple. format: { "office": "+49 40 12345-10", "fax": "+49 40 12345-05" }
@Override @Override
public String toString() { public String toString() {

View File

@ -20,3 +20,7 @@ spring:
liquibase: liquibase:
contexts: dev contexts: dev
hsadminng:
hsh-michaelhoennig marked this conversation as resolved

remove, unused

remove, unused

fixed

fixed
postgres:
leakproof:

View File

@ -0,0 +1,12 @@
--liquibase formatted sql
-- ============================================================================
-- NUMERIC-HASH-FUNCTIONS
--changeset hash:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create function postgresAdminUserName() returns text as $$
if
$$ language sql;
--//

View File

@ -763,13 +763,15 @@ $$;
do $$ do $$
begin begin
if '${ADMIN_USER}'='admin' then if '${HSADMINNG_POSTGRES_ADMIN_USERNAME}'='admin' then
create role admin; create role admin;
grant all privileges on all tables in schema public to admin; grant all privileges on all tables in schema public to admin;
create role restricted;
grant all privileges on all tables in schema public to restricted;
end if; end if;
if '${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}'='restricted' then
create role restricted;
end if;
-- grant all privileges on all tables in schema public to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
end $$ end $$
--// --//

View File

@ -41,7 +41,7 @@ select *
) as unordered ) as unordered
-- @formatter:on -- @formatter:on
order by objectTable || '#' || objectIdName || '.' || roleType; order by objectTable || '#' || objectIdName || '.' || roleType;
grant all privileges on rbacrole_rv to ${RESTRICTED_USER}; grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--// --//
@ -126,7 +126,7 @@ select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) ||
join RbacObject as o on o.uuid = r.objectUuid join RbacObject as o on o.uuid = r.objectUuid
order by grantedRoleIdName; order by grantedRoleIdName;
-- @formatter:on -- @formatter:on
grant all privileges on rbacrole_rv to ${RESTRICTED_USER}; grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--// --//
@ -240,7 +240,7 @@ create or replace view RbacUser_rv as
) as unordered ) as unordered
-- @formatter:on -- @formatter:on
order by unordered.name; order by unordered.name;
grant all privileges on RbacUser_rv to ${RESTRICTED_USER}; grant all privileges on RbacUser_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--// --//
-- ============================================================================ -- ============================================================================
@ -326,7 +326,7 @@ select r.uuid as roleuuid, p.uuid as permissionUuid,
join rbacgrants g on g.ascendantuuid = r.uuid join rbacgrants g on g.ascendantuuid = r.uuid
join rbacpermission p on p.uuid = g.descendantuuid join rbacpermission p on p.uuid = g.descendantuuid
join rbacobject o on o.uuid = p.objectuuid; join rbacobject o on o.uuid = p.objectuuid;
grant all privileges on RbacOwnGrantedPermissions_rv to ${RESTRICTED_USER}; grant all privileges on RbacOwnGrantedPermissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
-- @formatter:om -- @formatter:om
-- ============================================================================ -- ============================================================================

View File

@ -104,7 +104,7 @@ begin
create or replace view %1$s_iv as create or replace view %1$s_iv as
select target.uuid, cleanIdentifier(%2$s) as idName select target.uuid, cleanIdentifier(%2$s) as idName
from %1$s as target; from %1$s as target;
grant all privileges on %1$s_iv to ${RESTRICTED_USER}; grant all privileges on %1$s_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
$sql$, targetTable, idNameExpression); $sql$, targetTable, idNameExpression);
execute sql; execute sql;
@ -157,7 +157,7 @@ begin
from %1$s as target from %1$s as target
where target.uuid in (select * from accessibleObjects) where target.uuid in (select * from accessibleObjects)
order by %2$s; order by %2$s;
grant all privileges on %1$s_rv to ${RESTRICTED_USER}; grant all privileges on %1$s_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
$sql$, targetTable, orderBy); $sql$, targetTable, orderBy);
execute sql; execute sql;

View File

@ -18,7 +18,7 @@ create table Global
); );
create unique index Global_Singleton on Global ((0)); create unique index Global_Singleton on Global ((0));
grant select on global to ${RESTRICTED_USER}; grant select on global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--// --//
@ -48,7 +48,7 @@ drop view if exists global_iv;
create or replace view global_iv as create or replace view global_iv as
select target.uuid, target.name as idName select target.uuid, target.name as idName
from global as target; from global as target;
grant all privileges on global_iv to ${RESTRICTED_USER}; grant all privileges on global_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
/* /*
Returns the objectUuid for a given identifying name (in this case the idName). Returns the objectUuid for a given identifying name (in this case the idName).

View File

@ -93,7 +93,7 @@ call generateRbacIdentityView('test_package', 'target.name');
-- from test_package as target -- from test_package as target
-- where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'test_package', currentSubjectsUuids())) -- where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'test_package', currentSubjectsUuids()))
-- order by target.name; -- order by target.name;
-- grant all privileges on test_package_rv to ${RESTRICTED_USER}; -- grant all privileges on test_package_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
call generateRbacRestrictedView('test_package', 'target.name', call generateRbacRestrictedView('test_package', 'target.name',
$updates$ $updates$

View File

@ -110,5 +110,5 @@ create or replace view test_domain_rv as
select target.* select target.*
from test_domain as target from test_domain as target
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'domain', currentSubjectsUuids())); where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'domain', currentSubjectsUuids()));
grant all privileges on test_domain_rv to ${RESTRICTED_USER}; grant all privileges on test_domain_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--// --//

View File

@ -22,6 +22,7 @@ import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
@ -55,30 +56,45 @@ import static org.assertj.core.api.Assertions.assertThat;
* For a real import a main method will be added later * For a real import a main method will be added later
* which reads CSV files from the file system. * which reads CSV files from the file system.
* *
* When run on a Hostsharing database, it needs the following settings (hsh99_... just examples): * When run on a Hostsharing database, it needs the following settings (hsh99_... just examples).
*
* In a real hostsharing environment, these are created via (the old) hsadmin:
* *
* CREATE USER hsh99_admin WITH PASSWORD 'password'; * CREATE USER hsh99_admin WITH PASSWORD 'password';
* GRANT ALL ON SCHEMA public TO hsh99_admin; * CREATE DATABASE hsh99_hsadminng ENCODING 'UTF8' TEMPLATE template0;
* REVOKE ALL ON DATABASE hsh99_hsadminng FROM public; -- why does hsadmin do that?
* ALTER DATABASE hsh99_hsadminng OWNER TO hsh99_admin;
* *
* CREATE USER hsh99_restricted WITH PASSWORD 'password'; * CREATE USER hsh99_restricted WITH PASSWORD 'password';
* GRANT ALL PRIVILEGES ON ALL TALBES IN SCHEMA hsh99_hsadminng to hsh99_restricted * GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public to hsh99_restricted;
* Additionally we need these settings (because the Hostsharing DB-Admin has no CREATE right):
* *
* CREATE EXTENSION "uuid-ossp"; * CREATE EXTENSION IF EXISTS "uuid-ossp";
* *
* And the environment variables ADMIN_USER and RESTRICTED_USER have to be set to the actual users. * Then these environment variables need to be set for Liquibase:
* TODO: password * export HSADMIN_POSTGRES_JDBC=jdbc:postgresql://localhost:6432/hsh99_hsadminng
* export HSADMIN_POSTGRES_ADMIN_USERNAME=hsh99_admin
* export HSADMIN_POSTGRES_ADMIN_PASSWORD=password
* export HSADMIN_POSTGRES_RESTRICTED_USERNAME=hsh99_restricted
*
* Then, to run the import, uncomment the @Diabled and then run:
*
* gw test -tests ImportOfficeTables -x check
*/ */
// @Disabled //@Disabled
@DataJpaTest(properties = { @DataJpaTest(properties = {
"spring.profiles.active=migration", "spring.datasource.url=${HSADMIN_POSTGRES_JDBC:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}",
"spring.datasource.url=jdbc:postgresql://localhost:5432/postgres", "spring.datasource.username=${HSADMIN_POSTGRES_ADMIN_USERNAME:admin}",
"spring.datasource.username=hsh99_admin", "spring.datasource.password=${HSADMIN_POSTGRES_ADMIN_PASSWORD:password}"
"spring.datasource.password=password"
}) })
@Import({ Context.class, JpaAttempt.class }) @Import({ Context.class, JpaAttempt.class })
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ImportOfficeTables extends ContextBasedTest { public class ImportOfficeTables extends ContextBasedTest {
@Value("${spring.datasource.url}")
private String jdbcUrl;
// TODO: use real rbacSuperuser for actual import // TODO: use real rbacSuperuser for actual import
private static final String rbacSuperuser = "superuser-alex@hostsharing.net"; private static final String rbacSuperuser = "superuser-alex@hostsharing.net";
@ -115,6 +131,10 @@ public class ImportOfficeTables extends ContextBasedTest {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
return;
}
// no contacts yet => mostly null values // no contacts yet => mostly null values
assertThat(partners.toString()).isEqualToIgnoringWhitespace(""" assertThat(partners.toString()).isEqualToIgnoringWhitespace("""
{ {
@ -150,6 +170,10 @@ public class ImportOfficeTables extends ContextBasedTest {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
return;
}
assertThat(partners.toString()).isEqualToIgnoringWhitespace(""" assertThat(partners.toString()).isEqualToIgnoringWhitespace("""
{ {
7=partner(Mellies, Michael: Herr Michael Mellies ), 7=partner(Mellies, Michael: Herr Michael Mellies ),
@ -199,6 +223,10 @@ public class ImportOfficeTables extends ContextBasedTest {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
return;
}
assertThat(bankAccounts.toString()).isEqualToIgnoringWhitespace(""" assertThat(bankAccounts.toString()).isEqualToIgnoringWhitespace("""
{ {
234234=bankAccount(holder='Michael Mellies', iban='DE37500105177419788228', bic='INGDDEFFXXX'), 234234=bankAccount(holder='Michael Mellies', iban='DE37500105177419788228', bic='INGDDEFFXXX'),
@ -224,6 +252,10 @@ public class ImportOfficeTables extends ContextBasedTest {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
return;
}
assertThat(coopShares.toString()).isEqualToIgnoringWhitespace(""" assertThat(coopShares.toString()).isEqualToIgnoringWhitespace("""
{ {
33443=CoopShareTransaction(10007, 2000-12-06, SUBSCRIPTION, 20, initial share subscription), 33443=CoopShareTransaction(10007, 2000-12-06, SUBSCRIPTION, 20, initial share subscription),
@ -245,6 +277,10 @@ public class ImportOfficeTables extends ContextBasedTest {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
return;
}
assertThat(coopAssets.toString()).isEqualToIgnoringWhitespace(""" assertThat(coopAssets.toString()).isEqualToIgnoringWhitespace("""
{ {
30000=CoopAssetsTransaction(10007, 2000-12-06, DEPOSIT, 1280.00, for subscription A), 30000=CoopAssetsTransaction(10007, 2000-12-06, DEPOSIT, 1280.00, for subscription A),
@ -442,7 +478,7 @@ public class ImportOfficeTables extends ContextBasedTest {
.debitorNumberSuffix((byte) 0) .debitorNumberSuffix((byte) 0)
.defaultPrefix(rec.getString("member_code").replace("hsh00-", "")) .defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
.partner(partner) .partner(partner)
.billingContact(partner.getContact()) .billingContact(partner.getContact()) // TODO falsch
.billable(rec.isEmpty("free")) .billable(rec.isEmpty("free"))
.vatReverseCharge(rec.getBoolean("exempt_vat")) .vatReverseCharge(rec.getBoolean("exempt_vat"))
.vatBusiness("GROSS".equals(rec.getString("indicator_vat"))) // TODO: remove .vatBusiness("GROSS".equals(rec.getString("indicator_vat"))) // TODO: remove

View File

@ -7,12 +7,14 @@ import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserRepository;
import net.hostsharing.test.Accepts; import net.hostsharing.test.Accepts;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.test.web.server.LocalServerPort;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
@SpringBootTest( @SpringBootTest(
@ -37,6 +39,14 @@ class RbacRoleControllerAcceptanceTest {
@Autowired @Autowired
RbacRoleRepository rbacRoleRepository; RbacRoleRepository rbacRoleRepository;
@Value("${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}")
hsh-michaelhoennig marked this conversation as resolved Outdated

remove

remove
String restrictedUser;
@Test
void testEnv() {
assertThat(restrictedUser).isEqualTo("restricted");
}
@Test @Test
@Accepts({ "ROL:L(List)" }) @Accepts({ "ROL:L(List)" })
void globalAdmin_withoutAssumedRole_canViewAllRoles() { void globalAdmin_withoutAssumedRole_canViewAllRoles() {

View File

@ -9,6 +9,7 @@ import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -42,6 +43,14 @@ class RbacUserControllerAcceptanceTest {
@Autowired @Autowired
RbacUserRepository rbacUserRepository; RbacUserRepository rbacUserRepository;
@Value("${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}")
hsh-michaelhoennig marked this conversation as resolved Outdated

remove

remove
String restrictedUser;
@Test
void testEnv() {
assertThat(restrictedUser).isEqualTo("restricted");
}
@Nested @Nested
class CreateRbacUser { class CreateRbacUser {

View File

@ -1,5 +1,6 @@
contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode;city; country; phone_private; phone_office; phone_mobile; fax; email; roles contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode;city; country; phone_private; phone_office; phone_mobile; fax; email; roles
71; 7; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; billing,operation 71; 7; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; contractual,billing,operation
101; 10; Frau; Jenny; Meyer; Dr.; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 8888888; ; +49 30 9999999; jm@example.org; billing 101; 10; Frau; Jenny; Meyer; Dr.; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 1111111; ; +49 30 2222222; jm@example.org; billing
102; 10; Herr; Andrew; Meyer; ; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 9999999; am@example.org; operation 102; 10; Herr; Andrew; Meyer; ; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am@example.org; operation
121; 12; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; billing,operation 102; 10; Herr; Philip; Meyer; ; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; pm@example.org; contractual
121; 12; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; billing,contractual,operation

1 contact_id bp_id salut first_name last_name title firma co street zipcode city country phone_private phone_office phone_mobile fax email roles
2 71 7 Herr Michael Mellies Kleine Freiheit 50 26524 Hage DE +49 4931 123456 +49 1522 123456 mih@example.org contractual,billing,operation
3 101 10 Frau Jenny Meyer Dr. JM e.K. Waldweg 5 11001 Berlin DE +49 30 7777777 +49 30 1111111 +49 30 2222222 jm@example.org billing
4 102 10 Herr Andrew Meyer JM e.K. Waldweg 5 11001 Berlin DE +49 30 6666666 +49 30 3333333 +49 30 4444444 am@example.org operation
5 102 10 Herr Philip Meyer JM e.K. Waldweg 5 11001 Berlin DE +49 30 6666666 +49 30 5555555 +49 30 6666666 pm@example.org contractual
6 121 12 Petra Schmidt Test PS ps@example.com billing,contractual,operation