Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jans-config-api): dashboard with monthly active users #10726

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
73a2f51
feat(config-api): default ACR methods issue#10511
pujavs Dec 31, 2024
f128244
feat(config-api): agama flow acr method
pujavs Jan 2, 2025
306e42f
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 2, 2025
8076006
fix(config-api): setting agama flow as auth method
pujavs Jan 2, 2025
f05ee12
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 8, 2025
acf3fbc
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 9, 2025
6d2abe0
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 14, 2025
c83d649
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 14, 2025
3aae4f0
test(config-api) token test case failure #10619
pujavs Jan 14, 2025
ba6a158
test(config-api) token test case failure #10619
pujavs Jan 14, 2025
afa861a
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 17, 2025
1bf47e0
feat(config-api): lock stat endpoint
pujavs Jan 17, 2025
1f1b4fa
feat(config-api): lock stat endpoint
pujavs Jan 20, 2025
dfae7c5
feat(config-api): scope test case update
pujavs Jan 20, 2025
605d1b5
feat(config-api): scope test case update
pujavs Jan 20, 2025
faed1bf
feat(config-api): scope test case update
pujavs Jan 20, 2025
79ff177
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 21, 2025
e64b0f8
feat(config-api): sync with main
pujavs Jan 21, 2025
3f08ab4
feat(config-api): lock stat endpoint
pujavs Jan 21, 2025
ac8ca67
feat(config-api): lock endpoint for stat
pujavs Jan 21, 2025
58f278a
feat(config-api): sync with main
pujavs Jan 22, 2025
0d68999
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 22, 2025
7cdc3f8
feat(config-api): lock endpoint wip
pujavs Jan 22, 2025
0a0fe47
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 23, 2025
9b97d97
feat(config-api): lock stats endpoint
pujavs Jan 23, 2025
671aa7d
feat(config-api): lock stat endpoint
pujavs Jan 23, 2025
2a8bf86
feat(config-api): lock stat endpoint
pujavs Jan 23, 2025
f4bf3c5
Merge branch 'main' into jans-config-dev
yuriyz Jan 23, 2025
40586e0
Merge branch 'main' into jans-config-dev
devrimyatar Jan 23, 2025
dcdea5c
Merge branch 'main' of https://github.com/JanssenProject/jans into ja…
pujavs Jan 24, 2025
b9ab35b
Merge branch 'jans-config-dev' of https://github.com/JanssenProject/j…
pujavs Jan 24, 2025
6135564
fix(config-api): asset upload config and saml document store changes
pujavs Jan 24, 2025
4369b79
fix(config-api): asset upload config and saml document store changes
pujavs Jan 24, 2025
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
18 changes: 9 additions & 9 deletions jans-config-api/docs/jans-config-api-swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9337,19 +9337,19 @@ components:
type: string
selected:
type: boolean
userCanAccess:
type: boolean
adminCanAccess:
type: boolean
whitePagesCanView:
type: boolean
adminCanView:
type: boolean
userCanView:
type: boolean
userCanEdit:
type: boolean
adminCanEdit:
type: boolean
userCanView:
adminCanAccess:
type: boolean
userCanAccess:
type: boolean
whitePagesCanView:
type: boolean
baseDn:
type: string
Expand Down Expand Up @@ -10211,8 +10211,6 @@ components:
type: boolean
lockMessageConfig:
$ref: '#/components/schemas/LockMessageConfig'
fapi:
type: boolean
allResponseTypesSupported:
uniqueItems: true
type: array
Expand All @@ -10222,6 +10220,8 @@ components:
- code
- token
- id_token
fapi:
type: boolean
AuthenticationFilter:
required:
- baseDn
Expand Down
33 changes: 9 additions & 24 deletions jans-config-api/plugins/docs/lock-plugin-swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ paths:
security:
- oauth2:
- https://jans.io/oauth/lock-config.write
/lock/stat:
/lock/lockStat:
get:
tags:
- Statistics
Expand All @@ -488,12 +488,12 @@ paths:
is mandatory if start_month and end_month parameters are not present.
schema:
type: string
- name: start_month
- name: start-month
in: query
description: Start-Month for which the stat report is to be fetched
schema:
type: string
- name: end_month
- name: end-month
in: query
description: End-Month for which the stat report is to be fetched
schema:
Expand Down Expand Up @@ -671,9 +671,6 @@ components:
tokenUrl:
type: string
description: Jans URL of the OpenID Connect Provider's OAuth 2.0 Token Endpoint
groupScopeEnabled:
type: boolean
description: Group scope enabled
endpointGroups:
type: object
additionalProperties:
Expand Down Expand Up @@ -707,9 +704,6 @@ components:
externalLoggerConfiguration:
type: string
description: The path to the external log4j2 logging configuration
metricChannel:
type: string
description: Channel for metric reports
metricReporterInterval:
type: integer
description: The interval for metric reporter in seconds
Expand All @@ -725,11 +719,6 @@ components:
type: integer
description: Time interval for the Clean Service in seconds
format: int32
opaConfiguration:
$ref: '#/components/schemas/OpaConfiguration'
pdpType:
type: string
description: PDP type
policiesJsonUrisAuthorizationToken:
type: string
description: Authorization token to access Json Uris
Expand All @@ -748,18 +737,14 @@ components:
items:
type: string
description: List of Zip Uris with policies
errorReasonEnabled:
type: boolean
OpaConfiguration:
type: object
properties:
baseUrl:
messageConsumerType:
type: string
description: Base OPA URL
accessToken:
description: PubSub consumer service
policyConsumerType:
type: string
description: OPA access token
description: Opa Configuration
description: Policy consumer service
errorReasonEnabled:
type: boolean
JsonPatch:
type: object
JsonNode:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public Set<Class<?>> getClasses() {

classes.add(LockConfigResource.class);
classes.add(AuditResource.class);
classes.add(LockStatResource.class);

return classes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

package io.jans.configapi.plugin.lock.rest;



import com.fasterxml.jackson.databind.JsonNode;

import static io.jans.as.model.util.Util.escapeLog;
import io.jans.configapi.core.model.exception.ApiApplicationException;
import io.jans.configapi.core.rest.BaseResource;
import io.jans.configapi.core.rest.ProtectedApi;
import io.jans.configapi.plugin.lock.service.LockService;
Expand Down Expand Up @@ -66,8 +65,8 @@ public class LockStatResource extends BaseResource {
public Response getStatistics(
@Parameter(description = "Authorization code") @HeaderParam("Authorization") String authorization,
@Parameter(description = "Month for which the stat report is to be fetched. The parameter is mandatory if start_month and end_month parameters are not present.") @QueryParam(value = "month") String month,
@Parameter(description = "Start-Month for which the stat report is to be fetched") @QueryParam(value = "start_month") String startMonth,
@Parameter(description = "End-Month for which the stat report is to be fetched") @QueryParam(value = "end_month") String endMonth,
@Parameter(description = "Start-Month for which the stat report is to be fetched") @QueryParam(value = "start-month") String startMonth,
@Parameter(description = "End-Month for which the stat report is to be fetched") @QueryParam(value = "end-month") String endMonth,
@Parameter(description = "Report format") @QueryParam(value = "format") String format) {
if (StringUtils.isBlank(format)) {
format = "";
Expand All @@ -77,13 +76,17 @@ public Response getStatistics(
if (logger.isInfoEnabled()) {
logger.info(
"LockStatResource::getStatistics() - authorization:{}, month:{}, startMonth:{}, endMonth:{}, format:{}",
escapeLog(authorization), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth), escapeLog(format));
escapeLog(authorization), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth),
escapeLog(format));
}
String url = getIssuer() + STAT_URL;
jsonNode = this.lockService.getStat(url, authorization, month, startMonth, endMonth, format);
logger.info("StatResource::getUserStatistics() - jsonNode:{} ", jsonNode);
} catch (ApiApplicationException aex) {
logger.error(" ApiApplicationException while fetching lock stat is", aex);
throwInternalServerException("Stat Error", aex);
} catch (Exception ex) {
logger.error(" Error while fetching lock stat is", ex);
logger.error(" Exception while fetching lock stat is", ex);
throwBadRequestException(ex);
}
return Response.ok(jsonNode).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;

import static io.jans.as.model.util.Util.escapeLog;
import io.jans.configapi.core.model.exception.ApiApplicationException;
import io.jans.configapi.core.service.ConfigHttpService;
import io.jans.model.net.HttpServiceResponse;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.MediaType;

import jakarta.ws.rs.core.Response.Status;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;

@ApplicationScoped
public class LockService {

private static final String CONTENT_TYPE = "Content-Type";
private static final String AUTHORIZATION = "Authorization";

Expand All @@ -31,73 +37,95 @@ public class LockService {
ConfigHttpService configHttpService;

public JsonNode getStat(String url, String token, String month, String startMonth, String endMonth, String format)
throws JsonProcessingException {
throws ApiApplicationException, JsonProcessingException {
if (logger.isInfoEnabled()) {
logger.info(
"LockStatResource::getStatistics() - url:{}, token:{}, month:{}, startMonth:{}, endMonth:{}, format:{}",
escapeLog(url), escapeLog(token), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth), escapeLog(format));
escapeLog(url), escapeLog(token), escapeLog(month), escapeLog(startMonth), escapeLog(endMonth),
escapeLog(format));
}

JsonNode jsonNode = null;

// Request headers
Map<String, String> headers = new HashMap<>();
headers.put(CONTENT_TYPE, MediaType.APPLICATION_JSON);
if (StringUtils.isNotBlank(token)) {
headers.put(AUTHORIZATION, token);
}

// Query Param
// Query Parameter
Map<String, String> data = new HashMap<>();
data.put("month", month);
data.put("start-month", startMonth);
data.put("end-month", endMonth);
data.put("format", format);
HttpServiceResponse httpServiceResponse = configHttpService.executeGet(url, headers, data);

logger.info(" stat httpServiceResponse:{}", httpServiceResponse);
if (httpServiceResponse != null) {
jsonNode = getResponseJsonNode(httpServiceResponse, Status.OK);
logger.info(
" stat httpServiceResponse.getHttpResponse():{}, httpServiceResponse.getHttpResponse().getStatusLine():{}, httpServiceResponse.getHttpResponse().getEntity():{}",
httpServiceResponse.getHttpResponse(), httpServiceResponse.getHttpResponse().getStatusLine(),
httpServiceResponse.getHttpResponse().getEntity());
jsonNode = getResponseJsonNode(httpServiceResponse);
}
logger.info(" stat jsonNode:{}", jsonNode);
return jsonNode;
}

public String getResponseEntityString(HttpServiceResponse serviceResponse, Status status) {
public JsonNode getResponseJsonNode(HttpServiceResponse serviceResponse)
throws ApiApplicationException, JsonProcessingException {
JsonNode jsonNode = null;

if (serviceResponse == null) {
return jsonNode;
}

return getResponseJsonNode(getResponseEntityString(serviceResponse), "response");
}

public String getResponseEntityString(HttpServiceResponse serviceResponse) throws ApiApplicationException {
String jsonString = null;

if (serviceResponse == null) {
return jsonString;
}

if (serviceResponse.getHttpResponse() != null && serviceResponse.getHttpResponse().getStatusLine() != null
&& serviceResponse.getHttpResponse().getStatusLine().getStatusCode() == status.getStatusCode()) {
HttpEntity entity = serviceResponse.getHttpResponse().getEntity();
HttpResponse httpResponse = serviceResponse.getHttpResponse();
if (httpResponse != null) {
HttpEntity entity = httpResponse.getEntity();
logger.debug("entity:{}, httpResponse.getStatusLine().getStatusCode():{}", entity,
httpResponse.getStatusLine().getStatusCode());
if (entity == null) {
return jsonString;
}
jsonString = entity.toString();
try {
jsonString = EntityUtils.toString(entity, "UTF-8");
} catch (Exception ex) {
logger.error("Error while getting entity using EntityUtils is ", ex);
}

if (httpResponse.getStatusLine() != null
&& httpResponse.getStatusLine().getStatusCode() == Status.OK.getStatusCode()) {
return jsonString;
} else {
throw new ApiApplicationException(httpResponse.getStatusLine().getStatusCode(), jsonString);
}
}
logger.info(" stat jsonString:{}", jsonString);
return jsonString;
}

public JsonNode getResponseJsonNode(HttpServiceResponse serviceResponse, Status status)
throws JsonProcessingException {
public JsonNode getResponseJsonNode(String jsonSring, String nodeName) throws JsonProcessingException {
JsonNode jsonNode = null;

if (serviceResponse == null) {
if (StringUtils.isBlank(jsonSring)) {
return jsonNode;
}

return getResponseJsonNode(getResponseEntityString(serviceResponse, status));
}

public JsonNode getResponseJsonNode(String jsonSring) throws JsonProcessingException {
JsonNode jsonNode = null;

if (StringUtils.isNotBlank(jsonSring)) {
return jsonNode;
jsonNode = Jackson.asJsonNode(jsonSring);
if (StringUtils.isNotBlank(nodeName) && jsonNode != null && jsonNode.get(nodeName) != null) {
jsonNode = jsonNode.get("response");
}

return Jackson.asJsonNode(jsonSring);
return jsonNode;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ private Constants() {
public static final String LOCK = "/lock";
public static final String LOCK_CONFIG = "/lockConfig";
public static final String AUDIT = "/audit";
public static final String LOCK_STAT = "/stat";
public static final String LOCK_STAT = "/lockStat";
public static final String HEALTH = "/health";
public static final String LOG = "/log";
public static final String TELEMETRY = "/telemetry";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public String processAuthorization(String token, String issuer, ResourceInfo res

private String validateScope(String accessToken, List<String> tokenScopes, ResourceInfo resourceInfo, String issuer)
throws WebApplicationException {
logger.debug("Validate scope, accessToken:{}, tokenScopes:{}, resourceInfo: {}, issuer: {}", accessToken,
logger.info("Validate scope, accessToken:{}, tokenScopes:{}, resourceInfo: {}, issuer: {}", accessToken,
tokenScopes, resourceInfo, issuer);
try {
// Get resource scope
Expand All @@ -131,15 +131,15 @@ private String validateScope(String accessToken, List<String> tokenScopes, Resou

// find missing scopes
List<String> missingScopes = findMissingScopes(resourceScopesByType, tokenScopes);
logger.debug("missingScopes:{}", missingScopes);
logger.info("missingScopes:{}", missingScopes);

// Check if resource requires auth server specific scope
List<String> authSpecificScope = getAuthSpecificScopeRequired(resourceInfo);
logger.debug(" resourceScopes:{}, authSpecificScope:{} ", resourceScopes, authSpecificScope);
logger.info(" resourceScopes:{}, authSpecificScope:{} ", resourceScopes, authSpecificScope);

// If No auth scope required OR if token contains the authSpecificScope
if ((authSpecificScope == null || authSpecificScope.isEmpty())) {
logger.debug("Validating token scopes as no authSpecificScope required");
logger.info("Validating token scopes as no authSpecificScope required");
if ((missingScopes != null && !missingScopes.isEmpty())) {
logger.error("Insufficient scopes! Required scope:{} - however token scopes:{}", resourceScopes,
tokenScopes);
Expand All @@ -160,7 +160,14 @@ private String validateScope(String accessToken, List<String> tokenScopes, Resou
+ ", however token scopes: " + tokenScopes,
Response.status(Response.Status.UNAUTHORIZED).build());
}

//If no scope is missing
if (missingScopes == null || missingScopes.isEmpty()) {
logger.info(" No missing scopes and hence returning original accessToken");
return accessToken;
}

logger.info("Generating new token with authSpecificScope");
// Generate token with required resourceScopes
resourceScopes.addAll(authSpecificScope);
accessToken = openIdService.requestAccessToken(authUtil.getClientId(), resourceScopes);
Expand Down
Loading
Loading