Skip to content

Commit 8d70235

Browse files
committed
add preference to clear sensitive data after days
1 parent fd664d1 commit 8d70235

File tree

8 files changed

+86
-17
lines changed

8 files changed

+86
-17
lines changed

core/src/main/java/haveno/core/api/CoreTradesService.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ void closeTrade(String tradeId) {
189189
verifyTradeIsNotClosed(tradeId);
190190
var trade = getOpenTrade(tradeId).orElseThrow(() ->
191191
new IllegalArgumentException(format("trade with id '%s' not found", tradeId)));
192-
log.info("Keeping funds received from trade {}", tradeId);
193192
tradeManager.onTradeCompleted(trade);
194193
}
195194

core/src/main/java/haveno/core/trade/Contract.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -261,18 +261,12 @@ public boolean isMyRoleMaker(PubKeyRing myPubKeyRing) {
261261
}
262262

263263
public boolean maybeClearSensitiveData() {
264-
return false; // TODO: anything to clear?
264+
return false; // nothing to clear
265265
}
266266

267267
// edits a contract json string
268268
public static String sanitizeContractAsJson(String contractAsJson) {
269-
return contractAsJson
270-
.replaceAll(
271-
"\"takerPaymentAccountPayload\": \\{[^}]*}",
272-
"\"takerPaymentAccountPayload\": null")
273-
.replaceAll(
274-
"\"makerPaymentAccountPayload\": \\{[^}]*}",
275-
"\"makerPaymentAccountPayload\": null");
269+
return contractAsJson; // nothing to sanitize because the contract does not contain the payment account payloads
276270
}
277271

