Skip to content

Commit 76f4e3a

Browse files
committed
Feature: #56
Aliases can be switched to read-only. If an Alias is switched to read-only its Sessions are - only allowed to execute SQLs that start with the SELECT keyword, - all functions that change data, e.g. making tables editable, will not be executed. When read-only is active and non-SELECT SQLs are executed or data changing functions are called warnings are displayed in SQuirreL's message panel. See the new check box at the lower left of the Alias dialog.
1 parent a50976f commit 76f4e3a

File tree

25 files changed

+427
-208
lines changed

25 files changed

+427
-208
lines changed

sql12/core/doc/changes.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ Not yet released, available in our GIT repository, snapshots and future releases
66

77
Enhancements:
88

9+
https://github.com/squirrel-sql-client/squirrel-sql-code/issues/56
10+
Aliases can be switched to read-only. If an Alias is switched to read-only its Sessions are
11+
- only allowed to execute SQLs that start with the SELECT keyword,
12+
- all functions that change data, e.g. making tables editable, will not be executed.
13+
When read-only is active and non-SELECT SQLs are executed or data changing functions are called
14+
warnings are displayed in SQuirreL's message panel.
15+
See the new check box at the lower left of the Alias dialog.
16+
917
Upgraded JSQL-Parser (https://github.com/JSQLParser/JSqlParser) to version 5.1.
1018

1119
Look and Feel Plugin: The Look and Feel preferences now allows to adjust several controls,

sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasInternalFrame.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,31 @@
4545
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
4646
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
4747

48-
import javax.swing.*;
49-
import java.awt.*;
48+
import javax.swing.BorderFactory;
49+
import javax.swing.Box;
50+
import javax.swing.JButton;
51+
import javax.swing.JCheckBox;
52+
import javax.swing.JComboBox;
53+
import javax.swing.JInternalFrame;
54+
import javax.swing.JLabel;
55+
import javax.swing.JPanel;
56+
import javax.swing.JSeparator;
57+
import javax.swing.JTextField;
58+
import javax.swing.SwingConstants;
59+
import java.awt.GridBagConstraints;
60+
import java.awt.GridBagLayout;
61+
import java.awt.Insets;
62+
import java.awt.Window;
5063
import java.awt.event.ItemEvent;
5164
import java.awt.event.ItemListener;
5265
import java.io.Serializable;
66+
import java.util.ArrayList;
67+
import java.util.Collections;
68+
import java.util.Comparator;
69+
import java.util.HashMap;
70+
import java.util.Iterator;
5371
import java.util.List;
54-
import java.util.*;
72+
import java.util.Map;
5573

5674
import static net.sourceforge.squirrel_sql.client.preferences.PreferenceType.ALIAS_DEFINITIONS;
5775
/**
@@ -109,6 +127,8 @@ public class AliasInternalFrame extends DialogWidget
109127

110128
private JCheckBox _chkSavePasswordEncrypted = new JCheckBox(SQLAliasPropType.encryptPassword.getI18nString());
111129

130+
private JCheckBox _chkReadOnly = new JCheckBox(SQLAliasPropType.readOnly.getI18nString());
131+
112132
/** Button that brings up the driver properties dialog. */
113133
private final JButton _btnAliasProps = new JButton(s_stringMgr.getString("AliasInternalFrame.props"));
114134
private AliasSheetOkListener _aliasSheetOkListener;
@@ -194,6 +214,7 @@ private void loadData()
194214
_chkAutoLogon.setSelected(_sqlAlias.isAutoLogon());
195215
_chkConnectAtStartup.setSelected(_sqlAlias.isConnectAtStartup());
196216
_chkSavePasswordEncrypted.setSelected(_sqlAlias.isEncryptPassword());
217+
_chkReadOnly.setSelected(_sqlAlias.isReadOnly());
197218
//_useDriverPropsChk.setSelected(_sqlAlias.getUseDriverProperties());
198219

199220
if (_maintType != AliasMaintenanceType.NEW)
@@ -264,6 +285,8 @@ private void applyFromDialog(SQLAlias alias) throws ValidationException
264285
String unencryptedPassword = buf.toString();
265286
AliasPasswordHandler.setPassword(alias, unencryptedPassword);
266287

288+
alias.setReadOnly(_chkReadOnly.isSelected());
289+
267290
alias.setAutoLogon(_chkAutoLogon.isSelected());
268291
alias.setConnectAtStartup(_chkConnectAtStartup.isSelected());
269292
}
@@ -421,19 +444,35 @@ private JPanel createDataEntryPanel()
421444
gbc = new GridBagConstraints(0,6,2,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0);
422445
pnl.add(_chkSavePasswordEncrypted, gbc);
423446

