diff --git a/api/js/jsapi/egw_app.ts b/api/js/jsapi/egw_app.ts
index 77ad7fb8d9..668badb3fc 100644
--- a/api/js/jsapi/egw_app.ts
+++ b/api/js/jsapi/egw_app.ts
@@ -95,7 +95,7 @@ export abstract class EgwApp
*
*
* @example
Access via etemplate2 object
- * // Instead of this.et2, using it's unique ID
+ * // Instead of this.et2, using its unique ID
* var et2 = etemplate2.getById("myapp-index")
* if(et2)
* {
@@ -255,8 +255,8 @@ export abstract class EgwApp
/**
* Handle a push notification about entry changes from the websocket
*
- * Get's called for data of all apps, but should only handle data of apps it displays,
- * which is by default only it's own, but can be for multiple apps eg. for calendar.
+ * Gets called for data of all apps, but should only handle data of apps it displays,
+ * which is by default only its own, but can be for multiple apps eg. for calendar.
*
* @param pushData
* @param {string} pushData.app application name
@@ -1290,7 +1290,7 @@ export abstract class EgwApp
* the filemanager to link it since we can't link directly.
*
* This doesn't happen automatically. Each application must indicate that
- * it will accept dropped mail by it's nextmatch actions:
+ * it will accept dropped mail by its nextmatch actions:
*
* $actions['info_drop_mail'] = array(
* 'type' => 'drop',
@@ -1512,7 +1512,7 @@ export abstract class EgwApp
/**
* Create backup dialog
* @param {string} _selector DOM selector to attach backupDialog
- * @param {boolean} _initSetup determine wheter it's an initialization backup or restore backup
+ * @param {boolean} _initSetup determine whether it's an initialization backup or restore backup
*
* @returns {Promise.}
*/
diff --git a/filemanager/js/filemanager.ts b/filemanager/js/filemanager.ts
index bf5b855dfd..4a4f7cd923 100644
--- a/filemanager/js/filemanager.ts
+++ b/filemanager/js/filemanager.ts
@@ -11,7 +11,7 @@
/*egw:uses
/api/js/jsapi/egw_app.js;
*/
-import {EgwApp} from "../../api/js/jsapi/egw_app";
+import {EgwApp, PushData} from "../../api/js/jsapi/egw_app";
import {et2_nextmatch} from "../../api/js/etemplate/et2_extension_nextmatch";
import {etemplate2} from "../../api/js/etemplate/etemplate2";
import {Et2Dialog} from "../../api/js/etemplate/Et2Dialog/Et2Dialog";
@@ -28,14 +28,31 @@ import {et2_textbox} from "../../api/js/etemplate/et2_widget_textbox";
*/
export class filemanagerAPP extends EgwApp
{
+ /**
+ * If pushData.acl has fields that can help filter based on ACL grants, list them
+ * here and we can check them and ignore push messages if there is no ACL for that entry.
+ * We don't use fields, but setting this allows our custom check to run.
+ * @protected
+ */
+ protected push_grant_fields : string[] = ['acl'];
+
+ /**
+ * If pushData.acl has fields that can help filter based on current nextmatch filters,
+ * list them here and we can check and ignore push messages if the nextmatch filters do not exclude them.
+ * We only check path, which is the ID, but setting this allows our custom check to run.
+ *
+ * @protected
+ */
+ protected push_filter_fields : string[] = ['id'];
+
/**
* path widget, by template
*/
- path_widget: {} = {};
+ path_widget : {} = {};
/**
* Are files cut into clipboard - need to be deleted at source on paste
*/
- clipboard_is_cut: boolean = false;
+ clipboard_is_cut : boolean = false;
/**
* Regexp to convert id to a path, use this.id2path(_id)
@@ -200,6 +217,40 @@ export class filemanagerAPP extends EgwApp
return state;
}
+ /**
+ * Check grants to see if we can quickly tell if this entry is not for us
+ *
+ * Overridden to check current user and their memberships against pushData.acl, which is a list of account IDs
+ * that should have at least read access.
+ *
+ * @param pushData
+ * @param grant_fields List of fields in pushData.acl with account IDs that might grant access eg: info_responsible
+ * @param appname Optional, to check against the grants for a different application. Defaults to this.appname.
+ *
+ * @return boolean Entry has ACL access
+ */
+ _push_grant_check(pushData : PushData, grant_fields : string[], appname? : string) : boolean
+ {
+ let grants = [this.egw.user("account_id"), ...this.egw.user("memberships")];
+
+ // check user has a something in the pushData ACL list
+ return grants.filter(value => pushData.acl.includes(value)).length > 0;
+ }
+
+ /**
+ * Check pushData path to see if we care about this entry based on current nextmatch path.
+ * This is not a definitive yes or no (the server will tell us when we ask), we just want to cheaply
+ * avoid a server call if we know it won't be in the list.
+ *
+ * @param pushData
+ * @param filter_fields List of filter field names eg: [owner, cat_id]
+ * @return boolean True if the nextmatch filters might include the entry, false if not
+ */
+ _push_field_filter(pushData : PushData, nm : et2_nextmatch, filter_fields : string[]) : boolean
+ {
+ return pushData.id && (pushData.id).startsWith(this.get_path());
+ }
+
/**
* Convert id to path (remove "filemanager::" prefix)
*/