Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions api/gwtsrc/org/labkey/api/gwt/client/AuditBehaviorType.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,43 @@
*/
package org.labkey.api.gwt.client;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* User: klum
* Date: 10/17/12
*/
public enum AuditBehaviorType
{
NONE("None"),
DETAILED("Detailed"),
SUMMARY("Summary");
NONE("None", 1),
DETAILED("Detailed", 3),
SUMMARY("Summary", 2);

private final String _label;
private final int _priority;

AuditBehaviorType(String label)
AuditBehaviorType(String label, int priority)
{
_label = label;
_priority = priority;
}

public String getLabel()
{
return _label;
}

public int getPriority()
{
return _priority;
}

public static AuditBehaviorType getEffectiveAuditLevel(@Nullable AuditBehaviorType apiOverride, @NotNull AuditBehaviorType tableAuditBehaviorType)
{
if (apiOverride == null || apiOverride._priority < tableAuditBehaviorType._priority)
return tableAuditBehaviorType;

return apiOverride;
}
}
14 changes: 11 additions & 3 deletions api/src/org/labkey/api/audit/AbstractAuditHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ public abstract class AbstractAuditHandler implements AuditHandler

@Override
public void addSummaryAuditEvent(User user, Container c, TableInfo table, QueryService.AuditAction action, Integer dataRowCount, @Nullable AuditBehaviorType auditBehaviorType, @Nullable String userComment)
{
addSummaryAuditEvent(user, c, table, action, dataRowCount, auditBehaviorType, userComment, false);
}

