Skip to content

Commit

Permalink
Merge pull request #909 from PasinduYeshan/self-registration-profiles
Browse files Browse the repository at this point in the history
Introduce query param profile-name to return claims supported by given profile
  • Loading branch information
PasinduYeshan authored Jan 22, 2025
2 parents 2bb0332 + 0de619a commit f411d00
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/*
* Copyright (c) 2016-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.recovery.endpoint;

import org.wso2.carbon.identity.recovery.endpoint.dto.*;
Expand Down Expand Up @@ -38,9 +56,15 @@ public class ClaimsApi {

@io.swagger.annotations.ApiResponse(code = 500, message = "Server Error") })

public Response claimsGet(@ApiParam(value = "tenant domain. Default `carbon.super`") @QueryParam("tenant-domain") String tenantDomain)
public Response claimsGet(
@ApiParam(value = "tenant domain. Default `carbon.super`")
@QueryParam("tenant-domain") String tenantDomain,

@ApiParam(value = "profile name.")
@QueryParam("profile-name") String profileName)
{
return delegate.claimsGet(tenantDomain);

return delegate.claimsGet(tenantDomain, profileName);
}
}

Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/*
* Copyright (c) 2016-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.recovery.endpoint;

import org.wso2.carbon.identity.recovery.endpoint.*;
Expand All @@ -15,5 +33,10 @@

public abstract class ClaimsApiService {
public abstract Response claimsGet(String tenantDomain);

public Response claimsGet(String tenantDomain, String profileName) {

return claimsGet(tenantDomain);
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
/*
* Copyright (c) 2016-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.recovery.endpoint.Utils;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand All @@ -14,6 +33,9 @@
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.common.model.User;
import org.wso2.carbon.identity.captcha.util.CaptchaConstants;
import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService;
import org.wso2.carbon.identity.claim.metadata.mgt.model.LocalClaim;
import org.wso2.carbon.identity.claim.metadata.mgt.util.ClaimConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.governance.IdentityGovernanceException;
Expand Down Expand Up @@ -74,6 +96,12 @@ public static UserSelfRegistrationManager getUserSelfRegistrationManager() {
.getOSGiService(UserSelfRegistrationManager.class, null);
}

public static ClaimMetadataManagementService getClaimMetadataManagementService() {

return (ClaimMetadataManagementService) PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getOSGiService(ClaimMetadataManagementService.class, null);
}

/**
* To get identity governance service
*
Expand Down Expand Up @@ -201,6 +229,36 @@ public static ClaimDTO getClaimDTO(Claim claim) {
return claimDTO;
}

public static ClaimDTO[] getClaimDTOs(List<LocalClaim> claims) {

if (claims == null) {
return new ClaimDTO[0];
}

ClaimDTO[] claimDTOs = new ClaimDTO[claims.size()];
for (int i = 0; i < claims.size(); i++) {
claimDTOs[i] = getClaimDTO(claims.get(i));
}
return claimDTOs;
}

public static ClaimDTO getClaimDTO(LocalClaim claim) {

ClaimDTO claimDTO = new ClaimDTO();
claimDTO.setUri(claim.getClaimURI());
claimDTO.setDialect(claim.getClaimDialectURI());

Map<String, String> claimProperties = claim.getClaimProperties();
if (MapUtils.isNotEmpty(claimProperties)) {
claimDTO.setDescription(claimProperties.get(ClaimConstants.DESCRIPTION_PROPERTY));
claimDTO.setDisplayName(claimProperties.get(ClaimConstants.DISPLAY_NAME_PROPERTY));
claimDTO.setRequired(Boolean.parseBoolean(claimProperties.get(ClaimConstants.REQUIRED_PROPERTY)));
claimDTO.setReadOnly(Boolean.parseBoolean(claimProperties.get(ClaimConstants.READ_ONLY_PROPERTY)));
claimDTO.setValidationRegex(claimProperties.get(ClaimConstants.REGULAR_EXPRESSION_PROPERTY));
}
return claimDTO;
}

public static UserClaim[] getUserClaims(List<UserClaimDTO> claimDTOs) {
UserClaim[] userClaims = new UserClaim[claimDTOs.size()];
for (int i = 0; i < claimDTOs.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
/*
* Copyright (c) 2016-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.recovery.endpoint.impl;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.common.util.CollectionUtils;
import org.wso2.carbon.identity.claim.metadata.mgt.exception.ClaimMetadataException;
import org.wso2.carbon.identity.claim.metadata.mgt.model.LocalClaim;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException;
import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants;
Expand Down Expand Up @@ -30,26 +51,46 @@ public class ClaimsApiServiceImpl extends ClaimsApiService {
private static final Log LOG = LogFactory.getLog(ClaimsApiServiceImpl.class);

@Override
public Response claimsGet(String tenantDomain) {
public Response claimsGet(String tenantDomain, String profileName) {

if (IdentityUtil.threadLocalProperties.get().get(Constants.TENANT_NAME_FROM_CONTEXT) != null) {
tenantDomain = (String) IdentityUtil.threadLocalProperties.get().get(Constants.TENANT_NAME_FROM_CONTEXT);
if (StringUtils.isBlank(profileName)) {
return claimsGet(tenantDomain);
}

if (StringUtils.isBlank(tenantDomain)) {
tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
} else if (!RecoveryUtil.isValidTenantDomain(tenantDomain)) {
RecoveryUtil.handleBadRequest("Invalid tenant domain :" + tenantDomain, IdentityRecoveryConstants
.ErrorMessages.ERROR_CODE_INVALID_TENANT.getCode());
tenantDomain = resolveTenantDomain(tenantDomain);
ClaimDTO[] claimDTOs = new ClaimDTO[0];
try {
List<LocalClaim> localClaims = RecoveryUtil.getClaimMetadataManagementService()
.getSupportedLocalClaimsForProfile(tenantDomain, profileName);
if (CollectionUtils.isEmpty(localClaims)) {
claimDTOs = new ClaimDTO[0];
}
claimDTOs = RecoveryUtil.getClaimDTOs(localClaims);
} catch (ClaimMetadataException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Client Error while getting all identity claims ", e);
}
RecoveryUtil.handleBadRequest(e.getMessage(), e.getErrorCode());
} catch (Throwable throwable) {
RecoveryUtil.handleInternalServerError(Constants.SERVER_ERROR, IdentityRecoveryConstants
.ErrorMessages.ERROR_CODE_UNEXPECTED.getCode(), LOG, throwable);
}
return Response.ok(claimDTOs).build();
}

@Override
public Response claimsGet(String tenantDomain) {

tenantDomain = resolveTenantDomain(tenantDomain);
String dialect = IdentityRecoveryConstants.WSO2CARBON_CLAIM_DIALECT;
NotificationUsernameRecoveryManager notificationBasedUsernameRecoveryManager = RecoveryUtil
.getNotificationBasedUsernameRecoveryManager();
ClaimDTO[] claimDTOs = new ClaimDTO[0];

try {
Claim[] userClaims = notificationBasedUsernameRecoveryManager.getIdentitySupportedClaims(dialect, tenantDomain);
Claim[] userClaims =
notificationBasedUsernameRecoveryManager.getIdentitySupportedClaims(dialect, tenantDomain);
claimDTOs = RecoveryUtil.getClaimDTOs(userClaims);

} catch (IdentityRecoveryClientException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Client Error while getting all identity claims ", e);
Expand All @@ -64,4 +105,18 @@ public Response claimsGet(String tenantDomain) {
}
return Response.ok(claimDTOs).build();
}

private static String resolveTenantDomain(String tenantDomain) {

if (IdentityUtil.threadLocalProperties.get().get(Constants.TENANT_NAME_FROM_CONTEXT) != null) {
tenantDomain = (String) IdentityUtil.threadLocalProperties.get().get(Constants.TENANT_NAME_FROM_CONTEXT);
}
if (StringUtils.isBlank(tenantDomain)) {
tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
} else if (!RecoveryUtil.isValidTenantDomain(tenantDomain)) {
RecoveryUtil.handleBadRequest("Invalid tenant domain :" + tenantDomain, IdentityRecoveryConstants
.ErrorMessages.ERROR_CODE_INVALID_TENANT.getCode());
}
return tenantDomain;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ paths:
required: false
type: string

- name: profile-name
in: query
description: profile name`
required: false
type: string

responses:
200:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,22 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService;
import org.wso2.carbon.identity.claim.metadata.mgt.exception.ClaimMetadataException;
import org.wso2.carbon.identity.claim.metadata.mgt.model.LocalClaim;
import org.wso2.carbon.identity.recovery.endpoint.Exceptions.BadRequestException;
import org.wso2.carbon.identity.recovery.endpoint.Utils.RecoveryUtil;
import org.wso2.carbon.identity.recovery.endpoint.impl.ClaimsApiServiceImpl;
import org.wso2.carbon.identity.recovery.password.NotificationPasswordRecoveryManager;
import org.wso2.carbon.identity.recovery.username.NotificationUsernameRecoveryManager;
import org.wso2.carbon.user.core.claim.Claim;

import java.util.ArrayList;
import java.util.List;

import static org.mockito.ArgumentMatchers.anyString;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertThrows;

/**
* Unit tests for ClaimsApiServiceImpl.java
Expand All @@ -47,6 +56,9 @@ public class ClaimsApiServiceImplTest {
@Mock
NotificationUsernameRecoveryManager notificationUsernameRecoveryManager;

@Mock
ClaimMetadataManagementService claimMetadataManagementService;

@InjectMocks
ClaimsApiServiceImpl claimsApiService;

Expand Down Expand Up @@ -74,6 +86,30 @@ public void testClaimsGet() throws IdentityException {
assertEquals(claimsApiService.claimsGet(null).getStatus(), 200);
}

@Test
public void testClaimsGetWithProfile() throws IdentityException {

mockedRecoveryUtil.when(RecoveryUtil::getClaimMetadataManagementService).thenReturn(
claimMetadataManagementService);
List<LocalClaim> localClaims = new ArrayList<>();
Mockito.when(claimMetadataManagementService
.getSupportedLocalClaimsForProfile("carbon.super", "selfRegistration"))
.thenReturn(localClaims);
assertEquals(claimsApiService.claimsGet("carbon.super", "selfRegistration")
.getStatus(), 200);

// Case 2: Error while retrieving claims.
Mockito.when(claimMetadataManagementService
.getSupportedLocalClaimsForProfile("carbon.super", "selfRegistration"))
.thenThrow(new ClaimMetadataException("Error"));

mockedRecoveryUtil.when(() -> RecoveryUtil.handleBadRequest(anyString(), anyString()))
.thenThrow(new BadRequestException());

assertThrows(BadRequestException.class, () ->
claimsApiService.claimsGet("carbon.super", "selfRegistration"));
}

@Test
public void testThrowableinClaimsGet() throws IdentityException {

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@
<carbon.kernel.registry.imp.pkg.version.range>[1.0.1, 2.0.0)</carbon.kernel.registry.imp.pkg.version.range>

<!--Carbon Identity Framework Version-->
<carbon.identity.framework.version>7.7.100</carbon.identity.framework.version>
<carbon.identity.framework.version>7.7.114</carbon.identity.framework.version>
<carbon.identity.framework.imp.pkg.version.range>[7.3.6, 8.0.0)
</carbon.identity.framework.imp.pkg.version.range>

Expand Down

0 comments on commit f411d00

Please sign in to comment.