IDEMPIERE-5604 Column Encryption is broken in native postgresql (#1752)

This commit is contained in:
Carlos Ruiz 2023-03-25 12:43:43 +01:00 committed by GitHub
parent 45a8e18d32
commit 0dbba5a3c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 23 additions and 116 deletions

View File

@ -25,13 +25,10 @@
**********************************************************************/ **********************************************************************/
package org.compiere.process; package org.compiere.process;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.logging.Level; import java.util.logging.Level;
import org.compiere.db.AdempiereDatabase;
import org.compiere.model.MColumn; import org.compiere.model.MColumn;
import org.compiere.model.MProcessPara; import org.compiere.model.MProcessPara;
import org.compiere.model.MTable; import org.compiere.model.MTable;
@ -40,7 +37,6 @@ import org.compiere.util.CacheMgt;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.DisplayType; import org.compiere.util.DisplayType;
import org.compiere.util.SecureEngine; import org.compiere.util.SecureEngine;
import org.compiere.util.Trx;
/** /**
* Column Encryption Test * Column Encryption Test
@ -65,18 +61,6 @@ public class ColumnEncryption extends SvrProcess {
/** The Column */ /** The Column */
private int p_AD_Column_ID = 0; private int p_AD_Column_ID = 0;
/**
* All the resizing and encrypting database are managed by this
* transaction.
*/
private Trx m_trx;
/**
* All the resizing and encrypting database work goes through this
* connection.
*/
private Connection m_conn;
private int count; private int count;
/** /**
@ -213,25 +197,14 @@ public class ColumnEncryption extends SvrProcess {
// If only user chooses both encrypt the contents and override current // If only user chooses both encrypt the contents and override current
// settings resize the physical column and encrypt all its contents. // settings resize the physical column and encrypt all its contents.
if (p_ChangeSetting && column.isEncrypted() != p_IsEncrypted) { if (p_ChangeSetting && column.isEncrypted() != p_IsEncrypted) {
// Init the transaction and setup the connection.
m_trx = Trx.get(get_TrxName(), true);
if ((m_conn = m_trx.getConnection()) == null) {
log.warning("No connections available");
throw new Exception();
}
m_conn.setAutoCommit(false);
int columnID = column.get_ID(); int columnID = column.get_ID();
MTable table = MTable.get(getCtx(), column.getAD_Table_ID()); MTable table = MTable.get(getCtx(), column.getAD_Table_ID());
String tableName = table.getTableName();
if (p_IsEncrypted) { if (p_IsEncrypted) {
// Check if the encryption exceeds the current length. // Check if the encryption exceeds the current length.
int oldLength = column.getFieldLength(); int oldLength = column.getFieldLength();
int newLength = encryptedColumnLength(oldLength); int newLength = encryptedColumnLength(p_MaxLength > 0 ? p_MaxLength : oldLength);
if (newLength > oldLength) { if (newLength > oldLength) {
if (changeFieldLength(columnID, columnName, newLength, if (changeFieldLength(table, column, newLength) < 0) {
tableName) == -1) {
log.warning("EncryptError [ChangeFieldLength]: " log.warning("EncryptError [ChangeFieldLength]: "
+ "ColumnID=" + columnID + ", NewLength=" + "ColumnID=" + columnID + ", NewLength="
+ newLength); + newLength);
@ -324,10 +297,8 @@ public class ColumnEncryption extends SvrProcess {
ResultSet rs = null; ResultSet rs = null;
try { try {
String selectSqlStr = DB.getDatabase().convertStatement(selectSql.toString()); selectStmt = DB.prepareStatement(selectSql.toString(), get_TrxName());
selectStmt = m_conn.prepareStatement(selectSqlStr, updateStmt = DB.prepareStatement(updateSql.toString(), get_TrxName());
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
updateStmt = m_conn.prepareStatement(updateSql.toString());
rs = selectStmt.executeQuery(); rs = selectStmt.executeQuery();
@ -402,10 +373,8 @@ public class ColumnEncryption extends SvrProcess {
ResultSet rs = null; ResultSet rs = null;
try { try {
String selectSqlStr = DB.getDatabase().convertStatement(selectSql.toString()); selectStmt = DB.prepareStatement(selectSql.toString(), get_TrxName());
selectStmt = m_conn.prepareStatement(selectSqlStr, updateStmt = DB.prepareStatement(updateSql.toString(), get_TrxName());
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
updateStmt = m_conn.prepareStatement(updateSql.toString());
rs = selectStmt.executeQuery(); rs = selectStmt.executeQuery();
@ -452,91 +421,29 @@ public class ColumnEncryption extends SvrProcess {
/** /**
* Change the column length. * Change the column length.
* * @param table the table which owns the column
* @param columnID * @param column the column to be extended
* ID of the column * @param length New length of the column
* @param tableName
* The name of the table which owns the column
* @param length
* New length of the column
* @return The number of rows effected, 1 upon success and -1 for failure. * @return The number of rows effected, 1 upon success and -1 for failure.
* @throws Exception
*/ */
private int changeFieldLength(int columnID, String columnName, int length, private int changeFieldLength(MTable table, MColumn column, int length) throws Exception {
String tableName) throws Exception { column.setFieldLength(length);
int rowsEffected = -1; column.saveEx();
// Select SQL String sql = column.getSQLModify(table, false);
String selectSql = "SELECT FieldLength FROM AD_Column WHERE AD_Column_ID=?"; int no = -1;
if (sql.indexOf(DB.SQLSTATEMENT_SEPARATOR) == -1) {
String dataType = "NVARCHAR2"; no = DB.executeUpdateEx(sql.toString(), get_TrxName());
if (DB.isOracle()) { } else {
Connection conn = Trx.get(get_TrxName(), false).getConnection(); String statements[] = sql.toString().split(DB.SQLSTATEMENT_SEPARATOR);
AdempiereDatabase db = DB.getDatabase(); for (int i = 0; i < statements.length; i++) {
DatabaseMetaData md = conn.getMetaData(); int count = DB.executeUpdateEx(statements[i], get_TrxName());
String catalog = db.getCatalog(); no += count;
String schema = db.getSchema();
ResultSet rs = null;
try {
rs = md.getColumns(catalog, schema, tableName.toUpperCase(), columnName.toUpperCase());
if (rs.next()) {
dataType = rs.getString ("TYPE_NAME");
}
} finally {
DB.close(rs);
} }
} }
// Alter SQL return no;
StringBuilder alterSql = new StringBuilder();
alterSql.append("ALTER TABLE ").append(tableName);
alterSql.append(" MODIFY ").append(columnName);
alterSql.append(" ").append(dataType).append("(");
alterSql.append(length).append(") ");
// Update SQL
StringBuilder updateSql = new StringBuilder();
updateSql.append("UPDATE AD_Column");
updateSql.append(" SET FieldLength=").append(length);
updateSql.append(" WHERE AD_Column_ID=").append(columnID);
PreparedStatement selectStmt = null;
ResultSet rs = null;
try {
selectSql = DB.getDatabase().convertStatement(selectSql);
selectStmt = m_conn.prepareStatement(selectSql,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
selectStmt.setInt(1, columnID);
rs = selectStmt.executeQuery();
if (rs.next()) {
// Change the column size physically.
alterSql = new StringBuilder(DB.getDatabase().convertStatement(alterSql.toString()));
if (DB.executeUpdate(alterSql.toString(), false, m_trx
.getTrxName()) == -1) {
log.severe("EncryptError [ChangeFieldLength]: ColumnID="
+ columnID + ", NewLength=" + length);
throw new Exception();
}
// Change the column size in AD.
updateSql = new StringBuilder(DB.getDatabase().convertStatement(updateSql.toString()));
if (DB.executeUpdate(updateSql.toString(), false, m_trx
.getTrxName()) == -1) {
log.severe("EncryptError [ChangeFieldLength]: ColumnID="
+ columnID + ", NewLength=" + length);
throw new Exception();
}
}
} finally {
DB.close(rs, selectStmt);
}
// Update number of rows effected.
rowsEffected++;
return rowsEffected;
} // changeFieldLength } // changeFieldLength
@Override @Override