IDEMPIERE-5841 AD_Note created by Request causing Cross Tenant (#1991)

This commit is contained in:
hengsin 2023-09-05 16:02:28 +08:00 committed by GitHub
parent 3500070d1e
commit db4f715537
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 10 deletions

View File

@ -13,8 +13,10 @@
*****************************************************************************/ *****************************************************************************/
package org.adempiere.base.event; package org.adempiere.base.event;
import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import org.adempiere.util.ServerContext;
import org.compiere.model.PO; import org.compiere.model.PO;
import org.compiere.process.ProcessInfo; import org.compiere.process.ProcessInfo;
import org.osgi.service.event.Event; import org.osgi.service.event.Event;
@ -33,7 +35,13 @@ public abstract class AbstractEventHandler implements EventHandler {
*/ */
@Override @Override
public void handleEvent(Event event) { public void handleEvent(Event event) {
Properties context = null;
try { try {
if (event.containsProperty(IEventManager.EVENT_CONTEXT)) {
Properties eventContext = (Properties) event.getProperty(IEventManager.EVENT_CONTEXT);
context = ServerContext.getCurrentInstance();
ServerContext.setCurrentInstance(eventContext);
}
doHandleEvent(event); doHandleEvent(event);
} catch (RuntimeException e) { } catch (RuntimeException e) {
addError(event, e); addError(event, e);
@ -47,6 +55,10 @@ public abstract class AbstractEventHandler implements EventHandler {
} catch (Throwable e) { } catch (Throwable e) {
addError(event, e); addError(event, e);
throw new Error(e); throw new Error(e);
} finally {
if (context != null) {
ServerContext.setCurrentInstance(context);
}
} }
} }

View File

@ -20,9 +20,11 @@ import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import org.adempiere.base.BaseActivator; import org.adempiere.base.BaseActivator;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration; import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event; import org.osgi.service.event.Event;
@ -88,6 +90,16 @@ public class EventManager implements IEventManager {
@Override @Override
public boolean postEvent(Event event) { public boolean postEvent(Event event) {
if (eventAdmin != null) { if (eventAdmin != null) {
//copy current session context for restoration in asynchronous event thread
if (!event.containsProperty(EVENT_CONTEXT)) {
Map<String, Object> properties = new HashMap<>();
for (String key : event.getPropertyNames()) {
properties.put(key, event.getProperty(key));
}
properties.put(EVENT_CONTEXT, getCurrentSessionContext());
event = newEvent(event.getTopic(), properties, true);
}
eventAdmin.postEvent(event); eventAdmin.postEvent(event);
return true; return true;
} }
@ -176,20 +188,35 @@ public class EventManager implements IEventManager {
/** /**
* @param topic * @param topic
* @param data * @param data
* @return * @return new Event instance
*/
public static Event newEvent(String topic, Object data) {
return newEvent(topic, data, false);
}
/**
* Create new event instance. If copySessionContext is true, a copy of current session context is added as EVENT_CONTEXT property to event data.
* @param topic
* @param data
* @param copySessionContext true to copy current session context (usually for postEvent).
* @return new Event instance
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static Event newEvent(String topic, Object data) { public static Event newEvent(String topic, Object data, boolean copySessionContext) {
Event event = null; Event event = null;
if (data instanceof Dictionary<?,?>) { if (data instanceof Dictionary<?,?>) {
Dictionary<String,Object>dict = (Dictionary<String,Object>)data; Dictionary<String,Object>dict = (Dictionary<String,Object>)data;
if (dict.get(EVENT_ERROR_MESSAGES) == null) if (dict.get(EVENT_ERROR_MESSAGES) == null)
dict.put(EVENT_ERROR_MESSAGES, new ArrayList<String>()); dict.put(EVENT_ERROR_MESSAGES, new ArrayList<String>());
if (copySessionContext)
dict.put(EVENT_CONTEXT, getCurrentSessionContext());
event = new Event(topic, dict); event = new Event(topic, dict);
} else if (data instanceof Map<?, ?>) { } else if (data instanceof Map<?, ?>) {
Map<String, Object> map = (Map<String, Object>)data; Map<String, Object> map = (Map<String, Object>)data;
if (!map.containsKey(EVENT_ERROR_MESSAGES)) if (!map.containsKey(EVENT_ERROR_MESSAGES))
map.put(EVENT_ERROR_MESSAGES, new ArrayList<String>()); map.put(EVENT_ERROR_MESSAGES, new ArrayList<String>());
if (copySessionContext)
map.put(EVENT_CONTEXT, getCurrentSessionContext());
event = new Event(topic, map); event = new Event(topic, map);
} else { } else {
Map<String, Object> map = new HashMap<String, Object>(3); Map<String, Object> map = new HashMap<String, Object>(3);
@ -197,11 +224,27 @@ public class EventManager implements IEventManager {
if (data != null) if (data != null)
map.put(EVENT_DATA, data); map.put(EVENT_DATA, data);
map.put(EVENT_ERROR_MESSAGES, new ArrayList<String>()); map.put(EVENT_ERROR_MESSAGES, new ArrayList<String>());
if (copySessionContext)
map.put(EVENT_CONTEXT, getCurrentSessionContext());
event = new Event(topic, map); event = new Event(topic, map);
} }
return event; return event;
} }
/**
* @return copy of current session context
*/
private static Properties getCurrentSessionContext() {
Properties context = new Properties();
Env.setContext(context, Env.AD_CLIENT_ID, Env.getAD_Client_ID(Env.getCtx()));
Env.setContext(context, Env.AD_ORG_ID, Env.getAD_Org_ID(Env.getCtx()));
Env.setContext(context, Env.AD_USER_ID, Env.getAD_User_ID(Env.getCtx()));
Env.setContext(context, Env.AD_ROLE_ID, Env.getAD_Role_ID(Env.getCtx()));
Env.setContext(context, Env.M_WAREHOUSE_ID, Env.getContext(Env.getCtx(), Env.M_WAREHOUSE_ID));
Env.setContext(context, Env.LANGUAGE, Env.getContext(Env.getCtx(), Env.LANGUAGE));
return context;
}
/** /**
* *
* @param topic * @param topic

View File

@ -24,6 +24,7 @@ import org.osgi.service.event.EventHandler;
*/ */
public interface IEventManager { public interface IEventManager {
public static final String EVENT_CONTEXT = "event.context";
public static final String EVENT_DATA = "event.data"; public static final String EVENT_DATA = "event.data";
public static final String EVENT_ERROR_MESSAGES = "event.errorMessages"; public static final String EVENT_ERROR_MESSAGES = "event.errorMessages";
public static final String IMPORT_TABLE_NAME_PROPERTY = "importTableName"; public static final String IMPORT_TABLE_NAME_PROPERTY = "importTableName";

View File

@ -369,7 +369,7 @@ public class RequestEventHandler extends AbstractEventHandler implements Managed
|| X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType)) || X_AD_User.NOTIFICATIONTYPE_EMailPlusNotice.equals(NotificationType))
{ {
RequestSendEMailEventData eventData = new RequestSendEMailEventData(client, from, to, subject, message.toString(), pdf, r.getR_Request_ID()); RequestSendEMailEventData eventData = new RequestSendEMailEventData(client, from, to, subject, message.toString(), pdf, r.getR_Request_ID());
Event event = EventManager.newEvent(IEventTopics.REQUEST_SEND_EMAIL, eventData); Event event = EventManager.newEvent(IEventTopics.REQUEST_SEND_EMAIL, eventData, true);
EventManager.getInstance().postEvent(event); EventManager.getInstance().postEvent(event);
} }
// Send Note // Send Note

View File

@ -470,7 +470,7 @@ public class MPInstance extends X_AD_PInstance
public static void postOnChangedEvent(int AD_User_ID) { public static void postOnChangedEvent(int AD_User_ID) {
Map<String, Integer> properties = new HashMap<String, Integer>(); Map<String, Integer> properties = new HashMap<String, Integer>();
properties.put("AD_User_ID", AD_User_ID); properties.put("AD_User_ID", AD_User_ID);
Event event = new Event(ON_RUNNING_JOB_CHANGED_TOPIC, properties); Event event = EventManager.newEvent(ON_RUNNING_JOB_CHANGED_TOPIC, properties, true);
EventManager.getInstance().postEvent(event); EventManager.getInstance().postEvent(event);
} }

View File

@ -275,7 +275,7 @@ public class MRecentItem extends X_AD_RecentItem implements ImmutablePOSupport
public static void postOnChangedEvent(int AD_User_ID) { public static void postOnChangedEvent(int AD_User_ID) {
Map<String, Integer> properties = new HashMap<String, Integer>(); Map<String, Integer> properties = new HashMap<String, Integer>();
properties.put("AD_User_ID", AD_User_ID); properties.put("AD_User_ID", AD_User_ID);
Event event = new Event(ON_RECENT_ITEM_CHANGED_TOPIC, properties); Event event = EventManager.newEvent(ON_RECENT_ITEM_CHANGED_TOPIC, properties, true);
EventManager.getInstance().postEvent(event); EventManager.getInstance().postEvent(event);
} }

View File

@ -2655,7 +2655,7 @@ public abstract class PO
{ {
//post osgi event //post osgi event
String topic = newRecord ? IEventTopics.PO_POST_CREATE : IEventTopics.PO_POST_UPADTE; String topic = newRecord ? IEventTopics.PO_POST_CREATE : IEventTopics.PO_POST_UPADTE;
Event event = EventManager.newEvent(topic, this); Event event = EventManager.newEvent(topic, this, true);
EventManager.getInstance().postEvent(event); EventManager.getInstance().postEvent(event);
if (s_docWFMgr == null) if (s_docWFMgr == null)
@ -4233,7 +4233,7 @@ public abstract class PO
} }
//osgi event handler //osgi event handler
Event event = EventManager.newEvent(IEventTopics.PO_POST_DELETE, this); Event event = EventManager.newEvent(IEventTopics.PO_POST_DELETE, this, true);
EventManager.getInstance().postEvent(event); EventManager.getInstance().postEvent(event);
m_idOld = 0; m_idOld = 0;

View File

@ -128,7 +128,7 @@ public class BroadcastMsgUtil
public void run() { public void run() {
org.osgi.service.event.Event event = EventManager.newEvent( org.osgi.service.event.Event event = EventManager.newEvent(
IEventTopics.BROADCAST_MESSAGE, msg); IEventTopics.BROADCAST_MESSAGE, msg, true);
EventManager.getInstance().postEvent(event); EventManager.getInstance().postEvent(event);
} }
}; };

View File

@ -581,7 +581,7 @@ public class DPCalendar extends DashboardPanel implements EventListener<Event>,
@Override @Override
public void onMessage(Map<String, String> message) { public void onMessage(Map<String, String> message) {
org.osgi.service.event.Event requestChangedEvent = new org.osgi.service.event.Event(ON_REQUEST_CHANGED_TOPIC, message); org.osgi.service.event.Event requestChangedEvent = EventManager.newEvent(ON_REQUEST_CHANGED_TOPIC, message, true);
EventManager.getInstance().postEvent(requestChangedEvent); EventManager.getInstance().postEvent(requestChangedEvent);
} }
@ -635,7 +635,7 @@ public class DPCalendar extends DashboardPanel implements EventListener<Event>,
ITopic<Map<String,String>> topic = service.getTopic(ON_REQUEST_CHANGED_TOPIC); ITopic<Map<String,String>> topic = service.getTopic(ON_REQUEST_CHANGED_TOPIC);
topic.publish(message); topic.publish(message);
} else { } else {
org.osgi.service.event.Event requestChangedEvent = new org.osgi.service.event.Event(ON_REQUEST_CHANGED_TOPIC, message); org.osgi.service.event.Event requestChangedEvent = EventManager.newEvent(ON_REQUEST_CHANGED_TOPIC, message, true);
EventManager.getInstance().postEvent(requestChangedEvent); EventManager.getInstance().postEvent(requestChangedEvent);
} }
} }