Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>
<configuration>
<skipTests>false</skipTests>
<skipTests>true</skipTests>
</configuration>

Copilot AI Mar 5, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting Surefire’s <skipTests> to true disables unit tests for all builds, which makes it easy to ship regressions (especially for a release bump). If the intent is only to speed up local packaging, consider removing this change or gating it behind a Maven profile / CI property instead of committing it as the default.

Copilot uses AI. Check for mistakes.
</plugin>
<plugin>
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/privacyidea/AsyncRequestCallable.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,15 @@ public void onFailure(@NotNull Call call, @NotNull IOException e)
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException
{
// Only response.body() is available in OkHttp; ensure it is closed and consumed only once to prevent resource leaks.
// The body of the response can be in `body()` for success cases or in `errorBody()` for error cases.
// We need to handle both and ensure the body is closed to prevent resource leaks.
// The body can only be consumed once.
Comment thread
nilsbehlen marked this conversation as resolved.
Outdated
try (ResponseBody responseBody = response.body())
{
if (responseBody != null)
{
String s = responseBody.string();
if (!privacyIDEA.logExcludedEndpoints().contains(path) && !ENDPOINT_AUTH.equals(path))
if (!privacyIDEA.logExcludedEndpoints().contains(path))
Comment thread
nilsbehlen marked this conversation as resolved.
Outdated
{
privacyIDEA.log(path + " (" + response.code() + "):\n" + privacyIDEA.parser.formatJson(s));
}
Expand Down
48 changes: 39 additions & 9 deletions src/main/java/org/privacyidea/PIResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
Expand Down Expand Up @@ -84,10 +89,11 @@ public boolean authenticationSuccessful()
*/
public boolean pushAvailable()
{
return multiChallenge.stream().anyMatch(c -> isPushOrSmartphoneContainer(c.getType()));
return multiChallenge.stream().anyMatch(c -> isPushOrSmartphoneContainer(c.getType()) && "poll".equals(c.getClientMode()));
Comment thread
nilsbehlen marked this conversation as resolved.
}

private boolean isPushOrSmartphoneContainer(String type) {
private boolean isPushOrSmartphoneContainer(String type)
{
return TOKEN_TYPE_PUSH.equals(type) || CONTAINER_TYPE_SMARTPHONE.equals(type);
}

Expand All @@ -113,7 +119,8 @@ public String otpTransactionId()
return null;
}

public String pushTransactionId() {
public String pushTransactionId()
{
for (Challenge challenge : multiChallenge)
{
if (isPushOrSmartphoneContainer(challenge.getType()))
Expand Down Expand Up @@ -142,16 +149,27 @@ private boolean isNotBlank(String str) {
*/
public String otpMessage()
{
return reduceChallengeMessagesWhere(c -> !(isPushOrSmartphoneContainer(c.getType())));
return reduceChallengeMessagesWhere(c ->
{
String cm = c.getClientMode();
System.out.println(
"challenge for " + c.getType() + " " + c.getSerial() + " with mode: " + cm);
boolean yes = "interactive".equals(cm);
return yes;
Comment thread
nilsbehlen marked this conversation as resolved.
Outdated
});
Comment thread
nilsbehlen marked this conversation as resolved.
Outdated
}

private String reduceChallengeMessagesWhere(Predicate<Challenge> predicate)
{
StringBuilder sb = new StringBuilder();
sb.append(
multiChallenge.stream().filter(predicate).map(Challenge::getMessage).distinct().reduce("", (a, s) -> a + s + ", ").trim());

if (sb.length() > 0)
sb.append(this.multiChallenge.stream()
.filter(predicate)
.map(Challenge::getMessage)
.distinct()
.reduce("", (a, s) -> a + s + ", ")
.trim());

if (!sb.isEmpty())
Comment thread
nilsbehlen marked this conversation as resolved.
Outdated
{
sb.deleteCharAt(sb.length() - 1);
}
Expand Down Expand Up @@ -198,7 +216,19 @@ public String toJSON()

public static PIResponse fromJSON(String json)
{
return new Gson().fromJson(json, PIResponse.class);
JsonDeserializer<Challenge> challengeDeserializer = (jsonElement, type, ctx) ->
{
JsonObject obj = jsonElement.getAsJsonObject();
String serial = obj.has("serial") && !obj.get("serial").isJsonNull() ? obj.get("serial").getAsString() : "";
String message = obj.has("message") && !obj.get("message").isJsonNull() ? obj.get("message").getAsString() : "";
String clientMode = obj.has("clientMode") && !obj.get("clientMode").isJsonNull() ? obj.get("clientMode").getAsString() : "";
String image = obj.has("image") && !obj.get("image").isJsonNull() ? obj.get("image").getAsString() : "";
String transactionID = obj.has("transactionID") && !obj.get("transactionID").isJsonNull() ? obj.get("transactionID").getAsString() : "";
String tokenType = obj.has("type") && !obj.get("type").isJsonNull() ? obj.get("type").getAsString() : "";
return new Challenge(serial, message, clientMode, image, transactionID, tokenType);
};
Gson gson = new GsonBuilder().registerTypeAdapter(Challenge.class, challengeDeserializer).create();
return gson.fromJson(json, PIResponse.class);
}

@Override
Expand Down