@Override
public void addSummaryAuditEvent(User user, Container c, TableInfo table, QueryService.AuditAction action, Integer dataRowCount, @Nullable AuditBehaviorType auditBehaviorType, @Nullable String userComment, boolean skipAuditLevelCheck)
{
if (table.supportsAuditTracking())
{
AuditConfigurable auditConfigurable = (AuditConfigurable) table;
AuditBehaviorType auditType = auditBehaviorType == null ? auditConfigurable.getAuditBehavior() : auditBehaviorType;
AuditBehaviorType auditType = auditConfigurable.getEffectiveAuditBehavior(auditBehaviorType);

if (auditType == SUMMARY)
if (auditType == SUMMARY || skipAuditLevelCheck)
{
AuditTypeEvent event = createSummaryAuditRecord(user, c, auditConfigurable, action, userComment, dataRowCount, null);

Expand Down Expand Up @@ -68,7 +74,7 @@ public void addAuditEvent(User user, Container c, TableInfo table, @Nullable Aud
if (table.supportsAuditTracking())
{
AuditConfigurable auditConfigurable = (AuditConfigurable)table;
auditType = auditConfigurable.getAuditBehavior(auditType);
auditType = auditConfigurable.getEffectiveAuditBehavior(auditType);

// Truncate audit event doesn't accept any params
if (action == QueryService.AuditAction.TRUNCATE)
Expand Down Expand Up @@ -99,6 +105,8 @@ public void addAuditEvent(User user, Container c, TableInfo table, @Nullable Aud
AuditTypeEvent event = createSummaryAuditRecord(user, c, auditConfigurable, action, userComment, rows.size(), rows.get(0));

AuditLogService.get().addEvent(user, event);

return;
}
case DETAILED:
{
Expand Down
5 changes: 5 additions & 0 deletions api/src/org/labkey/api/audit/AuditHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public interface AuditHandler
{
void addSummaryAuditEvent(User user, Container c, TableInfo table, QueryService.AuditAction action, Integer dataRowCount, @Nullable AuditBehaviorType auditBehaviorType, @Nullable String userComment);

default void addSummaryAuditEvent(User user, Container c, TableInfo table, QueryService.AuditAction action, Integer dataRowCount, @Nullable AuditBehaviorType auditBehaviorType, @Nullable String userComment, boolean skipAuditLevelCheck)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't seem to be any actual usage of the skipAuditLevelCheck. Is this something that can be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used to bypass check for ETL in bulkLoad mode and some other places, it's overriden inAbstractAuditHandler.

{
addSummaryAuditEvent(user, c, table, action, dataRowCount, auditBehaviorType, userComment);
}

void addAuditEvent(User user, Container c, TableInfo table, @Nullable AuditBehaviorType auditType, @Nullable String userComment, QueryService.AuditAction action,
@Nullable List<Map<String, Object>> rows, @Nullable List<Map<String, Object>> existingRows, boolean useTransactionAuditCache);

Expand Down
24 changes: 16 additions & 8 deletions api/src/org/labkey/api/data/AbstractTableInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ public AbstractTableInfo(DbSchema schema, String name)
MemTracker.getInstance().put(this);
}

@NotNull
@Override
public AuditBehaviorType getDefaultAuditBehavior()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This override looks like it just repeats what TableInfo already specifies. Consider removing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, it actually did mean to override. Fixed.

{
return _auditBehaviorType;
}

public void afterConstruct()
{
Expand Down Expand Up @@ -1466,7 +1472,6 @@ else if (xmlColumn.isSetWrappedColumnName() && isNotBlank(xmlColumn.getWrappedCo
catch (QueryParseException qpe)
{
warnings.add(qpe.setFieldName(xmlColumn.getColumnName()));
continue;
}
}

Expand All @@ -1487,7 +1492,16 @@ else if (!calculatedFieldKeys.isEmpty())
if (xmlTable.getAuditLogging() != null)
{
AuditType.Enum auditBehavior = xmlTable.getAuditLogging();
setAuditBehavior(AuditBehaviorType.valueOf(auditBehavior.toString()));
try
{
AuditBehaviorType auditBehaviorType = AuditBehaviorType.valueOf(auditBehavior.toString());
setAuditBehavior(auditBehaviorType);
}
catch (IllegalArgumentException ignore)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Consider logging a warning about an invalid audit behavior argument here. Same for similar usage in SchemaTableInfo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

warnings.add(new QueryParseWarning("Invalid AuditLogging: " + auditBehavior,null,0,0));
}

}

_warnings.addAll(warnings);
Expand Down Expand Up @@ -2000,12 +2014,6 @@ public void setAuditBehavior(AuditBehaviorType type)
_xmlAuditBehaviorType = type;
}

@Override
public AuditBehaviorType getAuditBehavior()
{
return _auditBehaviorType;
}

@Override
public AuditBehaviorType getXmlAuditBehaviorType()
{
Expand Down
21 changes: 17 additions & 4 deletions api/src/org/labkey/api/data/SchemaTableInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.labkey.api.data;

import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.labkey.api.cache.CacheManager;
Expand Down Expand Up @@ -51,6 +52,7 @@
import org.labkey.api.util.StringExpression;
import org.labkey.api.util.StringExpressionFactory;
import org.labkey.api.util.URLHelper;
import org.labkey.api.util.logging.LogHelper;
import org.labkey.api.view.ActionURL;
import org.labkey.api.view.ViewContext;
import org.labkey.data.xml.AuditType;
Expand Down Expand Up @@ -112,6 +114,8 @@ public class SchemaTableInfo implements TableInfo, UpdateableTableInfo, AuditCon

protected boolean _autoLoadMetaData = true; // TODO: Remove this? DatasetSchemaTableInfo is the only user of this.

private static final Logger LOG = LogHelper.getLogger(SchemaTableInfo.class, "TableInfo construction");

public SchemaTableInfo(DbSchema parentSchema, DatabaseTableType tableType, String tableName, String metaDataName, SQLFragment selectName)
{
this(parentSchema, tableType, tableName, metaDataName, selectName, null);
Expand Down Expand Up @@ -527,14 +531,15 @@ public boolean supportsAuditTracking()
}

@Override
public void setAuditBehavior(AuditBehaviorType type)
public void setAuditBehavior(@NotNull AuditBehaviorType type)
{
_auditBehaviorType = type;
_xmlAuditBehaviorType = type;
}

@Override
public AuditBehaviorType getAuditBehavior()
@Override
@NotNull
public AuditBehaviorType getDefaultAuditBehavior()
{
return _auditBehaviorType;
}
Expand Down Expand Up @@ -629,7 +634,15 @@ public void loadTablePropertiesFromXml(TableType xmlTable, boolean dontSetName)
if (xmlTable.getAuditLogging() != null)
{
AuditType.Enum auditBehavior = xmlTable.getAuditLogging();
setAuditBehavior(AuditBehaviorType.valueOf(auditBehavior.toString()));
try
{
AuditBehaviorType auditBehaviorType = AuditBehaviorType.valueOf(auditBehavior.toString());
setAuditBehavior(auditBehaviorType);
}
catch (IllegalArgumentException ignore)
{
LOG.warn("Invalid AuditLogging: " + auditBehavior);
}
}

// Stash so we can overlay ColumnInfo properties later
Expand Down
33 changes: 18 additions & 15 deletions api/src/org/labkey/api/data/TableInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void addAuditEvent(User user, Container c, TableInfo table, @Nullable Aud

default AuditHandler getAuditHandler(@Nullable AuditBehaviorType auditBehaviorOverride)
{
if (!supportsAuditTracking() || auditBehaviorOverride == AuditBehaviorType.NONE || (auditBehaviorOverride == null && getAuditBehavior() == AuditBehaviorType.NONE))
if (!supportsAuditTracking() || getEffectiveAuditBehavior(auditBehaviorOverride) == AuditBehaviorType.NONE)
return new _DoNothingAuditHandler();
return QueryService.get().getDefaultAuditHandler();
}
Expand Down Expand Up @@ -662,43 +662,46 @@ void fireRowTrigger(Container c, User user, TriggerType type, boolean before, in
Set<ColumnInfo> getAllInvolvedColumns(Collection<ColumnInfo> selectColumns);

/** see interface AuditConfigurable */
default AuditBehaviorType getAuditBehavior()
@NotNull
default AuditBehaviorType getDefaultAuditBehavior()
{
return AuditBehaviorType.NONE;
}

@NotNull
default AuditBehaviorType getEffectiveAuditBehavior()
{
return getXmlAuditBehaviorType() == null ? getDefaultAuditBehavior() : getXmlAuditBehaviorType();
}

/**
* Retrieves the audit behavior for this table taking into account, in order of precedence:
* - the setting from the XML file (always returned if there is a value set)
* - the override value provided
* - the setting from the XML file (always returned if there is a value set)
* - the value supplied by this table's implementation
*
* @param overrideValue value used to override the behavior type provided by the table implementation
* @param apiOverride value used to override the behavior type provided by the table implementation
* @return audit behavior for this table
*/
default AuditBehaviorType getAuditBehavior(@Nullable AuditBehaviorType overrideValue)
@NotNull
default AuditBehaviorType getEffectiveAuditBehavior(@Nullable AuditBehaviorType apiOverride)
{
AuditBehaviorType type = getXmlAuditBehaviorType();
if (type != null)
return type;
if (overrideValue != null)
return overrideValue;
return getAuditBehavior();
return AuditBehaviorType.getEffectiveAuditLevel(apiOverride, getEffectiveAuditBehavior());
}

default AuditBehaviorType getAuditBehavior(@Nullable String overrideValue)
default AuditBehaviorType getEffectiveAuditBehavior(@Nullable String apiOverrideValue)
{
if (overrideValue != null)
if (apiOverrideValue != null)
{
try
{
return getAuditBehavior(AuditBehaviorType.valueOf(overrideValue));
return getEffectiveAuditBehavior(AuditBehaviorType.valueOf(apiOverrideValue));
}
catch (IllegalArgumentException ignored)
{
}
}
return getAuditBehavior();
return getEffectiveAuditBehavior();
}

/* Can be used to distinguish AuditBehaviorType.NONE vs absent xml audit config */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ protected DetailedAuditLogDataIterator(DataIterator data, DataIteratorContext co
_auditAction = auditAction;
_auditHandler = table.getAuditHandler(DETAILED);

assert DETAILED == table.getAuditBehavior() || DETAILED == context.getConfigParameter(AuditConfigs.AuditBehavior);
assert DETAILED == table.getEffectiveAuditBehavior((AuditBehaviorType) context.getConfigParameter(AuditConfigs.AuditBehavior));
assert !context.getInsertOption().mergeRows || _data.supportsGetExistingRecord();
assert !context.getConfigParameterBoolean(QueryUpdateService.ConfigParameters.BulkLoad);
assert !context.getConfigParameterBoolean(QueryUpdateService.ConfigParameters.ByPassAudit);

_existingRows = _data.supportsGetExistingRecord() ? new ArrayList<>() : null;
}
Expand Down Expand Up @@ -129,10 +130,10 @@ public static DataIteratorBuilder getDataIteratorBuilder(TableInfo queryTable, @
{
AuditBehaviorType auditType = AuditBehaviorType.NONE;
if (queryTable.supportsAuditTracking())
auditType = queryTable.getAuditBehavior((AuditBehaviorType) context.getConfigParameter(AuditConfigs.AuditBehavior));
auditType = queryTable.getEffectiveAuditBehavior((AuditBehaviorType) context.getConfigParameter(AuditConfigs.AuditBehavior));

// Detailed auditing and not set to bulk load in ETL
if (auditType == DETAILED && !context.getConfigParameterBoolean(QueryUpdateService.ConfigParameters.BulkLoad))
if (auditType == DETAILED && !context.getConfigParameterBoolean(QueryUpdateService.ConfigParameters.BulkLoad) && !context.getConfigParameterBoolean(QueryUpdateService.ConfigParameters.ByPassAudit))
{
DataIterator it = builder.getDataIterator(context);
DataIterator in = DataIteratorUtil.wrapMap(it, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ public static DataIteratorBuilder createBuilder(DataIteratorBuilder dib, TableIn
{
AuditBehaviorType auditType = AuditBehaviorType.NONE;
if (target.supportsAuditTracking())
auditType = target.getAuditBehavior((AuditBehaviorType) context.getConfigParameter(DetailedAuditLogDataIterator.AuditConfigs.AuditBehavior));
auditType = target.getEffectiveAuditBehavior((AuditBehaviorType) context.getConfigParameter(DetailedAuditLogDataIterator.AuditConfigs.AuditBehavior));
boolean detailed = auditType == DETAILED;
if (useGetRows)
return new ExistingDataIteratorsGetRows(new CachingDataIterator(di), target, keys, sharedKeys, context, detailed);
Expand Down
10 changes: 4 additions & 6 deletions api/src/org/labkey/api/exp/query/ExpSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -440,16 +440,14 @@ public Set<SampleTypeService.SampleOperations> getPermittedOps()
*/
public enum DataClassCategoryType
{
registry(null, null),
media(null, null),
sources(AuditBehaviorType.DETAILED, ADDITIONAL_SOURCES_AUDIT_FIELDS);
registry(null),
media(null),
sources(ADDITIONAL_SOURCES_AUDIT_FIELDS);

public final AuditBehaviorType defaultBehavior;
public final Set<String> additionalAuditFields;

DataClassCategoryType(@Nullable AuditBehaviorType defaultBehavior, @Nullable Set<String> addlAuditFields)
DataClassCategoryType(@Nullable Set<String> addlAuditFields)
{
this.defaultBehavior = defaultBehavior;
this.additionalAuditFields = addlAuditFields;
}

Expand Down
8 changes: 5 additions & 3 deletions api/src/org/labkey/api/query/AbstractQueryImportAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,11 @@ public final ApiResponse _execute(FORM form, BindException errors) throws Except

_useAsync = Boolean.valueOf(getParam(Params.useAsync)); // useAsync will save import file to pipeline root as well as run import in a background job

boolean isCrossTypeImport = getOptionParamsMap().getOrDefault(AbstractQueryImportAction.Params.crossTypeImport, false);

// Check first if the audit behavior has been defined for the table either in code or through XML.
// If not defined there, check for the audit behavior defined in the action form (getAuditBehaviorType()).
AuditBehaviorType behaviorType = (_target != null) ? _target.getAuditBehavior(getAuditBehaviorType()) : getAuditBehaviorType();
AuditBehaviorType behaviorType = (_target != null) ? _target.getEffectiveAuditBehavior(getAuditBehaviorType()) : getAuditBehaviorType();

try
{
Expand Down Expand Up @@ -630,8 +632,8 @@ else if (!dataFileDir.exists())
configureLoader(loader);

TransactionAuditProvider.TransactionAuditEvent auditEvent = null;
if (behaviorType != null && behaviorType != AuditBehaviorType.NONE)
auditEvent = createTransactionAuditEvent(getContainer(), QueryService.AuditAction.INSERT);
if (isCrossTypeImport || (behaviorType != null && behaviorType != AuditBehaviorType.NONE))
auditEvent = createTransactionAuditEvent(getContainer(), _insertOption.auditAction);

int rowCount = importData(loader, file, originalName, ve, behaviorType, auditEvent, _auditUserComment);

Expand Down
15 changes: 12 additions & 3 deletions api/src/org/labkey/api/query/AbstractQueryUpdateService.java
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,18 @@ protected int _importRowsUsingDIB(User user, Container container, DataIteratorBu
return 0;
else
{
AuditBehaviorType auditType = (AuditBehaviorType) context.getConfigParameter(DetailedAuditLogDataIterator.AuditConfigs.AuditBehavior);
String auditUserComment = (String) context.getConfigParameter(DetailedAuditLogDataIterator.AuditConfigs.AuditUserComment);
getQueryTable().getAuditHandler(auditType).addSummaryAuditEvent(user, container, getQueryTable(), context.getInsertOption().auditAction, count, auditType, auditUserComment);
if (!context.isCrossTypeImport() && !context.isCrossFolderImport()) // audit handled at table level
{
AuditBehaviorType auditType = (AuditBehaviorType) context.getConfigParameter(DetailedAuditLogDataIterator.AuditConfigs.AuditBehavior);
String auditUserComment = (String) context.getConfigParameter(DetailedAuditLogDataIterator.AuditConfigs.AuditUserComment);
boolean skipAuditLevelCheck = false;
if (context.getConfigParameterBoolean(QueryUpdateService.ConfigParameters.BulkLoad))
{
if (getQueryTable().getEffectiveAuditBehavior(auditType) == AuditBehaviorType.DETAILED) // allow ETL to demote audit level for bulkLoad
skipAuditLevelCheck = true;
}
getQueryTable().getAuditHandler(auditType).addSummaryAuditEvent(user, container, getQueryTable(), context.getInsertOption().auditAction, count, auditType, auditUserComment, skipAuditLevelCheck);
}
return count;
}
}
Expand Down
5 changes: 4 additions & 1 deletion api/src/org/labkey/api/query/FilteredTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ public FilteredTable(@NotNull TableInfo table, @NotNull SchemaType userSchema, @
_importTemplates = _rootTable.getRawImportTemplates();
_buttonBarConfig = BUTTON_BAR_NOT_SET; // lazy copy button bar when asked
if (_rootTable.supportsAuditTracking())
_auditBehaviorType = _rootTable.getAuditBehavior();
{
_auditBehaviorType = _rootTable.getDefaultAuditBehavior();
_xmlAuditBehaviorType = _rootTable.getXmlAuditBehaviorType();
}

// We used to copy the titleColumn from table, but this forced all ColumnInfos to load. Now, delegate
// to _rootTable lazily, allowing overrides.
Expand Down
Loading