diff --git a/migration/iD11/oracle/202407061229_IDEMPIERE-6188.sql b/migration/iD11/oracle/202407061229_IDEMPIERE-6188.sql new file mode 100644 index 0000000000..e1d06a1f6b --- /dev/null +++ b/migration/iD11/oracle/202407061229_IDEMPIERE-6188.sql @@ -0,0 +1,50 @@ +-- IDEMPIERE-6188 Read-Only Session +SELECT register_migration_script('202407061229_IDEMPIERE-6188.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jul 6, 2024, 12:29:56 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203938,0,0,'Y',TO_TIMESTAMP('2024-07-06 12:29:42','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-06 12:29:42','YYYY-MM-DD HH24:MI:SS'),100,'IsReadOnlySession','Read Only Session',NULL,NULL,'Read Only Session','D','6ee179e4-9573-4a3d-8815-23723ef241d7') +; + +-- Jul 6, 2024, 12:30:19 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,IsHtml,IsPartitionKey) VALUES (216614,0,'Read Only Session',200174,'IsReadOnlySession','N',1,'N','N','Y','N','N',0,'N',20,0,0,'Y',TO_TIMESTAMP('2024-07-06 12:30:18','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-06 12:30:18','YYYY-MM-DD HH24:MI:SS'),100,203938,'Y','N','D','N','N','N','Y','8c255baa-fbec-4a90-a43d-5461060368e9','Y',0,'N','N','N','N') +; + +-- Jul 6, 2024, 12:30:29 PM CEST +ALTER TABLE AD_UserPreference ADD IsReadOnlySession CHAR(1) DEFAULT 'N' CHECK (IsReadOnlySession IN ('Y','N')) NOT NULL +; + +-- Jul 6, 2024, 12:30:45 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan) VALUES (208494,'Read Only Session',200189,216614,'Y',1,170,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2024-07-06 12:30:45','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-06 12:30:45','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','f69131e7-4fca-4011-89d5-650ca506c920','Y',170,2,2) +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=110,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206133 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206134 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206407 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=208189 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=150, XPosition=5,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=208494 +; + +-- Jul 6, 2024, 12:31:25 PM CEST +UPDATE AD_Field SET IsQuickEntry='Y',Updated=TO_TIMESTAMP('2024-07-06 12:31:25','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=208494 +; + +-- Jul 9, 2024, 7:48:40 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Read-only session',0,0,'Y',TO_TIMESTAMP('2024-07-09 19:48:39','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-09 19:48:39','YYYY-MM-DD HH24:MI:SS'),100,200900,'ReadOnlySession','D','dc819f55-662d-4d30-b68d-0a93b46a8458') +; + diff --git a/migration/iD11/postgresql/202407061229_IDEMPIERE-6188.sql b/migration/iD11/postgresql/202407061229_IDEMPIERE-6188.sql new file mode 100644 index 0000000000..069052d6ad --- /dev/null +++ b/migration/iD11/postgresql/202407061229_IDEMPIERE-6188.sql @@ -0,0 +1,47 @@ +-- IDEMPIERE-6188 Read-Only Session +SELECT register_migration_script('202407061229_IDEMPIERE-6188.sql') FROM dual; + +-- Jul 6, 2024, 12:29:56 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203938,0,0,'Y',TO_TIMESTAMP('2024-07-06 12:29:42','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-06 12:29:42','YYYY-MM-DD HH24:MI:SS'),100,'IsReadOnlySession','Read Only Session',NULL,NULL,'Read Only Session','D','6ee179e4-9573-4a3d-8815-23723ef241d7') +; + +-- Jul 6, 2024, 12:30:19 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,IsHtml,IsPartitionKey) VALUES (216614,0,'Read Only Session',200174,'IsReadOnlySession','N',1,'N','N','Y','N','N',0,'N',20,0,0,'Y',TO_TIMESTAMP('2024-07-06 12:30:18','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-06 12:30:18','YYYY-MM-DD HH24:MI:SS'),100,203938,'Y','N','D','N','N','N','Y','8c255baa-fbec-4a90-a43d-5461060368e9','Y',0,'N','N','N','N') +; + +-- Jul 6, 2024, 12:30:29 PM CEST +ALTER TABLE AD_UserPreference ADD COLUMN IsReadOnlySession CHAR(1) DEFAULT 'N' CHECK (IsReadOnlySession IN ('Y','N')) NOT NULL +; + +-- Jul 6, 2024, 12:30:45 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan) VALUES (208494,'Read Only Session',200189,216614,'Y',1,170,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2024-07-06 12:30:45','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-06 12:30:45','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','f69131e7-4fca-4011-89d5-650ca506c920','Y',170,2,2) +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=110,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206133 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206134 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206407 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=208189 +; + +-- Jul 6, 2024, 12:31:06 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=150, XPosition=5,Updated=TO_TIMESTAMP('2024-07-06 12:31:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=208494 +; + +-- Jul 6, 2024, 12:31:25 PM CEST +UPDATE AD_Field SET IsQuickEntry='Y',Updated=TO_TIMESTAMP('2024-07-06 12:31:25','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=208494 +; + +-- Jul 9, 2024, 7:48:40 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Read-only session',0,0,'Y',TO_TIMESTAMP('2024-07-09 19:48:39','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2024-07-09 19:48:39','YYYY-MM-DD HH24:MI:SS'),100,200900,'ReadOnlySession','D','dc819f55-662d-4d30-b68d-0a93b46a8458') +; + diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_UserPreference.java b/org.adempiere.base/src/org/compiere/model/I_AD_UserPreference.java index 135b9ca181..d18abe4201 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_UserPreference.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_UserPreference.java @@ -62,21 +62,6 @@ public interface I_AD_UserPreference */ public int getAD_Org_ID(); - /** Column name AD_User_ID */ - public static final String COLUMNNAME_AD_User_ID = "AD_User_ID"; - - /** Set User/Contact. - * User within the system - Internal or Business Partner Contact - */ - public void setAD_User_ID (int AD_User_ID); - - /** Get User/Contact. - * User within the system - Internal or Business Partner Contact - */ - public int getAD_User_ID(); - - public org.compiere.model.I_AD_User getAD_User() throws RuntimeException; - /** Column name AD_UserPreference_ID */ public static final String COLUMNNAME_AD_UserPreference_ID = "AD_UserPreference_ID"; @@ -95,6 +80,21 @@ public interface I_AD_UserPreference /** Get AD_UserPreference_UU */ public String getAD_UserPreference_UU(); + /** Column name AD_User_ID */ + public static final String COLUMNNAME_AD_User_ID = "AD_User_ID"; + + /** Set User/Contact. + * User within the system - Internal or Business Partner Contact + */ + public void setAD_User_ID (int AD_User_ID); + + /** Get User/Contact. + * User within the system - Internal or Business Partner Contact + */ + public int getAD_User_ID(); + + public org.compiere.model.I_AD_User getAD_User() throws RuntimeException; + /** Column name AutoCommit */ public static final String COLUMNNAME_AutoCommit = "AutoCommit"; @@ -104,6 +104,15 @@ public interface I_AD_UserPreference /** Get Automatic Commit */ public boolean isAutoCommit(); + /** Column name AutoNew */ + public static final String COLUMNNAME_AutoNew = "AutoNew"; + + /** Set Automatic New Record */ + public void setAutoNew (boolean AutoNew); + + /** Get Automatic New Record */ + public boolean isAutoNew(); + /** Column name AutomaticDecimalPlacesForAmoun */ public static final String COLUMNNAME_AutomaticDecimalPlacesForAmoun = "AutomaticDecimalPlacesForAmoun"; @@ -117,15 +126,6 @@ public interface I_AD_UserPreference */ public int getAutomaticDecimalPlacesForAmoun(); - /** Column name AutoNew */ - public static final String COLUMNNAME_AutoNew = "AutoNew"; - - /** Set Automatic New Record */ - public void setAutoNew (boolean AutoNew); - - /** Get Automatic New Record */ - public boolean isAutoNew(); - /** Column name Created */ public static final String COLUMNNAME_Created = "Created"; @@ -177,6 +177,15 @@ public interface I_AD_UserPreference /** Get Detailed Zoom Across */ public boolean isDetailedZoomAcross(); + /** Column name IsReadOnlySession */ + public static final String COLUMNNAME_IsReadOnlySession = "IsReadOnlySession"; + + /** Set Read Only Session */ + public void setIsReadOnlySession (boolean IsReadOnlySession); + + /** Get Read Only Session */ + public boolean isReadOnlySession(); + /** Column name IsUseSimilarTo */ public static final String COLUMNNAME_IsUseSimilarTo = "IsUseSimilarTo"; diff --git a/org.adempiere.base/src/org/compiere/model/MGoal.java b/org.adempiere.base/src/org/compiere/model/MGoal.java index 2078e4e928..39111ef953 100644 --- a/org.adempiere.base/src/org/compiere/model/MGoal.java +++ b/org.adempiere.base/src/org/compiere/model/MGoal.java @@ -383,6 +383,8 @@ public class MGoal extends X_PA_Goal public boolean updateGoal(boolean force) { if (log.isLoggable(Level.CONFIG)) log.config("Force=" + force); + if (Env.isReadOnlySession()) + return false; MMeasure measure = MMeasure.get(getPA_Measure_ID()); boolean isUpdateByInterfal = false; diff --git a/org.adempiere.base/src/org/compiere/model/MPInstance.java b/org.adempiere.base/src/org/compiere/model/MPInstance.java index 4f9e80f781..a92b9cc307 100644 --- a/org.adempiere.base/src/org/compiere/model/MPInstance.java +++ b/org.adempiere.base/src/org/compiere/model/MPInstance.java @@ -30,6 +30,7 @@ import java.util.logging.Level; import org.adempiere.base.Core; import org.adempiere.base.event.EventManager; +import org.adempiere.exceptions.AdempiereException; import org.compiere.print.MPrintFormat; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -343,7 +344,10 @@ public class MPInstance extends X_AD_PInstance procMsg.append(proc.get_Translation("Name")).append(" / "); } procMsg.append(proc.getName()).append("]"); - throw new IllegalStateException(Msg.getMsg(getCtx(), "CannotAccessProcess", new Object[] {procMsg.toString(), role.getName()})); + if (Env.isReadOnlySession()) + throw new AdempiereException(Msg.getMsg(getCtx(), "ReadOnlySession")); + else + throw new IllegalStateException(Msg.getMsg(getCtx(), "CannotAccessProcess", new Object[] {procMsg.toString(), role.getName()})); } } super.setAD_Process_ID (AD_Process_ID); diff --git a/org.adempiere.base/src/org/compiere/model/MRole.java b/org.adempiere.base/src/org/compiere/model/MRole.java index ef59a77fc8..efe4261a89 100644 --- a/org.adempiere.base/src/org/compiere/model/MRole.java +++ b/org.adempiere.base/src/org/compiere/model/MRole.java @@ -1673,6 +1673,9 @@ public final class MRole extends X_AD_Role implements ImmutablePOSupport if (log.isLoggable(Level.FINE)) log.fine("#" + m_windowAccess.size()); } // reload Boolean retValue = m_windowAccess.get(AD_Window_ID); + // User Preference window is excluded - otherwise the user would not be able to reset the read-only session preference + if (retValue != null && AD_Window_ID != SystemIDs.WINDOW_USER_PREFERENCE && Env.isReadOnlySession()) + retValue = Boolean.FALSE; if (log.isLoggable(Level.FINE)) log.fine("getWindowAccess - AD_Window_ID=" + AD_Window_ID + " - " + retValue); return retValue; } // getWindowAccess @@ -1765,6 +1768,8 @@ public final class MRole extends X_AD_Role implements ImmutablePOSupport retValue = null; } } + if (retValue != null && Env.isReadOnlySession()) + retValue = Boolean.FALSE; return retValue; } // getProcessAccess @@ -1854,6 +1859,8 @@ public final class MRole extends X_AD_Role implements ImmutablePOSupport retValue = null; } } + if (retValue != null && Env.isReadOnlySession()) + retValue = Boolean.FALSE; return retValue; } // getTaskAccess @@ -1943,6 +1950,8 @@ public final class MRole extends X_AD_Role implements ImmutablePOSupport retValue = null; } } + if (retValue != null && Env.isReadOnlySession()) + retValue = Boolean.FALSE; return retValue; } // getFormAccess @@ -2032,6 +2041,8 @@ public final class MRole extends X_AD_Role implements ImmutablePOSupport retValue = null; } } + if (retValue != null && Env.isReadOnlySession()) + retValue = Boolean.FALSE; return retValue; } // getWorkflowAccess diff --git a/org.adempiere.base/src/org/compiere/model/MUserPreference.java b/org.adempiere.base/src/org/compiere/model/MUserPreference.java index 9016f77ad6..c91e35b557 100644 --- a/org.adempiere.base/src/org/compiere/model/MUserPreference.java +++ b/org.adempiere.base/src/org/compiere/model/MUserPreference.java @@ -28,6 +28,7 @@ package org.compiere.model; import java.sql.ResultSet; import java.util.Properties; +import org.compiere.util.CacheMgt; import org.compiere.util.Env; public class MUserPreference extends X_AD_UserPreference { @@ -124,8 +125,17 @@ public class MUserPreference extends X_AD_UserPreference { @Override protected boolean afterSave(boolean newRecord, boolean success) { - if (success) + if (success) { fillPreferences(); + if (is_ValueChanged(COLUMNNAME_IsReadOnlySession)) { + // Cache reset in same thread + CacheMgt.get().reset(MRole.Table_Name); + // reset cache to re-read the ReadOnly logic + CacheMgt.get().reset(MWindow.Table_Name); + CacheMgt.get().reset(MTab.Table_Name); + CacheMgt.get().reset(MField.Table_Name); + } + } return success; } diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index 3b25eb8544..2f279143ba 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -115,7 +115,7 @@ public abstract class PO /** * */ - private static final long serialVersionUID = 6591172659109078284L; + private static final long serialVersionUID = 3145791881535121558L; /* String key to create a new record based in UUID constructor */ public static final String UUID_NEW_RECORD = ""; @@ -2345,6 +2345,8 @@ public abstract class PO return true; } + if (!checkReadOnlySession()) + return false; checkImmutable(); checkValidContext(); checkCrossTenant(true); @@ -2569,6 +2571,32 @@ public abstract class PO } } // save + + /** + * Tables allowed to be written in a read-only session + */ + final Set ALLOWED_TABLES_IN_RO_SESSION = new HashSet<>(Arrays.asList(new String[] { + "AD_ChangeLog", + "AD_Preference", + "AD_Session", + "AD_UserPreference", + "AD_Wlistbox_Customization" + })); + + /** + * Do not allow saving if in a read-only session, except the allowed tables + * @return + */ + private boolean checkReadOnlySession() { + if (Env.isReadOnlySession()) { + if (! ALLOWED_TABLES_IN_RO_SESSION.contains(get_TableName())) { + log.saveError("Error", Msg.getMsg(getCtx(), "ReadOnlySession") + " [" + get_TableName() + "]"); + return false; + } + } + return true; + } + /** * Update Value or create new record. * @throws AdempiereException @@ -3927,6 +3955,8 @@ public abstract class PO if (is_new()) return true; + if (!checkReadOnlySession()) + return false; checkImmutable(); checkValidContext(); checkCrossTenant(true); diff --git a/org.adempiere.base/src/org/compiere/model/SystemIDs.java b/org.adempiere.base/src/org/compiere/model/SystemIDs.java index f9a30434ef..9a044064f3 100644 --- a/org.adempiere.base/src/org/compiere/model/SystemIDs.java +++ b/org.adempiere.base/src/org/compiere/model/SystemIDs.java @@ -230,6 +230,7 @@ public class SystemIDs public final static int WINDOW_RETURNTOVENDOR = 53098; public final static int WINDOW_SALES_ORDER = 143; public final static int WINDOW_SHIPMENT_CUSTOMER = 169; + public final static int WINDOW_USER_PREFERENCE = 200073; public final static int WINDOW_VENDOR_RMA = 53099; public final static int WINDOW_WAREHOUSE_LOCATOR = 139; public final static int WINDOW_WINDOW_TAB_FIELD = 102; diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_UserPreference.java b/org.adempiere.base/src/org/compiere/model/X_AD_UserPreference.java index bc8de4bc09..fb4babba61 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_UserPreference.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_UserPreference.java @@ -30,7 +30,7 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe /** * */ - private static final long serialVersionUID = 20231222L; + private static final long serialVersionUID = 20240719L; /** Standard Constructor */ public X_AD_UserPreference (Properties ctx, int AD_UserPreference_ID, String trxName) @@ -38,8 +38,10 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe super (ctx, AD_UserPreference_ID, trxName); /** if (AD_UserPreference_ID == 0) { - setAD_User_ID (0); setAD_UserPreference_ID (0); + setAD_User_ID (0); + setIsReadOnlySession (false); +// N setViewFindResult (null); // 0 } */ @@ -51,8 +53,10 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe super (ctx, AD_UserPreference_ID, trxName, virtualColumns); /** if (AD_UserPreference_ID == 0) { - setAD_User_ID (0); setAD_UserPreference_ID (0); + setAD_User_ID (0); + setIsReadOnlySession (false); +// N setViewFindResult (null); // 0 } */ @@ -64,8 +68,10 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe super (ctx, AD_UserPreference_UU, trxName); /** if (AD_UserPreference_UU == null) { - setAD_User_ID (0); setAD_UserPreference_ID (0); + setAD_User_ID (0); + setIsReadOnlySession (false); +// N setViewFindResult (null); // 0 } */ @@ -77,8 +83,10 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe super (ctx, AD_UserPreference_UU, trxName, virtualColumns); /** if (AD_UserPreference_UU == null) { - setAD_User_ID (0); setAD_UserPreference_ID (0); + setAD_User_ID (0); + setIsReadOnlySession (false); +// N setViewFindResult (null); // 0 } */ @@ -112,34 +120,6 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe return sb.toString(); } - public org.compiere.model.I_AD_User getAD_User() throws RuntimeException - { - return (org.compiere.model.I_AD_User)MTable.get(getCtx(), org.compiere.model.I_AD_User.Table_ID) - .getPO(getAD_User_ID(), get_TrxName()); - } - - /** Set User/Contact. - @param AD_User_ID User within the system - Internal or Business Partner Contact - */ - public void setAD_User_ID (int AD_User_ID) - { - if (AD_User_ID < 1) - set_ValueNoCheck (COLUMNNAME_AD_User_ID, null); - else - set_ValueNoCheck (COLUMNNAME_AD_User_ID, Integer.valueOf(AD_User_ID)); - } - - /** Get User/Contact. - @return User within the system - Internal or Business Partner Contact - */ - public int getAD_User_ID() - { - Integer ii = (Integer)get_Value(COLUMNNAME_AD_User_ID); - if (ii == null) - return 0; - return ii.intValue(); - } - /** Set AD_UserPreference_ID. @param AD_UserPreference_ID AD_UserPreference_ID */ @@ -176,6 +156,34 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe return (String)get_Value(COLUMNNAME_AD_UserPreference_UU); } + public org.compiere.model.I_AD_User getAD_User() throws RuntimeException + { + return (org.compiere.model.I_AD_User)MTable.get(getCtx(), org.compiere.model.I_AD_User.Table_ID) + .getPO(getAD_User_ID(), get_TrxName()); + } + + /** Set User/Contact. + @param AD_User_ID User within the system - Internal or Business Partner Contact + */ + public void setAD_User_ID (int AD_User_ID) + { + if (AD_User_ID < 1) + set_ValueNoCheck (COLUMNNAME_AD_User_ID, null); + else + set_ValueNoCheck (COLUMNNAME_AD_User_ID, Integer.valueOf(AD_User_ID)); + } + + /** Get User/Contact. + @return User within the system - Internal or Business Partner Contact + */ + public int getAD_User_ID() + { + Integer ii = (Integer)get_Value(COLUMNNAME_AD_User_ID); + if (ii == null) + return 0; + return ii.intValue(); + } + /** Set Automatic Commit. @param AutoCommit Automatic Commit */ @@ -198,6 +206,28 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe return false; } + /** Set Automatic New Record. + @param AutoNew Automatic New Record + */ + public void setAutoNew (boolean AutoNew) + { + set_Value (COLUMNNAME_AutoNew, Boolean.valueOf(AutoNew)); + } + + /** Get Automatic New Record. + @return Automatic New Record */ + public boolean isAutoNew() + { + Object oo = get_Value(COLUMNNAME_AutoNew); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; + } + /** Set Automatic Decimal Places For Amounts. @param AutomaticDecimalPlacesForAmoun Automatically insert a decimal point */ @@ -217,28 +247,6 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe return ii.intValue(); } - /** Set Automatic New Record. - @param AutoNew Automatic New Record - */ - public void setAutoNew (boolean AutoNew) - { - set_Value (COLUMNNAME_AutoNew, Boolean.valueOf(AutoNew)); - } - - /** Get Automatic New Record. - @return Automatic New Record */ - public boolean isAutoNew() - { - Object oo = get_Value(COLUMNNAME_AutoNew); - if (oo != null) - { - if (oo instanceof Boolean) - return ((Boolean)oo).booleanValue(); - return "Y".equals(oo); - } - return false; - } - /** Set Threshold. @param GridAfterFindThreshold Force grid view when Find panel closes if number of records exceed threshold */ @@ -280,6 +288,28 @@ public class X_AD_UserPreference extends PO implements I_AD_UserPreference, I_Pe return false; } + /** Set Read Only Session. + @param IsReadOnlySession Read Only Session + */ + public void setIsReadOnlySession (boolean IsReadOnlySession) + { + set_Value (COLUMNNAME_IsReadOnlySession, Boolean.valueOf(IsReadOnlySession)); + } + + /** Get Read Only Session. + @return Read Only Session */ + public boolean isReadOnlySession() + { + Object oo = get_Value(COLUMNNAME_IsReadOnlySession); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; + } + /** Set Use Similar To. @param IsUseSimilarTo Use Similar To */ diff --git a/org.adempiere.base/src/org/compiere/util/Env.java b/org.adempiere.base/src/org/compiere/util/Env.java index 3c968a6b5b..c882bce0d6 100644 --- a/org.adempiere.base/src/org/compiere/util/Env.java +++ b/org.adempiere.base/src/org/compiere/util/Env.java @@ -2329,4 +2329,12 @@ public final class Env return false; } + /** + * Is read only session? Based on user preference + * @return + */ + public static boolean isReadOnlySession() { + return "Y".equals(Env.getContext(Env.getCtx(), "IsReadOnlySession")); + } + } // Env \ No newline at end of file diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java index 312313fead..313634d961 100755 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/acct/WAcctViewer.java @@ -752,11 +752,11 @@ public class WAcctViewer extends Window implements EventListener { boolean visible = m_data.documentQuery && tabResult.isSelected(); - bRePost.setVisible(visible); + bRePost.setVisible(visible && !Env.isReadOnlySession()); bExport.setVisible(tabResult.isSelected()); bZoom.setVisible(tabResult.isSelected()); - forcePost.setVisible(visible); + forcePost.setVisible(visible && !Env.isReadOnlySession()); } // stateChanged /** diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/WProcessCtl.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/WProcessCtl.java index 789c5e17a4..cb18febf83 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/WProcessCtl.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/WProcessCtl.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.logging.Level; +import org.adempiere.exceptions.AdempiereException; import org.adempiere.util.IProcessUI; import org.adempiere.webui.ISupportMask; import org.adempiere.webui.LayoutUtils; @@ -91,6 +92,8 @@ public class WProcessCtl extends AbstractProcessCtl { } catch (Exception e) { + if (Env.isReadOnlySession()) + throw new AdempiereException(Msg.getMsg(Env.getCtx(), "ReadOnlySession")); pi.setSummary (e.getLocalizedMessage()); pi.setError (true); log.warning(pi.toString()); @@ -168,6 +171,8 @@ public class WProcessCtl extends AbstractProcessCtl { } catch (Exception e) { + if (Env.isReadOnlySession()) + throw new AdempiereException(Msg.getMsg(Env.getCtx(), "ReadOnlySession")); pi.setSummary (e.getLocalizedMessage()); pi.setError (true); log.warning(pi.toString()); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/CalendarWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/CalendarWindow.java index 4bd07f8d6a..fc1a58d3b7 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/CalendarWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/CalendarWindow.java @@ -314,7 +314,7 @@ public class CalendarWindow extends Window implements EventListener, ITab syncModel(); } } - else if (type.equals(ON_EVENT_CREATE_EVENT)) { + else if (type.equals(ON_EVENT_CREATE_EVENT) && !Env.isReadOnlySession()) { if (e instanceof CalendarsEvent) { CalendarsEvent calendarsEvent = (CalendarsEvent) e; RequestWindow requestWin = new RequestWindow(calendarsEvent, this); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java index 633e61d315..15aaa09f93 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java @@ -222,7 +222,7 @@ public class DPCalendar extends DashboardPanel implements EventListener, else if (e.getTarget() == divArrowRight) divArrowClicked(true); } - else if (type.equals(ON_EVENT_CREATE_EVENT)) { + else if (type.equals(ON_EVENT_CREATE_EVENT) && ! Env.isReadOnlySession()) { if (e instanceof CalendarsEvent) { CalendarsEvent calendarsEvent = (CalendarsEvent) e; RequestWindow requestWin = new RequestWindow(calendarsEvent, this);