add CustomerRepositoryIntegrationTest, fix testcontainers liquibase context and improve error messages
This commit is contained in:
		@@ -8,6 +8,7 @@ public class PostgreSQL95CustomDialect extends PostgreSQL95Dialect {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public PostgreSQL95CustomDialect() {
 | 
					    public PostgreSQL95CustomDialect() {
 | 
				
			||||||
        this.registerHibernateType(2003, StringArrayType.class.getName());
 | 
					        this.registerHibernateType(2003, StringArrayType.class.getName());
 | 
				
			||||||
 | 
					        this.registerHibernateType(1111, "pg-uuid");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,12 @@
 | 
				
			|||||||
package net.hostsharing.hsadminng.hscustomer;
 | 
					package net.hostsharing.hsadminng.hscustomer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
					import org.springframework.data.jpa.repository.JpaRepository;
 | 
				
			||||||
 | 
					import org.springframework.data.jpa.repository.Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.UUID;
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public interface CustomerRepository extends JpaRepository<CustomerEntity, UUID> {
 | 
					public interface CustomerRepository extends JpaRepository<CustomerEntity, UUID> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    List<CustomerEntity> findByPrefixLike(final String prefix);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -601,8 +601,12 @@ begin
 | 
				
			|||||||
    objectTable := pureIdentifier(objectTable);
 | 
					    objectTable := pureIdentifier(objectTable);
 | 
				
			||||||
    objectIdName := pureIdentifier(objectIdName);
 | 
					    objectIdName := pureIdentifier(objectIdName);
 | 
				
			||||||
    sql := format('select * from %sUuidByIdName(%L);', objectTable, objectIdName);
 | 
					    sql := format('select * from %sUuidByIdName(%L);', objectTable, objectIdName);
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
        raise notice 'sql: %', sql;
 | 
					        raise notice 'sql: %', sql;
 | 
				
			||||||
        execute sql into uuid;
 | 
					        execute sql into uuid;
 | 
				
			||||||
 | 
					    exception when OTHERS then
 | 
				
			||||||
 | 
					        raise exception 'function %UuidByIdName(...) not found, add identity view support for table %', objectTable, objectTable;
 | 
				
			||||||
 | 
					    end;
 | 
				
			||||||
    return uuid;
 | 
					    return uuid;
 | 
				
			||||||
end; $$;
 | 
					end; $$;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -622,8 +626,12 @@ declare
 | 
				
			|||||||
    roleUuidToAssume    uuid;
 | 
					    roleUuidToAssume    uuid;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
    currentUserId := currentUserId();
 | 
					    currentUserId := currentUserId();
 | 
				
			||||||
 | 
					    if currentUserId is null then
 | 
				
			||||||
 | 
					        raise exception 'user % does not exist', currentUser();
 | 
				
			||||||
 | 
					    end if;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    roleNames := assumedRoles();
 | 
					    roleNames := assumedRoles();
 | 
				
			||||||
    if (cardinality(roleNames) = 0) then
 | 
					    if cardinality(roleNames) = 0 then
 | 
				
			||||||
        return array [currentUserId];
 | 
					        return array [currentUserId];
 | 
				
			||||||
    end if;
 | 
					    end if;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -645,7 +653,7 @@ begin
 | 
				
			|||||||
                  and r.roleType = roleTypeToAssume
 | 
					                  and r.roleType = roleTypeToAssume
 | 
				
			||||||
                into roleUuidToAssume;
 | 
					                into roleUuidToAssume;
 | 
				
			||||||
            if (not isGranted(currentUserId, roleUuidToAssume)) then
 | 
					            if (not isGranted(currentUserId, roleUuidToAssume)) then
 | 
				
			||||||
                raise exception 'user % has no permission to assume role %', currentUser(), roleUuidToAssume;
 | 
					                raise exception 'user % (%) has no permission to assume role % (%)', currentUser(), currentUserId, roleName, roleUuidToAssume;
 | 
				
			||||||
            end if;
 | 
					            end if;
 | 
				
			||||||
            roleIdsToAssume := roleIdsToAssume || roleUuidToAssume;
 | 
					            roleIdsToAssume := roleIdsToAssume || roleUuidToAssume;
 | 
				
			||||||
        end loop;
 | 
					        end loop;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,19 +9,44 @@
 | 
				
			|||||||
    Otherwise these columns needed to be nullable and
 | 
					    Otherwise these columns needed to be nullable and
 | 
				
			||||||
    many queries would be more complicated.
 | 
					    many queries would be more complicated.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
create table Hostsharing
 | 
					create table Global
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
    uuid uuid primary key references RbacObject (uuid)
 | 
					    uuid uuid primary key references RbacObject (uuid),
 | 
				
			||||||
 | 
					    name varchar(63)
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
create unique index Hostsharing_Singleton on Hostsharing ((0));
 | 
					create unique index Global_Singleton on Global ((0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
  A single row to be referenced as a global object.
 | 
					  A single row to be referenced as a global object.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
insert
 | 
					insert
 | 
				
			||||||
    into RbacObject (objecttable) values ('hostsharing');
 | 
					    into RbacObject (objecttable) values ('global');
 | 
				
			||||||
insert
 | 
					insert
 | 
				
			||||||
    into Hostsharing (uuid) values ((select uuid from RbacObject where objectTable = 'hostsharing'));
 | 
					    into Global (uuid, name) values ((select uuid from RbacObject where objectTable = 'global'), 'hostsharing');
 | 
				
			||||||
 | 
					--//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- ============================================================================
 | 
				
			||||||
 | 
					--changeset hs-base-GLOBAL-IDENTITY-VIEW:1 endDelimiter:--//
 | 
				
			||||||
 | 
					-- ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					    Creates a view to the global object table which maps the identifying name to the objectUuid.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					drop view if exists global_iv;
 | 
				
			||||||
 | 
					create or replace view global_iv as
 | 
				
			||||||
 | 
					select distinct target.uuid, target.name as idName
 | 
				
			||||||
 | 
					    from global as target;
 | 
				
			||||||
 | 
					grant all privileges on global_iv to restricted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					    Returns the objectUuid for a given identifying name (in this case the prefix).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					create or replace function globalUuidByIdName(idName varchar)
 | 
				
			||||||
 | 
					    returns uuid
 | 
				
			||||||
 | 
					    language sql
 | 
				
			||||||
 | 
					    strict as $$
 | 
				
			||||||
 | 
					select uuid from global_iv iv where iv.idName = globalUuidByIdName.idName;
 | 
				
			||||||
 | 
					$$;
 | 
				
			||||||
--//
 | 
					--//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- ============================================================================
 | 
					-- ============================================================================
 | 
				
			||||||
@@ -35,12 +60,12 @@ create or replace function hostsharingAdmin()
 | 
				
			|||||||
    returns null on null input
 | 
					    returns null on null input
 | 
				
			||||||
    stable leakproof
 | 
					    stable leakproof
 | 
				
			||||||
    language sql as $$
 | 
					    language sql as $$
 | 
				
			||||||
    select 'global', (select uuid from RbacObject where objectTable = 'hostsharing'), 'admin'::RbacRoleType;
 | 
					select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType;
 | 
				
			||||||
$$;
 | 
					$$;
 | 
				
			||||||
select createRole(hostsharingAdmin());
 | 
					select createRole(hostsharingAdmin());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- ============================================================================
 | 
					-- ============================================================================
 | 
				
			||||||
--changeset hs-base-ADMIN-USERS:1 context:dev endDelimiter:--//
 | 
					--changeset hs-base-ADMIN-USERS:1 context:dev,test,tc endDelimiter:--//
 | 
				
			||||||
-- ----------------------------------------------------------------------------
 | 
					-- ----------------------------------------------------------------------------
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
    Create two users and assign both to the administrators role.
 | 
					    Create two users and assign both to the administrators role.
 | 
				
			||||||
@@ -58,7 +83,7 @@ $$;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- ============================================================================
 | 
					-- ============================================================================
 | 
				
			||||||
--changeset hs-base-hostsharing-TEST:1 context:dev runAlways:true endDelimiter:--//
 | 
					--changeset hs-base-hostsharing-TEST:1 context:dev,test,tc runAlways:true endDelimiter:--//
 | 
				
			||||||
-- ----------------------------------------------------------------------------
 | 
					-- ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -69,16 +94,16 @@ do language plpgsql $$
 | 
				
			|||||||
    declare
 | 
					    declare
 | 
				
			||||||
        userName varchar;
 | 
					        userName varchar;
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
        set local hsadminng.currentUser = 'mike@hostsharing.net';
 | 
					 | 
				
			||||||
        select userName from RbacUser where uuid = currentUserId() into userName;
 | 
					 | 
				
			||||||
        if userName <> 'mike@hostsharing.net' then
 | 
					 | 
				
			||||||
            raise exception 'fetching initial currentUser failed';
 | 
					 | 
				
			||||||
        end if;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        set local hsadminng.currentUser = 'sven@hostsharing.net';
 | 
					        set local hsadminng.currentUser = 'sven@hostsharing.net';
 | 
				
			||||||
        select userName from RbacUser where uuid = currentUserId() into userName;
 | 
					        select userName from RbacUser where uuid = currentUserId() into userName;
 | 
				
			||||||
        if userName <> 'sven@hostsharing.net' then
 | 
					        if userName <> 'sven@hostsharing.net' then
 | 
				
			||||||
            raise exception 'fetching changed currentUser failed';
 | 
					            raise exception 'setting or fetching initial currentUser failed, got: %', userName;
 | 
				
			||||||
 | 
					        end if;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        set local hsadminng.currentUser = 'mike@hostsharing.net';
 | 
				
			||||||
 | 
					        select userName from RbacUser where uuid = currentUserId() into userName;
 | 
				
			||||||
 | 
					        if userName = 'mike@hostsharing.net' then
 | 
				
			||||||
 | 
					            raise exception 'currentUser should not change in one transaction, but did change, got: %', userName;
 | 
				
			||||||
        end if;
 | 
					        end if;
 | 
				
			||||||
    end; $$;
 | 
					    end; $$;
 | 
				
			||||||
--//
 | 
					--//
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,155 @@
 | 
				
			|||||||
 | 
					package net.hostsharing.hsadminng.hscustomer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.hostsharing.hsadminng.context.Context;
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test;
 | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.ComponentScan;
 | 
				
			||||||
 | 
					import org.springframework.orm.jpa.JpaSystemException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.persistence.EntityManager;
 | 
				
			||||||
 | 
					import javax.transaction.Transactional;
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
 | 
					import static org.junit.jupiter.api.Assertions.assertThrows;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@DataJpaTest
 | 
				
			||||||
 | 
					@ComponentScan(basePackageClasses = { Context.class, CustomerRepository.class })
 | 
				
			||||||
 | 
					class CustomerRepositoryIntegrationTest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final static String adminUser = "mike@hostsharing.net";
 | 
				
			||||||
 | 
					    final static String customerAaa = "admin@aaa.example.com";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    Context context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    CustomerRepository customerRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired EntityManager em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void hostsharingAdminWithoutAssumedRoleCanViewAllCustomers() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser(adminUser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final var actual = customerRepository.findAll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThat(actual).hasSize(3)
 | 
				
			||||||
 | 
					            .extracting(CustomerEntity::getPrefix)
 | 
				
			||||||
 | 
					            .containsExactlyInAnyOrder("aaa", "aab", "aac");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void hostsharingAdminWithAssumedHostsharingAdminRoleCanViewAllCustomers() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser(adminUser);
 | 
				
			||||||
 | 
					        context.assumeRoles("global#hostsharing.admin");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final var actual = customerRepository.findAll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThat(actual).hasSize(3)
 | 
				
			||||||
 | 
					            .extracting(CustomerEntity::getPrefix)
 | 
				
			||||||
 | 
					            .containsExactlyInAnyOrder("aaa", "aab", "aac");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void customerAdminWithoutAssumedRoleCanViewItsOwnCustomer() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser(customerAaa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final var actual = customerRepository.findAll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertThat(actual).hasSize(1)
 | 
				
			||||||
 | 
					            .extracting(CustomerEntity::getPrefix)
 | 
				
			||||||
 | 
					            .containsExactly("aaa");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void customerAdminWithAssumedOwnedPackageAdminRoleCanViewItsOwnCustomer() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser(customerAaa);
 | 
				
			||||||
 | 
					        context.assumeRoles("package#aaa00.admin");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final var actual = customerRepository.findAll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					        assertThat(actual).hasSize(1)
 | 
				
			||||||
 | 
					            .extracting(CustomerEntity::getPrefix)
 | 
				
			||||||
 | 
					            .containsExactly("aaa");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void customerAdminWithAssumedAlienPackageAdminRoleCanViewItsOwnCustomer() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser(customerAaa);
 | 
				
			||||||
 | 
					        context.assumeRoles("package#aab00.admin");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final JpaSystemException thrown =
 | 
				
			||||||
 | 
					            assertThrows(JpaSystemException.class, () -> customerRepository.findAll());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					        assertThat(firstRootCauseMessageLineOf(thrown)).matches(
 | 
				
			||||||
 | 
					            ".* user admin@aaa.example.com .* has no permission to assume role package#aab00#admin .*"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void unknownUserWithoutAssumedRoleCannotViewAnyCustomers() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser("unknown@example.org");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final JpaSystemException thrown =
 | 
				
			||||||
 | 
					            assertThrows(JpaSystemException.class, () -> customerRepository.findAll());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					        assertThat(firstRootCauseMessageLineOf(thrown)).matches(
 | 
				
			||||||
 | 
					            ".* user unknown@example.org does not exist.*"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Transactional
 | 
				
			||||||
 | 
					    void unknownUserWithAssumedRoleCannotViewAnyCustomers() {
 | 
				
			||||||
 | 
					        // given
 | 
				
			||||||
 | 
					        context.setCurrentUser("unknown@example.org");
 | 
				
			||||||
 | 
					        assertThat(context.getCurrentUser()).isEqualTo("unknown@example.org");
 | 
				
			||||||
 | 
					        context.assumeRoles("customer#aaa.admin");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // when
 | 
				
			||||||
 | 
					        final JpaSystemException thrown =
 | 
				
			||||||
 | 
					            assertThrows(JpaSystemException.class, () -> customerRepository.findAll());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then
 | 
				
			||||||
 | 
					        assertThat(firstRootCauseMessageLineOf(thrown)).matches(
 | 
				
			||||||
 | 
					            ".* user unknown@example.org does not exist.*"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String firstRootCauseMessageLineOf(final JpaSystemException throwable) {
 | 
				
			||||||
 | 
					        return Optional.ofNullable(throwable.getRootCause())
 | 
				
			||||||
 | 
					            .map(Throwable::getMessage)
 | 
				
			||||||
 | 
					            .map( message -> message.split("\\r|\\n|\\r\\n", 0)[0])
 | 
				
			||||||
 | 
					        .orElse(null);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,7 +4,8 @@ spring:
 | 
				
			|||||||
            platform: postgres
 | 
					            platform: postgres
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    datasource:
 | 
					    datasource:
 | 
				
			||||||
        url: jdbc:tc:postgresql:12.9-alpine:///spring_boot_testcontainers
 | 
					        url: jdbc:tc:postgresql:13.7-bullseye:///spring_boot_testcontainers
 | 
				
			||||||
 | 
					        url-local: jdbc:postgresql://localhost:5432/postgres
 | 
				
			||||||
        username: postgres
 | 
					        username: postgres
 | 
				
			||||||
        password: password
 | 
					        password: password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,11 +24,8 @@ spring:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    liquibase:
 | 
					    liquibase:
 | 
				
			||||||
        change-log: classpath:/db/changelog/db.changelog-master.yaml
 | 
					        change-log: classpath:/db/changelog/db.changelog-master.yaml
 | 
				
			||||||
        contexts: test
 | 
					        contexts: tc,test,dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logging:
 | 
					logging:
 | 
				
			||||||
    level:
 | 
					    level:
 | 
				
			||||||
        liquibase: INFO
 | 
					        liquibase: INFO
 | 
				
			||||||
 | 
					 | 
				
			||||||
liquibase:
 | 
					 | 
				
			||||||
    contexts: dev,tc
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user