diff --git a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
index 917242b94f7722685a31a4c77b11822cc46865a9..de090b22a0c999486c279171bd108c1f8c17d1aa 100644
--- a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
@@ -3,8 +3,7 @@ import("system.result");
 import("system.tools");
 import("Util_lib");
 import("Contact_lib");
-
-var filter = vars.exists("$local.filter") && vars.get("$local.filter");
+import("JditoFilter_lib");
 
 var users;
 if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
@@ -28,10 +27,17 @@ users = users.map(function (user)
         user[tools.PARAMS][tools.EMAIL],
         user[tools.DESCRIPTION],
         user[tools.PARAMS][tools.CONTACTID],
-        ContactUtils.getTitleByContactId(user[tools.PARAMS][tools.CONTACTID]), //not good
+        ContactUtils.getTitleByContactId(user[tools.PARAMS][tools.CONTACTID]), //TODO: get the names more efficiently
         user[tools.PARAMS][tools.FRAME_STOREDSEARCHES]
     ];
 });
+
+var filter = vars.exists("$local.filter") && vars.get("$local.filter"); 
+
+//TODO: this is a workaround that filters the records manually, it should be possible to filter the users with a tools.* method
+users = JditoFilterUtils.filterRecords(["UID", "", "ISACTIVE", "FIRSTNAME", "LASTNAME", "EMAIL_ADDRESS", "DESCRIPTION", "CONTACT_ID", "", ], users, filter);
+
+
 ArrayUtils.sort2d(users, 0, true, false); //sort by username
 
 result.object(users);
\ No newline at end of file
diff --git a/process/JditoFilter_lib/JditoFilter_lib.aod b/process/JditoFilter_lib/JditoFilter_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..fcd05c04eec14b76a0b13a8362a146953961c9c0
--- /dev/null
+++ b/process/JditoFilter_lib/JditoFilter_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>JditoFilter_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/JditoFilter_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/JditoFilter_lib/process.js b/process/JditoFilter_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..f0331604c5ae33e3f6778e7ea1cf274dd8e818d8
--- /dev/null
+++ b/process/JditoFilter_lib/process.js
@@ -0,0 +1,111 @@
+
+/**
+ * object for filtering records
+ * 
+ * @param {Array} pColumns the column names
+ * @param {String|Object} pFilter the filter object
+ */
+function JditoFilter (pColumns, pFilter) 
+{
+    var columnMap = {};
+    pColumns.forEach(function (row, i)
+    {
+        columnMap[row] = i;
+    });
+    this._columnMap = columnMap;
+    
+    if (pFilter.length) //check if pFilter is a string
+        pFilter = JSON.parse(pFilter);
+    
+    this._operator = pFilter.operator;
+    this._filters = pFilter.childs;
+}
+
+/**
+ * tests the given row if it matches the filter
+ * 
+ * @param {Array} pRow one record
+ * 
+ * @return {boolean} true, if it matches the condition
+ */
+JditoFilter.prototype.checkRecord = function (pRow)
+{
+    if (this._filters.length == 0)
+        return true;
+    
+    if (this._operator == "AND")
+        return this._filters.every(_testFn, this);
+    
+    return this._filters.some(_testFn, this);
+    
+    function _testFn (pFilter)
+    {
+        let value = pRow[this._columnMap[pFilter.name]];
+        return this._testValue(value, (pFilter.key || pFilter.value), pFilter.operator);
+    }
+}
+
+/**
+ * compares two values with the given operator
+ */
+JditoFilter.prototype._testValue = function (pRowValue, pFilterValue, pOperator)
+{
+    switch (pOperator)
+    {
+        case "CONTAINS":
+            return (new RegExp(pFilterValue)).test(pRowValue);
+        case "CONTAINSNOT":
+            return !(new RegExp(pFilterValue)).test(pRowValue);
+        case "STARTSWITH":
+            return (new RegExp("^" + pFilterValue)).test(pRowValue);
+        case "ENDSWITH":
+            return (new RegExp(pFilterValue + "$")).test(pRowValue);
+        case "EQUAL":
+            return (new RegExp("^" + pFilterValue + "$")).test(pRowValue);
+        case "NOT_EQUAL":
+            return !(new RegExp("^" + pFilterValue + "$")).test(pRowValue);
+        case "LESS":
+            return pRowValue < pFilterValue;
+        case "LESS_OR_EQUAL":
+            return pRowValue <= pFilterValue;
+        case "GREATER":
+            return pRowValue > pFilterValue;
+        case "GREATER_OR_EQUAL":
+            return pRowValue >= pFilterValue;
+        case "ISNULL":
+            return pRowValue == "";
+        case "ISNOTNULL":
+            return pRowValue != "";
+    }
+}
+
+/**
+ * Provides functions for using the filter with jdito recordcontainers
+ * 
+ * Do not instanciate this!
+ * 
+ * @class
+ */
+function JditoFilterUtils () {}
+
+/**
+ * Filters the given records
+ * 
+ * @param {Array} pColumns one dimensional array with all column names, the order has to match the columns of pRecords
+ * @param {Array} pRecords two dimensional array with all records
+ * @param {String|Object} pFilter the value of $local.filter
+ * 
+ * @return {Array} the filtered records
+ */
+JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter)
+{
+    if (!pFilter)
+        return pRecords;
+    
+    var filter = new JditoFilter(pColumns, pFilter);
+    
+    return pRecords.filter(function (row)
+        {
+            return this.checkRecord(row);
+        }, filter);
+}
\ No newline at end of file