diff --git a/others/db_changes/data_alias/basic/init/struct/AditoBasic/create_ab_loghistory.xml b/others/db_changes/data_alias/basic/init/struct/AditoBasic/create_ab_loghistory.xml new file mode 100644 index 0000000000000000000000000000000000000000..730afa8142bc35226670c692915eebfd0849c3b6 --- /dev/null +++ b/others/db_changes/data_alias/basic/init/struct/AditoBasic/create_ab_loghistory.xml @@ -0,0 +1,24 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="m.kuhn" id="fbe17fba-5bf7-4203-8f6f-01723e07194c"> + <createTable tableName="AB_LOGHISTORY"> + <column name="AB_LOGHISTORYID" type="CHAR(36)"> + <constraints primaryKey="true" primaryKeyName="PK_AB_LOGHISTORY_AB_LOGHISTORYID"/> + </column> + <column name="USER_EDIT" type="NVARCHAR(50)"/> + <column name="USER_NEW" type="NVARCHAR(50)"> + <constraints nullable="false"/> + </column> + <column name="DATE_EDIT" type="TIMESTAMP"/> + <column name="DATE_NEW" type="TIMESTAMP"> + <constraints nullable="false"/> + </column> + <column name="DESCRIPTION" type="LONGVARCHAR(2147483647)"/> + <column name="LOGTYPE" type="CHAR(1)"/> + <column name="SOURCE_TABLENAME" type="NVARCHAR(30)"/> + <column name="SOURCE_TABLENAMEID" type="CHAR(36)"/> + <column name="TABLENAME" type="NVARCHAR(30)"/> + <column name="TABLENAMEID" type="CHAR(36)"/> + </createTable> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/process/Loghistory_lib/Loghistory_lib.aod b/process/Loghistory_lib/Loghistory_lib.aod new file mode 100644 index 0000000000000000000000000000000000000000..a88fbae558bce3d2e5167603a24fad6ada8c344c --- /dev/null +++ b/process/Loghistory_lib/Loghistory_lib.aod @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.0"> + <name>Loghistory_lib</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <process>%aditoprj%/process/Loghistory_lib/process.js</process> + <variants> + <element>LIBRARY</element> + </variants> +</process> diff --git a/process/Loghistory_lib/process.js b/process/Loghistory_lib/process.js new file mode 100644 index 0000000000000000000000000000000000000000..a3079c490e28b519fc8c29f75b80cc9b4a233bd9 --- /dev/null +++ b/process/Loghistory_lib/process.js @@ -0,0 +1,297 @@ +import("system.project"); +import("system.calendars"); +import("system.db"); +import("system.text"); +import("system.datetime"); +import("system.translate"); +import("system.SQLTYPES"); +import("Keyword_lib"); +import("Sql_lib"); +import("Attribute_lib"); +import("Contact_lib"); +import("AddressEntity_lib"); +import("Util_lib"); + +/* +* Saves changes done to db-columns that have been turned on for auditing in the repository into the table AB_LOGHISTORY +* +* @param {String} pTable req TableName +* @param {String} pUser req UserName +* @param {String []} pColumns req ColumnNames +* @param {String []} pNewValues req new Values +* @param {String []} pOldValues req old Values +* @param {Date} pTimeStamp req TimeStamp +* @param {String} pAction req SQLAction +* @param {String} pIdValue req IdValue +* +* @return {} void +*/ + +function logHistory (pTable, pUser, pColumns, pNewValues, pOldValues, pTimeStamp, pAction, pIdValue) +{ + var references = {}; + var columns = {}; + var toLog = false; + + pTable = pTable.toUpperCase(); + pColumns = pColumns.map(function (v){ return v.toUpperCase(); }); + + var Structure = project.getAliasDefinitionStructure("Data_alias", pTable); + if (Structure) + { + columns = Structure.tables[pTable].columns; + for (var column in columns) + { + if (columns[column].tableRef != null) references[column] = {table: columns[column].tableRef, id: ""}; + if (columns[column].primaryKey) primaryKey = column; + if (columns[column].log) toLog = columns[column].log; + } + } + + if (toLog) + { + var idvalue = pIdValue; + var description = []; + var extra = []; + extra["COMMUNICATION"] = { + IDs: ["CONTACT_ID", "MEDIUM_ID"], + RefTable: "CONTACT", + Description: "Kommunikation" + }; + extra["AB_ATTRIBUTERELATION"] = { + IDs: ["OBJECT_ROWID", "AB_ATTRIBUTE_ID"], + Description: "Eigenschaft" + }; + + if (extra[pTable]) + { + var conf = extra[pTable]; + var oldvalues = []; + var newvalues = []; + + for(i = 0; i < pColumns.length; i++ ) + { + if (pAction == 'D' || pAction == 'U') oldvalues[pColumns[i]] = pOldValues[i]; + if (pAction == 'I' || pAction == 'U') newvalues[pColumns[i]] = pNewValues[i]; + } + if (pAction == 'D') newvalues = oldvalues; + if ((pAction == 'D' || pAction == 'I') && newvalues[conf.IDs[1]]) + { + idvalue = newvalues[conf.IDs[0]]; + var data = _getData(pTable, newvalues[conf.IDs[1]], newvalues); + description.push(conf.Description + " " + data[0] + ": '" + data[1] + "'"); + } + if (pAction == 'U') + { + var ids = db.array(db.ROW, "select " + conf.IDs.join(", ") + " from " + pTable + " where " + pTable + "ID = '" + pIdValue + "'"); + idvalue = ids[0]; + var oldid = ids[1]; + if (oldvalues[conf.IDs[1]]) oldid = oldvalues[conf.IDs[1]]; + var olddata = _getData(pTable, oldid, oldvalue); + var newdata = _getData(pTable, ids[1], newvalues); + if (newdata[1] && olddata[1]) + { + if (olddata[0] == newdata[0]) description.push(conf.Description + " " + olddata[0] + " von '" + olddata[1] + "' auf '" + newdata[1] + "' "); + else description.push(conf.Description + " " + olddata[0] + " von '" + olddata[1] + "' auf " + conf.Description + " " + newdata[0] + " '" + newdata[1] + "' "); + } + else if(pTable == "COMMUNICATION") + { + description.push(conf.Description + " Medium von '" + olddata[0] + "' auf '" + newdata[0] + "' "); + } + } + if (conf.RefTable) pTable = conf.RefTable; + } //no extra tables + else + { + if (pTable == "ASYS_CALENDARBACKEND") { + var entrytypePosition = pColumns.indexOf("ENTRYTYPE"); + if (entrytypePosition > -1) if (pNewValues[entrytypePosition] == calendars.VEVENT) return; + } + + for(i = 0; i < pColumns.length; i++ ) + { + if (pTable == "ASYS_CALENDARBACKEND" && pColumns[i] == "VCOMPONENT") _getCalendarDescription(pAction, i, pNewValues, pOldValues); + if (references[pColumns[i]]) + { + if (pAction == "I") references[pColumns[i]].id = pNewValues[i]; + if (pAction == "D") references[pColumns[i]].id = pOldValues[i]; + } + var logfield = columns[pColumns[i]]; + if (logfield && logfield.log) + { + if (pAction != 'I' && pOldValues[i] != "") pOldValues[i] = _getFormattedValue(logfield, pOldValues[i]); + if (pAction != 'D' && pNewValues[i] != "") pNewValues[i] = _getFormattedValue(logfield, pNewValues[i]); + if (pAction == 'U' && pOldValues[i] != pNewValues[i]) + { + let value = pOldValues[i] == "[CLOB]" || pOldValues[i] == "" ? ":" : ": von '" + pOldValues[i]; + description.push(logfield.title + value + "' auf '" + pNewValues[i] + "'"); + } + if (pAction == 'I' && pNewValues[i] != "") description.push(logfield.title + ": '" + pNewValues[i] + "'"); + if (pAction == 'D' && pOldValues[i] != "") description.push(logfield.title + ": '" + pOldValues[i] + "'"); + } + } + if (pAction == "U") + { + for (var index in references) references[index].id = db.cell("select " + index + " from " + pTable + " where " + primaryKey + " = '" + pIdValue + "'"); + } + } + + if (description.length > 0) + { + if (pAction == 'I') description = description.join(", ") + " eingefügt."; + if (pAction == 'U') description = description.join(", ") + " geändert."; + if (pAction == 'D') description = description.join(", ") + " gelöscht."; + var cols = ["LOGTYPE","TABLENAME","TABLENAMEID","DESCRIPTION", "SOURCE_TABLENAME", "SOURCE_TABLENAMEID", "DATE_NEW","USER_NEW"]; + for (index in references) + { + if (references[index].id != "") + { + db.insertData("ASYS_LOGHISTORY", cols, null, [pAction, references[index].table.trim(), references[index].id, description, pTable.trim(), idvalue, pTimeStamp, pUser]); + idvalue = ""; + } + } + if (idvalue != "") db.insertData("ASYS_LOGHISTORY", cols, null, [pAction, pTable.trim(), idvalue, description, "", "", pTimeStamp, pUser]); + } + } +} + +/* +* Creates an Array of AB_LOGHISTORY data for display in a view +* +* @param {String} pCondition req TableName +* +* @return {[]} table +*/ +function showLoghistory(pCondition) +{ + var loglist = db.createEmptyTable(3); + var data = db.table("select DATE_NEW, USER_NEW, DESCRIPTION from ASYS_LOGHISTORY where " + pCondition + " order by DATE_NEW desc"); + + if (data.length > 0) + { + loglist = []; + var groupdate = datetime.toDate(data[0][0], translate.text("dd.MM.yyyy HH:mm")); + var logdate = data[0][0]; + var loguser = data[0][1]; + var descripton = data[0][2]; + + for (var i = 1; i < data.length; i++) + { + if (groupdate + loguser == datetime.toDate(data[i][0], translate.text("dd.MM.yyyy HH:mm")) + data[i][1]) + { + if (descripton != data[i][2]) descripton = data[i][2] + "\n" + descripton; + } + else + { + loglist.push([logdate, loguser, descripton]); + groupdate = datetime.toDate(data[i][0], translate.text("dd.MM.yyyy HH:mm")); + logdate = data[i][0]; + loguser = data[i][1]; + descripton = data[i][2]; + } + } + loglist.push([logdate, loguser, descripton]); + } + return loglist; +} + +/* +* Creates the data for the tables with special cases +* +* @param {String} pTable the table name +* @param {String} pId the table id +* @param {[]} pValues the values +* +* @return {[]} table +*/ +function _getData(pTable, pId, pValues) +{ + var data = []; + //TODO: Attribute_lib + if (pTable == "AB_ATTRIBUTERELATION") data = GetAttrAudit(pId, pValues[getValueFieldName(pId)]); + if (pTable == "COMMUNICATION") + { + data[0] = KeywordUtils.getResolvedTitleSqlPart("MediumOrgPers", pId, false); + data[1] = pValues["ADDR"]; + } + return data; +} + +/* +* Creates an Array of AB_LOGHISTORY data for display in a view +* +* @param {String} pCondition req TableName +* +* @return {[]} table +*/ +function _getFormattedValue(pDescription, pValue) +{ + if (pDescription.keyword != null && pDescription.keyword != "") + { + if (/^(; \d*)*$/.test(pValue)) + { + pValue = text.decodeMS(pValue); + for (let i = 0; i < pValue.length; i++) + { + if (!isNaN(pValue[i])) pValue[i] = getKeyName(pValue[i], pDescription.keyword); + } + pValue = pValue.join(", "); + } + else pValue = getKeyName(pValue, pDescription.keyword); + } + else if (pDescription.translate4Log != null && pDescription.translate4Log != "") + { + var params = { + rowId: pIdValue + ,value: pValue.toString() + ,action: pAction + }; + pValue = evalScript("Loghistory_lib._getFormattedValue", pDescription.translate4Log.replace(/{value}/gi, pValue.toString()), params); + } + else if (pDescription.columnType == String(SQLTYPES.TIMESTAMP)) pValue = datetime.toDate(pValue, "dd.MM.yyyy", "Europe/Berlin"); + else if (pDescription.autoMapTrueFalse4Log) + { + switch (pValue.toLowerCase()) + { + case "true": + case "t": + case "y": + case "1": + pValue = translate.text("Ja"); + break; + case "false": + case "f": + case "n": + case "0": + case "2": + pValue = translate.text("Nein"); + break; + default: + break; + } + } + return pValue; +} + +/* +* Creates the description for changes in the calendar +* +* @param {String} pAction the user action +* @param {String} pId the talbe id +* @param {String} pNewValue the old entry +* @param {String} pOldValue the new entry +* +* @return {String} the description of the action +*/ +function _getCalendarDescription(pAction, pId, pNewValue, pOldValue) +{ + if (pAction != "D") pNewValue[pId] = _getEntry("DESCRIPTION:", pNewValue[pId]); + if (pAction != "I") pOldValue[pId] = _getEntry("DESCRIPTION:", pOldValue[pId]); + + function _getEntry(pWert, pVcomponent) + { + var value = pVcomponent.toString().match(new RegExp(pWert + ".+\r")); + if (value != null) return value.toString().replace(pWert, "").replace(/\\R\\N/g, "\r\n"); + else return ""; + } +} diff --git a/process/process_audit/process.js b/process/process_audit/process.js new file mode 100644 index 0000000000000000000000000000000000000000..7dd2dd289bdaf5fd672c22104c2749f85e5dce55 --- /dev/null +++ b/process/process_audit/process.js @@ -0,0 +1,16 @@ +import("Loghist_lib"); +import("system.vars"); + +var tableName = vars.get("$local.table"); +var id = vars.get("$local.idvalue"); +var columns = vars.get("$local.columns"); +var timestamp = vars.get("$local.timestamp"); +var newvalues = vars.get("$local.values"); +var oldvalues = vars.get("$local.oldvalues"); +var sqlAction = vars.get("$local.action"); +var userLogin = vars.get("$local.user"); + +if (sqlAction != 'X') +{ + logHistory(tableName, userLogin, columns, newvalues, oldvalues, timestamp, sqlAction, id); +} diff --git a/process/process_audit/process_audit.aod b/process/process_audit/process_audit.aod new file mode 100644 index 0000000000000000000000000000000000000000..018d83646b332fa9ffe82a2c4177909a3567df53 --- /dev/null +++ b/process/process_audit/process_audit.aod @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.0"> + <name>process_audit</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <process>%aditoprj%/process/process_audit/process.js</process> +</process>