Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f0b63dd
feat(jans-fido2): add controllers for metrics and resolve staging issues
imran-ishaq Jan 1, 2026
64a70b7
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
imran-ishaq Jan 5, 2026
4b31356
feat(jans-fido2): resolved sonar cube issues
imran-ishaq Jan 5, 2026
0420288
Merge branch 'main' into jans-fido2-metrics-endpoints
yurem Jan 16, 2026
7a24c5d
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
imran-ishaq Jan 19, 2026
3a8b2e5
feat(jans-fido2): resolved coderabbit issues
imran-ishaq Jan 21, 2026
2e11cd4
feat(jans-fido2): resolved build creation issues
imran-ishaq Jan 23, 2026
c522e81
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
imran-ishaq Jan 23, 2026
706b511
Merge branch 'jans-fido2-metrics-endpoints' of https://github.com/Jan…
imran-ishaq Jan 23, 2026
bf0103d
feat(jans-fido2): resolved sonar cube and code-rabbit issues 1
imran-ishaq Jan 23, 2026
4c1b156
feat(jans-fido2): resolved sonar cube and code-rabbit issues 2
imran-ishaq Jan 23, 2026
4328496
feat(jans-fido2): resolved sonar cube and code-rabbit issues 3
imran-ishaq Jan 23, 2026
11b63ad
feat(jans-fido2): resolved sonar cube and code-rabbit issues 4
imran-ishaq Jan 23, 2026
c2c2884
feat(jans-fido2): resolved sonar cube and code-rabbit issues 5
imran-ishaq Jan 23, 2026
6760d2e
feat(jans-fido2): resolved sonar cube and code-rabbit issues 6
imran-ishaq Jan 23, 2026
bf9d6e3
Merge branch 'main' into jans-fido2-metrics-endpoints
yurem Jan 27, 2026
a589940
Merge branch 'main' into jans-fido2-metrics-endpoints
yurem Jan 27, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import io.jans.orm.model.base.Entry;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
Expand All @@ -40,21 +42,24 @@ public class Fido2MetricsAggregation extends Entry implements Serializable {
private String aggregationType; // HOURLY, DAILY, WEEKLY, MONTHLY

@AttributeName(name = "jansStartTime")
private LocalDateTime startTime;
private Date startTime;

@AttributeName(name = "jansEndTime")
private LocalDateTime endTime;
private Date endTime;

@AttributeName(name = "jansUniqueUsers")
private Long uniqueUsers;

@AttributeName(name = "jansLastUpdated")
private LocalDateTime lastUpdated;
private Date lastUpdated;

/**
* All metrics data stored as JSON for flexibility
* Contains: registrationAttempts, registrationSuccesses, authenticationAttempts,
* authenticationSuccesses, deviceTypes, errorCounts, performanceMetrics, etc.
*
* Note: 'transient' prevents Java serialization, while '@JsonObject' enables ORM JSON persistence.
* This is a valid Janssen ORM pattern for storing complex objects as JSON in the database.
*/
@AttributeName(name = "jansMetricsData")
@JsonObject
Expand All @@ -65,13 +70,14 @@ public Fido2MetricsAggregation() {
this.metricsData = new HashMap<>();
}

public Fido2MetricsAggregation(String aggregationType, String period, LocalDateTime startTime, LocalDateTime endTime) {
public Fido2MetricsAggregation(String aggregationType, String period, Date startTime, Date endTime) {
this();
this.aggregationType = aggregationType;
this.id = aggregationType + "_" + period;
this.startTime = startTime;
this.endTime = endTime;
this.lastUpdated = LocalDateTime.now();
// Use UTC timezone to align with FIDO2 services
this.lastUpdated = Date.from(ZonedDateTime.now(ZoneId.of("UTC")).toInstant());
}

// Core getters and setters
Expand Down Expand Up @@ -102,19 +108,19 @@ public String getPeriod() {
return id;
}

public LocalDateTime getStartTime() {
public Date getStartTime() {
return startTime;
}

public void setStartTime(LocalDateTime startTime) {
public void setStartTime(Date startTime) {
this.startTime = startTime;
}

public LocalDateTime getEndTime() {
public Date getEndTime() {
return endTime;
}

public void setEndTime(LocalDateTime endTime) {
public void setEndTime(Date endTime) {
this.endTime = endTime;
}

Expand All @@ -126,11 +132,11 @@ public void setUniqueUsers(Long uniqueUsers) {
this.uniqueUsers = uniqueUsers;
}

public LocalDateTime getLastUpdated() {
public Date getLastUpdated() {
return lastUpdated;
}

public void setLastUpdated(LocalDateTime lastUpdated) {
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}

Expand Down Expand Up @@ -278,7 +284,16 @@ private Map<String, Long> getMapMetric(String key) {
}
Object value = metricsData.get(key);
if (value instanceof Map) {
return (Map<String, Long>) value;
Map<String, Object> rawMap = (Map<String, Object>) value;
// Convert Integer values to Long for JSON serialization compatibility
Map<String, Long> resultMap = new HashMap<>();
for (Map.Entry<String, Object> entry : rawMap.entrySet()) {
Object val = entry.getValue();
if (val instanceof Number) {
resultMap.put(entry.getKey(), ((Number) val).longValue());
}
}
return resultMap;
}
return Collections.emptyMap();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private Fido2MetricsConstants() {
public static final String MATURE = "MATURE";

// Database Attributes
public static final String JANS_TIMESTAMP = "jansTimestamp";
public static final String JANS_TIMESTAMP = "jansFido2MetricsTimestamp";

// Service Names
public static final String METRICS_SERVICE = "metricsService";
Expand Down Expand Up @@ -108,10 +108,20 @@ private Fido2MetricsConstants() {
public static final String PREVIOUS_PERIOD = "previousPeriod";
public static final String COMPARISON = "comparison";

// Query parameter names
public static final String PARAM_START_TIME = "startTime";
public static final String PARAM_END_TIME = "endTime";

// Fallback method constants
public static final String FALLBACK_METHOD_PASSWORD = "PASSWORD";

// Error message keywords
public static final String ERROR_KEYWORD_TIMEOUT = "timeout";
public static final String ERROR_KEYWORD_EXPIRED = "expired";

// Error messages
public static final String ERROR_UNEXPECTED = "An unexpected error occurred while processing the request";

// Health check keys
public static final String HEALTH_SERVICE_AVAILABLE = "serviceAvailable";
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Map;

/**
Expand Down Expand Up @@ -100,7 +102,8 @@ public class Fido2MetricsData implements Serializable {
private Double cpuUsagePercent;

public Fido2MetricsData() {
this.timestamp = LocalDateTime.now();
// Use UTC timezone to align with existing FIDO2 services
this.timestamp = ZonedDateTime.now(ZoneId.of("UTC")).toLocalDateTime();
}

// Getters and Setters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package io.jans.fido2.model.metric;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.jans.orm.annotation.AttributeName;
import io.jans.orm.annotation.DataEntry;
Expand All @@ -15,7 +16,9 @@
import io.jans.orm.model.base.Entry;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

Expand All @@ -27,70 +30,77 @@
@DataEntry
@ObjectClass("jansFido2MetricsEntry")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Fido2MetricsEntry extends Entry implements Serializable {

private static final long serialVersionUID = 1L;

@AttributeName(name = "jansId")
@AttributeName(name = "jansFido2MetricsId")
private String id;

@AttributeName(name = "jansMetricType")
@AttributeName(name = "jansFido2MetricsType")
private String metricType;

@AttributeName(name = "jansTimestamp")
private LocalDateTime timestamp;
@AttributeName(name = "jansFido2MetricsTimestamp")
private Date timestamp;

@AttributeName(name = "jansUserId")
@AttributeName(name = "jansFido2MetricsUserId")
private String userId;

@AttributeName(name = "jansUsername")
@AttributeName(name = "jansFido2MetricsUsername")
private String username;

@AttributeName(name = "jansOperationType")
@AttributeName(name = "jansFido2MetricsOperationType")
private String operationType; // REGISTRATION, AUTHENTICATION, FALLBACK

@AttributeName(name = "jansStatus")
@AttributeName(name = "jansFido2MetricsStatus")
private String status; // SUCCESS, FAILURE, ATTEMPT

@AttributeName(name = "jansDurationMs")
@AttributeName(name = "jansFido2MetricsDuration")
private Long durationMs;

@AttributeName(name = "jansAuthenticatorType")
@AttributeName(name = "jansFido2MetricsAuthenticatorType")
private String authenticatorType; // PLATFORM, CROSS_PLATFORM, SECURITY_KEY

@AttributeName(name = "jansDeviceInfo")
@AttributeName(name = "jansFido2MetricsDeviceInfo")
@JsonObject
private DeviceInfo deviceInfo;

@AttributeName(name = "jansErrorReason")
@AttributeName(name = "jansFido2MetricsErrorReason")
private String errorReason;

@AttributeName(name = "jansErrorCategory")
@AttributeName(name = "jansFido2MetricsErrorCategory")
private String errorCategory;

@AttributeName(name = "jansFallbackMethod")
@AttributeName(name = "jansFido2MetricsFallbackMethod")
private String fallbackMethod;

@AttributeName(name = "jansFallbackReason")
@AttributeName(name = "jansFido2MetricsFallbackReason")
private String fallbackReason;

@AttributeName(name = "jansUserAgent")
@AttributeName(name = "jansFido2MetricsUserAgent")
private String userAgent;

@AttributeName(name = "jansIpAddress")
@AttributeName(name = "jansFido2MetricsIpAddress")
private String ipAddress;

@AttributeName(name = "jansSessionId")
@AttributeName(name = "jansFido2MetricsSessionId")
private String sessionId;

@AttributeName(name = "jansAdditionalData")
/**
* Additional data stored as JSON for flexibility
*
* Note: 'transient' prevents Java serialization, while '@JsonObject' enables ORM JSON persistence.
* This is a valid Janssen ORM pattern for storing complex objects as JSON in the database.
*/
@AttributeName(name = "jansFido2MetricsAdditionalData")
@JsonObject
private transient Map<String, Object> additionalData;

@AttributeName(name = "jansNodeId")
@AttributeName(name = "jansFido2MetricsNodeId")
private String nodeId;

@AttributeName(name = "jansApplicationType")
@AttributeName(name = "jansFido2MetricsApplicationType")
private String applicationType;

// Constructors
Expand All @@ -102,7 +112,8 @@ public Fido2MetricsEntry(String metricType, String operationType, String status)
this.metricType = metricType;
this.operationType = operationType;
this.status = status;
this.timestamp = LocalDateTime.now();
// Use UTC timezone to align with FIDO2 services
this.timestamp = Date.from(ZonedDateTime.now(ZoneId.of("UTC")).toInstant());
}

// Getters and Setters
Expand All @@ -122,11 +133,11 @@ public void setMetricType(String metricType) {
this.metricType = metricType;
}

public LocalDateTime getTimestamp() {
public Date getTimestamp() {
return timestamp;
}

public void setTimestamp(LocalDateTime timestamp) {
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}

Expand Down Expand Up @@ -291,6 +302,7 @@ public String toString() {
* Device information extracted from User-Agent
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class DeviceInfo implements Serializable {
private static final long serialVersionUID = 1L;

Expand Down
Loading