278272
public void printDiff(@Nullable String peersContractAsJson) {

core/src/main/java/haveno/core/trade/Trade.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1584,11 +1584,24 @@ private void clearProcessData() {
15841584

15851585
public void maybeClearSensitiveData() {
15861586
String change = "";
1587+
if (contract != null && contract.maybeClearSensitiveData()) {
1588+
change += "contract;";
1589+
}
1590+
if (processModel != null && processModel.maybeClearSensitiveData()) {
1591+
change += "processModel;";
1592+
}
1593+
if (contractAsJson != null) {
1594+
String edited = Contract.sanitizeContractAsJson(contractAsJson);
1595+
if (!edited.equals(contractAsJson)) {
1596+
contractAsJson = edited;
1597+
change += "contractAsJson;";
1598+
}
1599+
}
15871600
if (removeAllChatMessages()) {
15881601
change += "chat messages;";
15891602
}
15901603
if (change.length() > 0) {
1591-
log.info("cleared sensitive data from {} of trade {}", change, getShortId());
1604+
log.info("Cleared sensitive data from {} of {} {}", change, getClass().getSimpleName(), getShortId());
15921605
}
15931606
}
15941607

core/src/main/java/haveno/core/trade/protocol/ProcessModel.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,17 @@ void witnessDebugLog(Trade trade) {
326326
getAccountAgeWitnessService().getAccountAgeWitnessUtils().witnessDebugLog(trade, null);
327327
}
328328

329+
public boolean maybeClearSensitiveData() {
330+
boolean changed = false;
331+
for (TradePeer tradingPeer : getTradePeers()) {
332+
if (tradingPeer.getPaymentAccountPayload() != null || tradingPeer.getContractAsJson() != null) {
333+
tradingPeer.setPaymentAccountPayload(null);
334+
tradingPeer.setContractAsJson(null);
335+
changed = true;
336+
}
337+
}
338+
return changed;
339+
}
329340

330341
///////////////////////////////////////////////////////////////////////////////////////////
331342
// Delegates

core/src/main/java/haveno/core/user/Preferences.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ public boolean isUseTorForXmr() {
109109
));
110110

111111
public static final boolean USE_SYMMETRIC_SECURITY_DEPOSIT = true;
112-
public static final int CLEAR_DATA_AFTER_DAYS_INITIAL = 99999; // feature effectively disabled until user agrees to settings notification
113-
public static final int CLEAR_DATA_AFTER_DAYS_DEFAULT = 60; // used when user has agreed to settings notification
112+
public static final int CLEAR_DATA_AFTER_DAYS_DEFAULT = 60; // used with new instance or when existing user has agreed to settings notification
113+
public static final int CLEAR_DATA_AFTER_DAYS_DISABLED = 99999; // feature effectively disabled until existing user agrees to settings notification
114114

115115

116116
// payload is initialized so the default values are available for Property initialization.
@@ -309,6 +309,10 @@ private void setupPreferences() {
309309
setIgnoreDustThreshold(600);
310310
}
311311

312+
if (prefPayload.getClearDataAfterDays() < 1) {
313+
setClearDataAfterDays(Preferences.CLEAR_DATA_AFTER_DAYS_DISABLED);
314+
}
315+
312316
// For users from old versions the 4 flags a false but we want to have it true by default
313317
// PhoneKeyAndToken is also null so we can use that to enable the flags
314318
if (prefPayload.getPhoneKeyAndToken() == null) {

core/src/main/java/haveno/core/user/PreferencesPayload.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
122122
private String takeOfferSelectedPaymentAccountId;
123123
private double securityDepositAsPercent = getDefaultSecurityDepositAsPercent();
124124
private int ignoreDustThreshold = 600;
125-
private int clearDataAfterDays = Preferences.CLEAR_DATA_AFTER_DAYS_INITIAL;
125+
private int clearDataAfterDays = Preferences.CLEAR_DATA_AFTER_DAYS_DISABLED;
126126
private double securityDepositAsPercentForCrypto = getDefaultSecurityDepositAsPercent();
127127
private int blockNotifyPort;
128128
private boolean tacAcceptedV120;

core/src/main/resources/i18n/displayStrings.properties

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,7 @@ setting.preferences.notifyOnPreRelease=Receive pre-release notifications
13371337
setting.preferences.resetAllFlags=Reset all \"Don't show again\" flags
13381338
settings.preferences.languageChange=To apply the language change to all screens requires a restart.
13391339
settings.preferences.supportLanguageWarning=In case of a dispute, please note that arbitration is handled in {0}.
1340+
setting.preferences.clearDataAfterDays=Clear sensitive data after (days)
13401341
settings.preferences.editCustomExplorer.headline=Explorer Settings
13411342
settings.preferences.editCustomExplorer.description=Choose a system defined explorer from the list on the left, and/or \
13421343
customize to suit your own preferences.
@@ -1346,6 +1347,15 @@ settings.preferences.editCustomExplorer.name=Name
13461347
settings.preferences.editCustomExplorer.txUrl=Transaction URL
13471348
settings.preferences.editCustomExplorer.addressUrl=Address URL
13481349

1350+
setting.info.headline=New data-privacy feature
1351+
settings.preferences.sensitiveDataRemoval.msg=To protect the privacy of yourself and other traders, Haveno intends to \
1352+
remove sensitive data from old trades. This is particularly important for fiat trades which may include bank \
1353+
account details.\n\n\
1354+
The threshold for data removal can be configured on this screen via the field "Clear sensitive data after (days)". \
1355+
It is recommended to set it as low as possible, for example 60 days. That means trades from more than 60 \
1356+
days ago will have sensitive data cleared, as long as they are completed. Completed trades are found in the \
1357+
Portfolio / History tab.
1358+
13491359
settings.net.xmrHeader=Monero network
13501360
settings.net.p2pHeader=Haveno network
13511361
settings.net.onionAddressLabel=My onion address

desktop/src/main/java/haveno/desktop/main/settings/preferences/PreferencesView.java

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import haveno.core.payment.payload.PaymentMethod;
4040
import haveno.core.payment.validation.XmrValidator;
4141
import haveno.core.trade.HavenoUtils;
42+
import haveno.core.user.DontShowAgainLookup;
4243
import haveno.core.user.Preferences;
4344
import haveno.core.user.User;
4445
import haveno.core.util.FormattingUtils;
@@ -111,7 +112,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
111112
private int gridRow = 0;
112113
private int displayCurrenciesGridRowIndex = 0;
113114
private InputTextField ignoreTradersListInputTextField,
114-
autoConfRequiredConfirmationsTf, autoConfServiceAddressTf, autoConfTradeLimitTf, /*referralIdInputTextField,*/
115+
autoConfRequiredConfirmationsTf, autoConfServiceAddressTf, autoConfTradeLimitTf, clearDataAfterDaysInputTextField,
115116
rpcUserTextField, blockNotifyPortTextField;
116117
private PasswordTextField rpcPwTextField;
117118

@@ -135,7 +136,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
135136
private ObservableList<TradeCurrency> tradeCurrencies;
136137
private InputTextField deviationInputTextField;
137138
private ChangeListener<String> deviationListener, ignoreTradersListListener,
138-
rpcUserListener, rpcPwListener, blockNotifyPortListener,
139+
rpcUserListener, rpcPwListener, blockNotifyPortListener, clearDataAfterDaysListener,
139140
autoConfTradeLimitListener, autoConfServiceAddressListener;
140141
private ChangeListener<Boolean> deviationFocusedListener;
141142
private final boolean displayStandbyModeFeature;
@@ -184,6 +185,24 @@ public void initialize() {
184185

185186
@Override
186187
protected void activate() {
188+
String key = "sensitiveDataRemovalInfo";
189+
if (DontShowAgainLookup.showAgain(key) &&
190+
(preferences.getClearDataAfterDays() == 0 ||
191+
preferences.getClearDataAfterDays() == Preferences.CLEAR_DATA_AFTER_DAYS_DISABLED)) { // existing users must agree to new feature
192+
new Popup()
193+
.headLine(Res.get("setting.info.headline"))
194+
.backgroundInfo(Res.get("settings.preferences.sensitiveDataRemoval.msg"))
195+
.actionButtonText(Res.get("shared.iUnderstand"))
196+
.onAction(() -> {
197+
DontShowAgainLookup.dontShowAgain(key, true);
198+
// user has acknowledged, enable the feature with a reasonable default value
199+
preferences.setClearDataAfterDays(Preferences.CLEAR_DATA_AFTER_DAYS_DEFAULT);
200+
clearDataAfterDaysInputTextField.setText(String.valueOf(preferences.getClearDataAfterDays()));
201+
})
202+
.closeButtonText(Res.get("shared.cancel"))
203+
.show();
204+
}
205+
187206
// We want to have it updated in case an asset got removed
188207
allCryptoCurrencies = FXCollections.observableArrayList(CurrencyUtil.getActiveSortedCryptoCurrencies(filterManager));
189208
allCryptoCurrencies.removeAll(cryptoCurrencies);
@@ -207,7 +226,7 @@ protected void deactivate() {
207226
///////////////////////////////////////////////////////////////////////////////////////////
208227

209228
private void initializeGeneralOptions() {
210-
int titledGroupBgRowSpan = displayStandbyModeFeature ? 7 : 6;
229+
int titledGroupBgRowSpan = displayStandbyModeFeature ? 8 : 7;
211230
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, titledGroupBgRowSpan, Res.get("setting.preferences.general"));
212231
GridPane.setColumnSpan(titledGroupBg, 1);
213232

@@ -257,14 +276,30 @@ private void initializeGeneralOptions() {
257276
}
258277
};
259278

279+
// clearDataAfterDays
280+
clearDataAfterDaysInputTextField = addInputTextField(root, ++gridRow, Res.get("setting.preferences.clearDataAfterDays"));
281+
IntegerValidator clearDataAfterDaysValidator = new IntegerValidator();
282+
clearDataAfterDaysValidator.setMinValue(1);
283+
clearDataAfterDaysValidator.setMaxValue(Preferences.CLEAR_DATA_AFTER_DAYS_DISABLED);
284+
clearDataAfterDaysInputTextField.setValidator(clearDataAfterDaysValidator);
285+
clearDataAfterDaysListener = (observable, oldValue, newValue) -> {
286+
try {
287+
int value = Integer.parseInt(newValue);
288+
if (!newValue.equals(oldValue)) {
289+
preferences.setClearDataAfterDays(value);
290+
}
291+
} catch (Throwable ignore) {
292+
}
293+
};
294+
260295
if (displayStandbyModeFeature) {
261296
// AvoidStandbyModeService feature works only on OSX & Windows
262297
avoidStandbyMode = addSlideToggleButton(root, ++gridRow,
263298
Res.get("setting.preferences.avoidStandbyMode"));
264299
}
265300

266301
useSoundForNotifications = addSlideToggleButton(root, ++gridRow,
267-
Res.get("setting.preferences.useSoundForNotifications"));
302+
Res.get("setting.preferences.useSoundForNotifications"), -5); // TODO: why must negative value be used to place toggle consistently?
268303
}
269304

270305
private void initializeSeparator() {
@@ -613,6 +648,7 @@ private void activateGeneralOptions() {
613648
ignoreTradersListInputTextField.setText(String.join(", ", preferences.getIgnoreTradersList()));
614649
/* referralIdService.getOptionalReferralId().ifPresent(referralId -> referralIdInputTextField.setText(referralId));
615650
referralIdInputTextField.setPromptText(Res.get("setting.preferences.refererId.prompt"));*/
651+
clearDataAfterDaysInputTextField.setText(String.valueOf(preferences.getClearDataAfterDays()));
616652
userLanguageComboBox.setItems(languageCodes);
617653
userLanguageComboBox.getSelectionModel().select(preferences.getUserLanguage());
618654
userLanguageComboBox.setConverter(new StringConverter<>() {
@@ -672,6 +708,7 @@ public Country fromString(String string) {
672708

673709
ignoreTradersListInputTextField.textProperty().addListener(ignoreTradersListListener);
674710
//referralIdInputTextField.textProperty().addListener(referralIdListener);
711+
clearDataAfterDaysInputTextField.textProperty().addListener(clearDataAfterDaysListener);
675712
}
676713

677714
private void activateDisplayCurrencies() {
@@ -805,6 +842,7 @@ private void deactivateGeneralOptions() {
805842
deviationInputTextField.focusedProperty().removeListener(deviationFocusedListener);
806843
ignoreTradersListInputTextField.textProperty().removeListener(ignoreTradersListListener);
807844
//referralIdInputTextField.textProperty().removeListener(referralIdListener);
845+
clearDataAfterDaysInputTextField.textProperty().removeListener(clearDataAfterDaysListener);
808846
}
809847

810848
private void deactivateDisplayCurrencies() {

0 commit comments

Comments
 (0)