Skip to content

Commit 5eed858

Browse files
committed
Apply CRAI suggestions
1 parent 7b5b655 commit 5eed858

File tree

5 files changed

+33
-37
lines changed

5 files changed

+33
-37
lines changed

api/src/main/java/bisq/api/rest_api/endpoints/RestApiBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ protected Response buildOkResponse(Object entity) {
4242
* @return The HTTP response.
4343
*/
4444
protected Response buildNoContentResponse( ) {
45-
return buildResponse(Response.Status.NO_CONTENT, "");
45+
return Response.status(Response.Status.NO_CONTENT).build();
4646
}
4747

4848
protected Response buildNotFoundResponse(String message) {

api/src/main/java/bisq/api/rest_api/endpoints/devices/DevicesRestApi.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@
4949
description = "API for registering and unregistering mobile devices for push notifications"
5050
)
5151
public class DevicesRestApi extends RestApiBase {
52-
53-
private static final int APNS_TOKEN_LENGTH = 64;
54-
private static final String ALPHANUMERIC_REGEX = "^[a-zA-Z0-9]+$";
52+
private static final String APNS_HEX_REGEX = "^[0-9a-fA-F]+$";
5553

5654
private final DeviceRegistrationService deviceRegistrationService;
5755

@@ -92,20 +90,16 @@ public Response registerDevice(RegisterDeviceRequest request) {
9290
deviceId, deviceDescriptor, deviceToken.length(), platform
9391
);
9492

95-
// Basic structural validation only; platform-specific rules belong in the service
96-
if (!deviceToken.matches(ALPHANUMERIC_REGEX)) {
93+
// Platform-specific token validation
94+
if (platform == MobileDevicePlatform.IOS && !deviceToken.matches(APNS_HEX_REGEX)) {
9795
return buildResponse(
9896
Response.Status.BAD_REQUEST,
99-
"deviceToken must contain only alphanumeric characters"
97+
"APNs device token must be a hex-encoded string"
10098
);
10199
}
102100

103-
if (platform == MobileDevicePlatform.IOS && deviceToken.length() != APNS_TOKEN_LENGTH) {
104-
log.warn("Unexpected APNs token length: {}", deviceToken.length());
105-
}
106-
107101
try {
108-
deviceRegistrationService.register(
102+
deviceRegistrationService.register(
109103
deviceId,
110104
deviceToken,
111105
publicKeyBase64,
@@ -157,10 +151,10 @@ public Response unregisterDevice(@PathParam("deviceId") String deviceId) {
157151

158152
private boolean isValid(RegisterDeviceRequest request) {
159153
return request != null
160-
&& !StringUtils.isEmpty(request.getDeviceId())
161-
&& !StringUtils.isEmpty(request.getDeviceToken())
162-
&& !StringUtils.isEmpty(request.getPublicKeyBase64())
163-
&& !StringUtils.isEmpty(request.getDeviceDescriptor())
154+
&& StringUtils.isNotEmpty(request.getDeviceId())
155+
&& StringUtils.isNotEmpty(request.getDeviceToken())
156+
&& StringUtils.isNotEmpty(request.getPublicKeyBase64())
157+
&& StringUtils.isNotEmpty(request.getDeviceDescriptor())
164158
&& request.getPlatform() != null;
165159
}
166160
}

bonded-roles/src/main/java/bisq/bonded_roles/mobile_notification_relay/MobileNotificationRelayClient.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,20 @@ public static Config from(com.typesafe.config.Config typesafeConfig) {
9393
}
9494

9595
private static TransportType getTransportTypeFromUrl(String url) {
96-
if (url.endsWith(".i2p")) {
97-
return TransportType.I2P;
98-
} else if (url.endsWith(".onion")) {
99-
return TransportType.TOR;
100-
} else {
101-
return TransportType.CLEAR;
96+
try {
97+
java.net.URI uri = java.net.URI.create(url);
98+
String host = uri.getHost();
99+
if (host != null) {
100+
if (host.endsWith(".i2p")) {
101+
return TransportType.I2P;
102+
} else if (host.endsWith(".onion")) {
103+
return TransportType.TOR;
104+
}
105+
}
106+
} catch (IllegalArgumentException e) {
107+
log.warn("Failed to parse URL for transport type detection: {}", url);
102108
}
109+
return TransportType.CLEAR;
103110
}
104111

105112
private final Set<Provider> providers;
@@ -214,7 +221,7 @@ private CompletableFuture<Boolean> sendToRelayServer(boolean isAndroid,
214221
String encryptedMessageHex,
215222
AtomicInteger recursionDepth) {
216223
if (noProviderAvailable) {
217-
return CompletableFuture.failedFuture(new RuntimeException("No block explorer provider available"));
224+
return CompletableFuture.failedFuture(new RuntimeException("No mobile notification relay provider available"));
218225
}
219226
if (shutdownStarted) {
220227
return CompletableFuture.failedFuture(new RuntimeException("Shutdown has already started"));

notifications/src/main/java/bisq/notifications/mobile/registration/DeviceRegistrationService.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ public void register(String deviceId,
4747
String publicKeyBase64,
4848
String deviceDescriptor,
4949
MobileDevicePlatform platform) {
50-
checkArgument(StringUtils.isEmpty(deviceId), "deviceId must not be null or empty");
51-
checkArgument(StringUtils.isEmpty(deviceToken), "deviceToken must not be null or empty");
52-
checkArgument(StringUtils.isEmpty(publicKeyBase64), "publicKeyBase64 must not be null or empty");
53-
checkArgument(StringUtils.isEmpty(deviceDescriptor), "deviceDescriptor must not be null or empty");
50+
checkArgument(StringUtils.isNotEmpty(deviceId), "deviceId must not be null or empty");
51+
checkArgument(StringUtils.isNotEmpty(deviceToken), "deviceToken must not be null or empty");
52+
checkArgument(StringUtils.isNotEmpty(publicKeyBase64), "publicKeyBase64 must not be null or empty");
53+
checkArgument(StringUtils.isNotEmpty(deviceDescriptor), "deviceDescriptor must not be null or empty");
5454
checkNotNull(platform, "platform must not be null");
5555

5656
String tokenPreview = deviceToken.substring(0, Math.min(10, deviceToken.length())) + "...";
@@ -64,12 +64,14 @@ public void register(String deviceId,
6464
publicKeyBase64,
6565
deviceDescriptor,
6666
platform);
67-
persistableStore.getDeviceByDeviceId().putIfAbsent(deviceId, mobileDeviceProfile);
68-
persist();
67+
MobileDeviceProfile previous = persistableStore.getDeviceByDeviceId().put(deviceId, mobileDeviceProfile);
68+
if (previous == null || !previous.equals(mobileDeviceProfile)) {
69+
persist();
70+
}
6971
}
7072

7173
public boolean unregister(String deviceId) {
72-
checkArgument(StringUtils.isEmpty(deviceId), "deviceId must not be null or empty");
74+
checkArgument(StringUtils.isNotEmpty(deviceId), "deviceId must not be null or empty");
7375

7476
MobileDeviceProfile previous = persistableStore.getDeviceByDeviceId().remove(deviceId);
7577
boolean hadValue = previous != null;

security/src/main/java/bisq/security/mobile_notifications/MobileNotificationEncryption.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,8 @@ public static String encrypt(String publicKeyBase64, String message) throws Gene
5959
// Any mismatch in these parameters will cause decryption to fail silently or produce garbage.
6060
byte[] derivation = new byte[0]; // Intentionally empty, not null
6161
byte[] encoding = new byte[0]; // Intentionally empty, not null
62-
63-
// Size (in bits) of the symmetric encryption key derived via ECIES KDF.
64-
// 128 bits → AES-128-CBC is used internally by Bouncy Castle ECIES.
65-
// The MAC key (HMAC-SHA1) is derived alongside it.
66-
// NOTE: This value MUST match exactly on all platforms.
6762
int macKeySize = 128;
68-
6963
IESParameterSpec iesSpec = new IESParameterSpec(derivation, encoding, macKeySize);
70-
7164
Cipher cipher = Cipher.getInstance("ECIES", BouncyCastleProvider.PROVIDER_NAME);
7265
cipher.init(Cipher.ENCRYPT_MODE, publicKey, iesSpec);
7366
byte[] encryptedBytes = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));

0 commit comments

Comments
 (0)