424-
gbc = new GridBagConstraints(1,7,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0);
447+
gbc = new GridBagConstraints(0,7, GridBagConstraints.REMAINDER, 1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0);
425448
_btnAliasProps.setIcon(Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.ALIAS_PROPERTIES));
426449
pnl.add(_btnAliasProps, gbc);
427450

451+
gbc = new GridBagConstraints(0,8,GridBagConstraints.REMAINDER,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0);
452+
pnl.add(getReadOnlyPanel(), gbc);
428453

429454

430455
// make it grow when added
431-
gbc = new GridBagConstraints(0,8,2,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5,5,5,5), 0,0);
456+
gbc = new GridBagConstraints(0,9,2,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5,5,5,5), 0,0);
432457
pnl.add(new JPanel(), gbc);
433458

434459
return pnl;
435460
}
436461

462+
private JPanel getReadOnlyPanel()
463+
{
464+
JPanel ret = new JPanel(new GridBagLayout());
465+
466+
GridBagConstraints gbc;
467+
468+
gbc = new GridBagConstraints(0,0,1,1,0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0);
469+
ret.add(_chkReadOnly, gbc);
470+
471+
gbc = new GridBagConstraints(1,0,1,1,0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2,0,0,0), 0,0);
472+
ret.add(new SmallToolTipInfoButton(s_stringMgr.getString("AliasInternalFrame.readOnly.info")).getButton(), gbc);
473+
return ret;
474+
}
475+
437476
private JPanel createAutoLogonPanel()
438477
{
439478
JPanel ret = new JPanel(new GridBagLayout());

sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/I18NStrings.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ AliasInternalFrame.changealias=Change Alias: {0}
3535

3636
AliasInternalFrame.cleartext=Warning - Passwords are saved in clear text
3737
AliasInternalFrame.password.encrypted=Save password encrypted
38+
AliasInternalFrame.readOnly=Read-only
39+
AliasInternalFrame.readOnly.info=<html>Only SQLs starting with SELECT will be executed.<br>Functions that modify data will not be supported.</html>
40+
3841

3942
AliasInternalFrame.close=Close
4043
AliasInternalFrame.connectatstartup=Connect at application startup

sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/SQLAlias.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,6 @@ public class SQLAlias implements Serializable, Comparable<SQLAlias>, IHasIdentif
4242
{
4343
private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(SQLAlias.class);
4444

45-
private interface IStrings
46-
{
47-
String ERR_BLANK_NAME = s_stringMgr.getString("SQLAlias.error.blankname");
48-
String ERR_BLANK_DRIVER = s_stringMgr.getString("SQLAlias.error.blankdriver");
49-
String ERR_BLANK_URL = s_stringMgr.getString("SQLAlias.error.blankurl");
50-
}
51-
5245
/** The <CODE>IIdentifier</CODE> that uniquely identifies this object. */
5346
private IIdentifier _id;
5447

@@ -94,6 +87,8 @@ private interface IStrings
9487

9588
private long _aliasVersionTimeMills = 0;
9689

90+
private boolean _readOnly;
91+
9792
public SQLAlias()
9893
{
9994
distributeVersioner();
@@ -161,6 +156,7 @@ public void assignFromWithValidationException(SQLAlias sqlAlias, boolean withIde
161156
setUrl(sqlAlias.getUrl());
162157
setUserName(sqlAlias.getUserName());
163158
setEncryptPassword(sqlAlias.isEncryptPassword());
159+
setReadOnly(sqlAlias.isReadOnly());
164160
setPassword(sqlAlias.getPassword()); // Copying of SQL Alias, no need for AliasPasswordHandler.setPassword(...) here.
165161
setAutoLogon(sqlAlias.isAutoLogon());
166162
setUseDriverProperties(sqlAlias.getUseDriverProperties());
@@ -290,6 +286,19 @@ public void setEncryptPassword(boolean b)
290286
_encryptPassword = b;
291287
}
292288

289+
@SQLAliasProp(sqlAliasPropType = SQLAliasPropType.readOnly)
290+
public boolean isReadOnly()
291+
{
292+
return _readOnly;
293+
}
294+
295+
public void setReadOnly(boolean b)
296+
{
297+
_versioner.trigger(_readOnly, b);
298+
_readOnly = b;
299+
}
300+
301+
293302

294303
public long getAliasVersionTimeMills()
295304
{
@@ -372,7 +381,7 @@ public void setName(String name) throws ValidationException
372381
String data = getString(name);
373382
if (data.length() == 0)
374383
{
375-
throw new ValidationException(IStrings.ERR_BLANK_NAME);
384+
throw new ValidationException(s_stringMgr.getString("SQLAlias.error.blankname"));
376385
}
377386
_versioner.trigger(_name, data);
378387
_name = data;
@@ -383,7 +392,7 @@ public void setDriverIdentifier(IIdentifier data)
383392
{
384393
if (data == null)
385394
{
386-
throw new ValidationException(IStrings.ERR_BLANK_DRIVER);
395+
throw new ValidationException(s_stringMgr.getString("SQLAlias.error.blankdriver"));
387396
}
388397
_versioner.trigger(_driverId, data);
389398
_driverId = data;
@@ -394,7 +403,7 @@ public void setUrl(String url) throws ValidationException
394403
String data = getString(url);
395404
if (data.length() == 0)
396405
{
397-
throw new ValidationException(IStrings.ERR_BLANK_URL);
406+
throw new ValidationException(s_stringMgr.getString("SQLAlias.error.blankurl"));
398407
}
399408
_versioner.trigger(_url, data);
400409
_url = data;

sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/SQLAliasBeanInfo.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ interface IPropertyNames
4141
String NAME = "name";
4242
String PASSWORD = "password";
4343
String ENCRYPT_PASSWORD = "encryptPassword"; // Renamed from PasswordEncrypted because of bug #1409
44+
String READ_ONLY = "readOnly";
4445
String URL = "url";
4546
String USE_DRIVER_PROPERTIES = "useDriverProperties";
4647
String ALIAS_VERSION_TIME_MILLIS = "aliasVersionTimeMills";
@@ -73,6 +74,7 @@ public PropertyDescriptor[] getPropertyDescriptors()
7374
new PropertyDescriptor(IPropertyNames.PASSWORD, SQLAlias.class, "getPassword", "setPassword"),
7475
new PropertyDescriptor(IPropertyNames.ENCRYPT_PASSWORD, SQLAlias.class, "isEncryptPassword", "setEncryptPassword"), // Renamed from PasswordEncrypted because of bug #1409
7576
new PropertyDescriptor(IPropertyNames.AUTO_LOGON, SQLAlias.class, "isAutoLogon", "setAutoLogon"),
77+
new PropertyDescriptor(IPropertyNames.READ_ONLY, SQLAlias.class, "isReadOnly", "setReadOnly"),
7678
new PropertyDescriptor(IPropertyNames.CONNECT_AT_STARTUP, SQLAlias.class, "isConnectAtStartup", "setConnectAtStartup"),
7779
new PropertyDescriptor(IPropertyNames.ALIAS_VERSION_TIME_MILLIS, SQLAlias.class, "getAliasVersionTimeMills", "setAliasVersionTimeMills"),
7880
new PropertyDescriptor(IPropertyNames.SCHEMA_PROPERTIES, SQLAlias.class, "getSchemaProperties","setSchemaProperties"),

sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/listholder/AliasListHolder.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ public void load(File aliasesFile)
9191
}
9292
catch (Exception e)
9393
{
94-
e.printStackTrace();
9594
s_log.error(e);
9695
throw Utilities.wrapRuntime(e);
9796
}
@@ -108,7 +107,6 @@ public void save(String path)
108107
}
109108
catch (Exception e)
110109
{
111-
e.printStackTrace();
112110
s_log.error(e);
113111
throw Utilities.wrapRuntime(e);
114112
}

sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/modifyaliases/SQLAliasPropType.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package net.sourceforge.squirrel_sql.client.gui.db.modifyaliases;
22

3-
import java.util.Objects;
4-
53
import net.sourceforge.squirrel_sql.client.gui.db.AliasInternalFrame;
64
import net.sourceforge.squirrel_sql.client.gui.db.SQLAliasSchemaDetailProperties;
75
import net.sourceforge.squirrel_sql.client.gui.db.aliasproperties.ConnectionPropertiesPanel;
@@ -10,6 +8,8 @@
108
import net.sourceforge.squirrel_sql.fw.sql.SQLDriverPropertyCollection;
119
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
1210

11+
import java.util.Objects;
12+
1313
public enum SQLAliasPropType
1414
{
1515
aliasName("AliasInternalFrame.name", AliasInternalFrame.class),
@@ -18,6 +18,7 @@ public enum SQLAliasPropType
1818
userName("AliasInternalFrame.username", AliasInternalFrame.class),
1919
password("AliasInternalFrame.password", AliasInternalFrame.class),
2020
encryptPassword("AliasInternalFrame.password.encrypted", AliasInternalFrame.class),
21+
readOnly("AliasInternalFrame.readOnly", AliasInternalFrame.class),
2122
autoLogon("AliasInternalFrame.autologon", AliasInternalFrame.class),
2223
connectAtStartup("AliasInternalFrame.connectatstartup", AliasInternalFrame.class),
2324
driverProp_useDriverProperties("DriverPropertiesPanel.useDriverProperties", DriverPropertiesPanel.class),

sql12/core/src/net/sourceforge/squirrel_sql/client/session/DataSetUpdateableTableModelImpl.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.sourceforge.squirrel_sql.client.session;
22

3+
import net.sourceforge.squirrel_sql.client.session.mainpanel.sqltypecheck.DataChangesAllowedCheck;
34
import net.sourceforge.squirrel_sql.client.session.properties.EditWhereCols;
45
import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition;
56
import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetUpdateableTableModelListener;
@@ -8,7 +9,11 @@
89
import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.LimitReadLengthFeatureUnstable;
910
import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.IWhereClausePart;
1011
import net.sourceforge.squirrel_sql.fw.dialects.DialectUtils2;
11-
import net.sourceforge.squirrel_sql.fw.sql.*;
12+
import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
13+
import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData;
14+
import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
15+
import net.sourceforge.squirrel_sql.fw.sql.SQLUtilities;
16+
import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo;
1217
import net.sourceforge.squirrel_sql.fw.sql.databasemetadata.SQLDatabaseMetaData;
1318
import net.sourceforge.squirrel_sql.fw.util.StringManager;
1419
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
@@ -17,7 +22,7 @@
1722
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
1823
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
1924

20-
import javax.swing.*;
25+
import javax.swing.JOptionPane;
2126
import java.sql.PreparedStatement;
2227
import java.sql.ResultSet;
2328
import java.sql.SQLException;
@@ -60,8 +65,7 @@ public class DataSetUpdateableTableModelImpl implements IDataSetUpdateableTableM
6065
*/
6166
String sqlOutputClassNameAtTimeOfForcedEdit = "";
6267

63-
private Vector<DataSetUpdateableTableModelListener> _dataSetUpdateableTableModelListener =
64-
new Vector<DataSetUpdateableTableModelListener>();
68+
private Vector<DataSetUpdateableTableModelListener> _dataSetUpdateableTableModelListener = new Vector<>();
6569

6670
/**
6771
* Remember which column contains the rowID; if no rowID, this is -1
@@ -129,16 +133,23 @@ public String getFullTableName()
129133
*/
130134
public void forceEditMode(boolean mode)
131135
{
136+
if(mode == true)
137+
{
138+
if(false == DataChangesAllowedCheck.checkMakeEditableAllowed(_session))
139+
{
140+
return;
141+
}
142+
}
143+
132144
editModeForced = mode;
133-
sqlOutputClassNameAtTimeOfForcedEdit =
134-
_session.getProperties().getTableContentsOutputClassName();
145+
sqlOutputClassNameAtTimeOfForcedEdit = _session.getProperties().getTableContentsOutputClassName();
135146

136147
DataSetUpdateableTableModelListener[] listeners =
137148
_dataSetUpdateableTableModelListener.toArray(new DataSetUpdateableTableModelListener[0]);
138149

139-
for (int i = 0; i < listeners.length; i++)
150+
for(DataSetUpdateableTableModelListener listener : listeners)
140151
{
141-
listeners[i].forceEditMode(mode);
152+
listener.forceEditMode(mode);
142153
}
143154

144155

@@ -168,6 +179,11 @@ public boolean editModeIsForced()
168179
*/
169180
public String getDestinationClassName()
170181
{
182+
if(DataChangesAllowedCheck.isSessionReadOnly(_session))
183+
{
184+
return _session.getProperties().getReadOnlySQLResultsOutputClassName();
185+
}
186+
171187
if (editModeForced)
172188
{
173189
if (_session.getProperties().getTableContentsOutputClassName().equals(

sql12/core/src/net/sourceforge/squirrel_sql/client/session/EditableSqlCheck.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.sourceforge.squirrel_sql.client.session;
22

3+
import net.sourceforge.squirrel_sql.client.session.mainpanel.sqltypecheck.DataChangesAllowedCheck;
34
import net.sourceforge.squirrel_sql.fw.sql.tablenamefind.TableNameFindService;
45

56

@@ -9,6 +10,13 @@ public class EditableSqlCheck
910

1011
public EditableSqlCheck(SQLExecutionInfo exInfo, ISession session)
1112
{
13+
14+
if(DataChangesAllowedCheck.isSessionReadOnly(session))
15+
{
16+
// See also caller of DataChangesAllowedCheck.checkMakeEditableToolbarButton
17+
return;
18+
}
19+
1220
if(null == exInfo || null == exInfo.getSQL())
1321
{
1422
return;

0 commit comments

Comments
 (0)