[New] Implemented opt-in audit trail in Strolch

The audit trail has its own map on the Realm and a trail is written by
realm at the end of the transaction.

You can write your own audit trail using tx.getAuditTrail().

Enable the audit trail by setting the realm configuration value
'enableAuditTrail'.
This commit is contained in:
Robert von Burg 2014-08-23 20:49:52 +02:00
parent bfc27cebaf
commit 9ca21c29f8
19 changed files with 686 additions and 26 deletions

View File

@ -76,7 +76,7 @@ public class DbSchemaVersionCheck {
String username = connectionInfo.getUsername();
String password = connectionInfo.getPassword();
logger.info(MessageFormat.format("[{0}] Checking Schema version...", realm));
logger.info(MessageFormat.format("[{0}] Checking Schema version for: {1}@{2}", realm, username, url));
try (Connection con = DriverManager.getConnection(url, username, password);
Statement st = con.createStatement();) {
@ -202,5 +202,4 @@ public class DbSchemaVersionCheck {
dropSchema(realm, dbVersion, st);
createSchema(realm, dbVersion, st);
}
}

View File

@ -0,0 +1,326 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.persistence.postgresql;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import li.strolch.model.audit.AccessType;
import li.strolch.model.audit.Audit;
import li.strolch.model.audit.AuditQuery;
import li.strolch.model.audit.AuditVisitor;
import li.strolch.persistence.api.AuditDao;
import li.strolch.persistence.api.StrolchPersistenceException;
import ch.eitchnet.utils.collections.DateRange;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PostgreSqlAuditDao implements AuditDao {
private PostgreSqlStrolchTransaction tx;
/**
* @param postgreSqlStrolchTransaction
*/
public PostgreSqlAuditDao(PostgreSqlStrolchTransaction postgreSqlStrolchTransaction) {
this.tx = postgreSqlStrolchTransaction;
}
@Override
public boolean hasElement(String type, Long id) {
String sql = "select count(*) from audits where element_type = ? and id = ?";
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setLong(2, id);
try (ResultSet result = statement.executeQuery()) {
result.next();
long numberOfElements = result.getLong(1);
if (numberOfElements == 0)
return false;
if (numberOfElements == 1)
return true;
String msg = MessageFormat.format("Non unique number of elements with type {0} and id {1}", type, id);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
}
}
@Override
public long querySize(DateRange dateRange) {
String sql = "select count(*) from audits where date between ? and ?";
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
statement.setDate(1, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
statement.setDate(2, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
try (ResultSet result = statement.executeQuery()) {
result.next();
return result.getLong(1);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
}
}
@Override
public long querySize(String type, DateRange dateRange) {
String sql = "select count(*) from audits where element_type = ? and date between ? and ?";
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setDate(2, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
statement.setDate(3, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
try (ResultSet result = statement.executeQuery()) {
result.next();
return result.getLong(1);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
}
}
@Override
public Set<String> queryTypes() {
Set<String> keySet = new HashSet<>();
String sql = "select distinct element_type from audits";
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
keySet.add(result.getString("element_type"));
}
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
return keySet;
}
@Override
public Audit queryBy(String type, Long id) {
String sql = "select id, username, firstname, lastname, date, element_type, element_accessed, new_version, action, access_type from audits where element_type = ? and id = ?";
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setLong(2, id);
try (ResultSet result = statement.executeQuery()) {
if (!result.next()) {
return null;
}
Audit audit = auditFrom(result);
if (result.next())
throw new StrolchPersistenceException("Non unique result for query: " + sql);
return audit;
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
}
@Override
public List<Audit> queryAll(String type, DateRange dateRange) {
List<Audit> list = new ArrayList<>();
String sql = "select id, username, firstname, lastname, date, element_type, element_accessed, new_version, action, access_type from audits where element_type = ? and date between ? and ?";
try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setDate(2, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
statement.setDate(3, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
list.add(auditFrom(result));
}
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
return list;
}
@Override
public void save(Audit audit) {
String sql = "insert into audits (id, username, firstname, lastname, date, element_type, element_accessed, new_version, action, access_type) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::access_type)";
try (PreparedStatement preparedStatement = tx.getConnection().prepareStatement(sql)) {
setAuditFields(audit, preparedStatement);
int count = preparedStatement.executeUpdate();
if (count != 1) {
throw new StrolchPersistenceException(MessageFormat.format(
"Expected to create 1 record, but created {0} for audit {2}", count, audit.getId()));
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to update Audit {0} due to {1}", audit,
e.getLocalizedMessage()), e);
}
}
@Override
public void saveAll(List<Audit> audits) {
for (Audit audit : audits) {
save(audit);
}
}
@Override
public void update(Audit audit) {
String sql = "update audits set id = ?, username = ?, firstname = ?, lastname = ?, date = ?, element_type = ?, element_accessed = ?, new_version = ?, action = ?, access_type = ?::access_type where id = ?";
try (PreparedStatement preparedStatement = tx.getConnection().prepareStatement(sql)) {
setAuditFields(audit, preparedStatement);
preparedStatement.setLong(11, audit.getId());
int count = preparedStatement.executeUpdate();
if (count != 1) {
throw new StrolchPersistenceException(MessageFormat.format(
"Expected to update 1 record, but updated {0} for audit {2}", count, audit.getId()));
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to update Audit {0} due to {1}", audit,
e.getLocalizedMessage()), e);
}
}
@Override
public void updateAll(List<Audit> audits) {
for (Audit audit : audits) {
update(audit);
}
}
@Override
public void remove(Audit audit) {
String sql = "delete from audits where id = ?";
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
preparedStatement.setLong(1, audit.getId());
int count = preparedStatement.executeUpdate();
if (count != 1) {
String msg = "Expected to delete 1 audit with id {0} but deleted {1} elements!";
msg = MessageFormat.format(msg, audit.getId(), count);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove {0} due to {2}",
audit.getId(), e.getLocalizedMessage()), e);
}
}
@Override
public void removeAll(List<Audit> audits) {
for (Audit audit : audits) {
remove(audit);
}
}
@Override
public long removeAll(String type, DateRange dateRange) {
String sql = "delete from audits where element_type = ? and date between ? and ?";
try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) {
preparedStatement.setString(1, type);
preparedStatement.setDate(2, new Date(dateRange.getFromDate().getTime()), Calendar.getInstance());
preparedStatement.setDate(3, new Date(dateRange.getToDate().getTime()), Calendar.getInstance());
int modCount = preparedStatement.executeUpdate();
return modCount;
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove all elements due to {0}",
e.getLocalizedMessage()), e);
}
}
@Override
public <U> List<U> doQuery(AuditQuery query, AuditVisitor<U> auditVisitor) {
// TODO Auto-generated method stub
return null;
}
private void setAuditFields(Audit audit, PreparedStatement ps) throws SQLException {
// 1 id = ?,
// 2 username = ?,
// 3 firstname = ?,
// 4 lastname = ?,
// 5 date = ?,
// 6 element_type = ?,
// 7 element_accessed = ?,
// 8 new_version = ?,
// 9 action = ?,
// 10 access_type = ?::access_type
ps.setLong(1, audit.getId());
ps.setString(2, audit.getUsername());
ps.setString(3, audit.getFirstname());
ps.setString(4, audit.getLastname());
ps.setDate(5, new Date(audit.getDate().getTime()), Calendar.getInstance());
ps.setString(6, audit.getElementType());
ps.setString(7, audit.getElementAccessed());
if (audit.getNewVersion() == null)
ps.setDate(8, null);
else
ps.setDate(8, new Date(audit.getNewVersion().getTime()), Calendar.getInstance());
ps.setString(9, audit.getAction());
ps.setString(10, audit.getAccessType().name());
}
private Audit auditFrom(ResultSet resultSet) throws SQLException {
Audit audit = new Audit();
audit.setId(resultSet.getLong(1));
audit.setUsername(resultSet.getString(2));
audit.setFirstname(resultSet.getString(3));
audit.setLastname(resultSet.getString(4));
audit.setDate(resultSet.getDate(5));
audit.setElementType(resultSet.getString(6));
audit.setElementAccessed(resultSet.getString(7));
audit.setNewVersion(resultSet.getDate(8));
audit.setAction(resultSet.getString(9));
audit.setAccessType(AccessType.valueOf(resultSet.getString(10)));
return audit;
}
}

View File

@ -29,6 +29,7 @@ import java.util.Set;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
import li.strolch.agent.api.StrolchRealm;
import li.strolch.persistence.api.AuditDao;
import li.strolch.persistence.api.DbConnectionInfo;
import li.strolch.persistence.api.OrderDao;
import li.strolch.persistence.api.PersistenceHandler;
@ -39,6 +40,7 @@ import li.strolch.runtime.StrolchConstants;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.configuration.StrolchConfigurationException;
import li.strolch.runtime.observer.ObserverHandler;
import ch.eitchnet.privilege.model.Certificate;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
@ -128,8 +130,9 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe
super.start();
}
public StrolchTransaction openTx(StrolchRealm realm) {
PostgreSqlStrolchTransaction tx = new PostgreSqlStrolchTransaction(realm, this);
@Override
public StrolchTransaction openTx(StrolchRealm realm, Certificate certificate, String action) {
PostgreSqlStrolchTransaction tx = new PostgreSqlStrolchTransaction(realm, certificate, action, this);
if (getContainer().hasComponent(ObserverHandler.class)) {
tx.setObserverHandler(getContainer().getComponent(ObserverHandler.class));
}
@ -165,4 +168,9 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe
public ResourceDao getResourceDao(StrolchTransaction tx) {
return ((PostgreSqlStrolchTransaction) tx).getResourceDao();
}
@Override
public AuditDao getAuditDao(StrolchTransaction tx) {
return ((PostgreSqlStrolchTransaction) tx).getAuditDao();
}
}

View File

@ -19,6 +19,7 @@ import java.sql.Connection;
import li.strolch.agent.api.StrolchRealm;
import li.strolch.persistence.api.AbstractTransaction;
import li.strolch.persistence.api.AuditDao;
import li.strolch.persistence.api.OrderDao;
import li.strolch.persistence.api.PersistenceHandler;
import li.strolch.persistence.api.ResourceDao;
@ -27,6 +28,8 @@ import li.strolch.persistence.api.TransactionResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.eitchnet.privilege.model.Certificate;
public class PostgreSqlStrolchTransaction extends AbstractTransaction {
private static final Logger logger = LoggerFactory.getLogger(PostgreSqlStrolchTransaction.class);
@ -34,15 +37,17 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
private PostgresqlDao<?> orderDao;
private PostgresqlDao<?> resourceDao;
private AuditDao auditDao;
private Connection connection;
public PostgreSqlStrolchTransaction(StrolchRealm realm, PostgreSqlPersistenceHandler persistenceHandler) {
super(realm);
public PostgreSqlStrolchTransaction(StrolchRealm realm, Certificate certificate, String action,
PostgreSqlPersistenceHandler persistenceHandler) {
super(realm, certificate, action);
this.persistenceHandler = persistenceHandler;
}
@Override
protected void commit(TransactionResult txResult) throws Exception {
protected void writeChanges(TransactionResult txResult) throws Exception {
// first perform DAOs
if (this.orderDao != null)
@ -50,13 +55,7 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
if (this.resourceDao != null)
this.resourceDao.commit(txResult);
// then commit the SQL connection
if (this.connection != null) {
this.connection.commit();
// and close the connection, but not catching, as otherwise we can't rollback in exception case
this.connection.close();
}
// don't commit the connection, this is done in postCommit when we close the connection
}
@Override
@ -74,6 +73,14 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
}
}
@Override
protected void commit() throws Exception {
if (this.connection != null) {
this.connection.commit();
this.connection.close();
}
}
OrderDao getOrderDao() {
if (this.orderDao == null)
this.orderDao = new PostgreSqlOrderDao(this);
@ -86,6 +93,15 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
return (ResourceDao) this.resourceDao;
}
/**
* @return
*/
public AuditDao getAuditDao() {
if (this.auditDao == null)
this.auditDao = new PostgreSqlAuditDao(this);
return (AuditDao) this.auditDao;
}
Connection getConnection() {
if (this.connection == null) {
this.connection = this.persistenceHandler.getConnection(getRealm().getRealm());
@ -97,4 +113,5 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction {
public PersistenceHandler getPersistenceHandler() {
return this.persistenceHandler;
}
}

View File

@ -37,9 +37,6 @@ public abstract class PostgresqlDao<T extends StrolchElement> implements Strolch
protected PostgreSqlStrolchTransaction tx;
protected List<DaoCommand> commands;
/**
* @param tx
*/
public PostgresqlDao(PostgreSqlStrolchTransaction tx) {
this.tx = tx;
this.commands = new ArrayList<>();

View File

@ -0,0 +1,8 @@
DROP TABLE IF EXISTS resources;
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS audits;
DROP TABLE IF EXISTS db_version;
DROP TYPE IF EXISTS order_state;
DROP TYPE IF EXISTS access_type;

View File

@ -0,0 +1,61 @@
-- DB_VERSION
CREATE TABLE IF NOT EXISTS db_version (
id SERIAL PRIMARY KEY,
version varchar(255),
description varchar(255),
created timestamp with time zone
);
-- RESOURCES
CREATE TABLE IF NOT EXISTS resources (
id varchar(255) PRIMARY KEY,
name VARCHAR(255),
type VARCHAR(255),
asxml xml
);
-- ORDERS
CREATE TYPE order_state AS ENUM ('CREATED', 'OPEN', 'EXECUTION', 'CLOSED');
CREATE TABLE IF NOT EXISTS orders (
id varchar(255) PRIMARY KEY,
name VARCHAR(255),
type VARCHAR(255),
state order_state,
date timestamp with time zone,
asxml xml
);
-- AUDITS
CREATE TYPE access_type AS ENUM ('READ', 'CREATE', 'UPDATE', 'DELETE');
CREATE TABLE IF NOT EXISTS audits (
id bigint PRIMARY KEY,
username VARCHAR(255) NOT NULL,
firstname VARCHAR(255) NOT NULL,
lastname VARCHAR(255) NOT NULL,
date timestamp with time zone NOT NULL,
element_type VARCHAR(255) NOT NULL,
element_accessed VARCHAR(255) NOT NULL,
new_version timestamp with time zone,
action VARCHAR(255) NOT NULL,
access_type access_type NOT NULL
);
-- set version
INSERT INTO db_version
(version, description, created)
values(
'0.1.0',
'Initial schema version',
CURRENT_TIMESTAMP
);
INSERT INTO db_version
(version, description, created)
values(
'0.2.0',
'Added new table for audits',
CURRENT_TIMESTAMP
);

View File

@ -1,2 +1,2 @@
# Property file defining what the currently expected version is supposed to be
db_version=0.1.0
db_version=0.2.0

View File

@ -17,6 +17,10 @@ package li.strolch.persistence.postgresql.dao.test;
import static li.strolch.model.ModelGenerator.createOrder;
import static li.strolch.model.ModelGenerator.createResource;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_PASSWORD;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_URL;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_USERNAME;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
import static org.junit.Assert.assertEquals;
import java.io.File;
@ -36,12 +40,14 @@ import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.runtime.StrolchConstants;
import li.strolch.runtime.observer.Observer;
import li.strolch.runtime.observer.ObserverHandler;
import li.strolch.runtime.privilege.PrivilegeHandler;
import li.strolch.testbase.runtime.RuntimeMock;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.*;
import ch.eitchnet.privilege.model.Certificate;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
@ -113,15 +119,18 @@ public class ObserverUpdateTest {
runtimeMock.getContainer().getComponent(ObserverHandler.class).registerObserver(Tags.ORDER, observer);
runtimeMock.getContainer().getComponent(ObserverHandler.class).registerObserver(Tags.RESOURCE, observer);
PrivilegeHandler privilegeHandler = runtimeMock.getAgent().getContainer().getPrivilegeHandler();
Certificate certificate = privilegeHandler.authenticate("test", "test".getBytes());
// create order
Order newOrder = createOrder("MyTestOrder", "Test Name", "TestType", new Date(), State.CREATED); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
try (StrolchTransaction tx = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM).openTx();) {
try (StrolchTransaction tx = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) {
tx.getOrderMap().add(tx, newOrder);
}
// create resource
Resource newResource = createResource("MyTestResource", "Test Name", "TestType"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
try (StrolchTransaction tx = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM).openTx();) {
try (StrolchTransaction tx = runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test");) {
tx.getResourceMap().add(tx, newResource);
}

View File

@ -27,6 +27,7 @@ import li.strolch.agent.impl.DataStoreMode;
import li.strolch.model.ModelGenerator;
import li.strolch.model.Resource;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.runtime.privilege.PrivilegeHandler;
import li.strolch.testbase.runtime.AbstractModelTest;
import li.strolch.testbase.runtime.RuntimeMock;
@ -35,6 +36,8 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ch.eitchnet.privilege.model.Certificate;
public class RealmTest extends AbstractModelTest {
public static final String RUNTIME_PATH = "target/realmtest/"; //$NON-NLS-1$
@ -74,15 +77,18 @@ public class RealmTest extends AbstractModelTest {
String expectedId2 = "@realmTestId2";
String type = "Bla";
PrivilegeHandler privilegeHandler = runtimeMock.getAgent().getContainer().getPrivilegeHandler();
Certificate certificate = privilegeHandler.authenticate("test", "test".getBytes());
{
StrolchRealm firstRealm = runtimeMock.getRealm("first");
assertEquals(DataStoreMode.TRANSACTIONAL, firstRealm.getMode());
Resource expectedRes1 = ModelGenerator.createResource(expectedId1, "Bla bla", type);
try (StrolchTransaction tx = firstRealm.openTx()) {
try (StrolchTransaction tx = firstRealm.openTx(certificate, "test")) {
tx.getResourceMap().add(tx, expectedRes1);
}
try (StrolchTransaction tx = firstRealm.openTx()) {
try (StrolchTransaction tx = firstRealm.openTx(certificate, "test")) {
Resource res = tx.getResourceMap().getBy(tx, type, expectedId1);
assertEquals("Should find object previously added in same realm!", expectedRes1, res);
}
@ -92,11 +98,11 @@ public class RealmTest extends AbstractModelTest {
StrolchRealm secondRealm = runtimeMock.getRealm("second");
assertEquals(DataStoreMode.TRANSACTIONAL, secondRealm.getMode());
Resource expectedRes2 = ModelGenerator.createResource(expectedId2, "Bla bla", type);
try (StrolchTransaction tx = secondRealm.openTx()) {
try (StrolchTransaction tx = secondRealm.openTx(certificate, "test")) {
tx.getResourceMap().add(tx, expectedRes2);
}
try (StrolchTransaction tx = secondRealm.openTx()) {
try (StrolchTransaction tx = secondRealm.openTx(certificate, "test")) {
Resource res = tx.getResourceMap().getBy(tx, type, expectedId2);
assertEquals("Should find object previously added in same realm!", expectedRes2, res);
}
@ -104,7 +110,7 @@ public class RealmTest extends AbstractModelTest {
{
StrolchRealm secondRealm = runtimeMock.getRealm("second");
try (StrolchTransaction tx = secondRealm.openTx()) {
try (StrolchTransaction tx = secondRealm.openTx(certificate, "test")) {
Resource res = tx.getResourceMap().getBy(tx, type, expectedId1);
assertNull("Should not find object added in differenct realm!", res);
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="autoPersistOnPasswordChange" value="true" />
</Parameters>
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<Parameter name="hashAlgorithm" value="SHA-256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="basePath" value="target/strolchRuntime/config" />
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
</Parameters>
</PersistenceHandler>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
</Policies>
</Privilege>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<UsersAndRoles>
<Users>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en_GB</Locale>
<Roles>
<Role>PrivilegeAdmin</Role>
<Role>AppUser</Role>
</Roles>
</User>
</Users>
<Roles>
<Role name="PrivilegeAdmin" />
<Role name="agent">
<Privilege name="li.strolch.agent.impl.StartRealms" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>
</UsersAndRoles>

View File

@ -7,13 +7,23 @@
<verbose>true</verbose>
</Properties>
</Runtime>
<Component>
<name>PrivilegeHandler</name>
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
<Properties>
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
</Properties>
</Component>
<Component>
<name>RealmHandler</name>
<api>li.strolch.agent.api.RealmHandler</api>
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
<depends>PrivilegeHandler</depends>
<depends>PersistenceHandler</depends>
<Properties>
<dataStoreMode>TRANSACTIONAL</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
</Properties>
</Component>
<Component>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="autoPersistOnPasswordChange" value="true" />
</Parameters>
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<Parameter name="hashAlgorithm" value="SHA-256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="basePath" value="target/strolchRuntime/config" />
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
</Parameters>
</PersistenceHandler>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
</Policies>
</Privilege>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<UsersAndRoles>
<Users>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en_GB</Locale>
<Roles>
<Role>PrivilegeAdmin</Role>
<Role>AppUser</Role>
</Roles>
</User>
</Users>
<Roles>
<Role name="PrivilegeAdmin" />
<Role name="agent">
<Privilege name="li.strolch.agent.impl.StartRealms" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>
</UsersAndRoles>

View File

@ -7,15 +7,26 @@
<verbose>true</verbose>
</Properties>
</Runtime>
<Component>
<name>PrivilegeHandler</name>
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
<Properties>
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
</Properties>
</Component>
<Component>
<name>RealmHandler</name>
<api>li.strolch.agent.api.RealmHandler</api>
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
<depends>PrivilegeHandler</depends>
<depends>PersistenceHandler</depends>
<Properties>
<realms>first, second</realms>
<dataStoreMode.first>TRANSACTIONAL</dataStoreMode.first>
<dataStoreMode.second>TRANSACTIONAL</dataStoreMode.second>
<enableAuditTrail.first>true</enableAuditTrail.first>
<enableAuditTrail.second>true</enableAuditTrail.second>
</Properties>
</Component>
<Component>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="autoPersistOnPasswordChange" value="true" />
</Parameters>
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<Parameter name="hashAlgorithm" value="SHA-256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="basePath" value="target/strolchRuntime/config" />
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
</Parameters>
</PersistenceHandler>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
</Policies>
</Privilege>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<UsersAndRoles>
<Users>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en_GB</Locale>
<Roles>
<Role>PrivilegeAdmin</Role>
<Role>AppUser</Role>
</Roles>
</User>
</Users>
<Roles>
<Role name="PrivilegeAdmin" />
<Role name="agent">
<Privilege name="li.strolch.agent.impl.StartRealms" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>
</UsersAndRoles>

View File

@ -7,13 +7,23 @@
<verbose>true</verbose>
</Properties>
</Runtime>
<Component>
<name>PrivilegeHandler</name>
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
<Properties>
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
</Properties>
</Component>
<Component>
<name>RealmHandler</name>
<api>li.strolch.agent.api.RealmHandler</api>
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
<depends>PrivilegeHandler</depends>
<depends>PersistenceHandler</depends>
<Properties>
<dataStoreMode>TRANSACTIONAL</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
</Properties>
</Component>
<Component>