Skip to content

Commit

Permalink
Merge pull request #872 from PasinduYeshan/multi-email-userstore
Browse files Browse the repository at this point in the history
Toggle multi-email and mobile feature based on user store exclusion and support by default config
  • Loading branch information
PasinduYeshan authored Nov 4, 2024
2 parents a1eca1e + 4088369 commit 6f41c3f
Show file tree
Hide file tree
Showing 9 changed files with 444 additions and 146 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ public void handleEvent(Event event) throws IdentityEventException {
claims = new HashMap<>();
}

boolean supportMultipleMobileNumbers = Utils.isMultiEmailsAndMobileNumbersPerUserEnabled();
boolean supportMultipleMobileNumbers =
Utils.isMultiEmailsAndMobileNumbersPerUserEnabled(user.getTenantDomain(), user.getUserStoreDomain());

boolean enable = isMobileVerificationOnUpdateEnabled(user.getTenantDomain());

Expand All @@ -121,30 +122,6 @@ public void handleEvent(Event event) throws IdentityEventException {
}
claims.remove(IdentityRecoveryConstants.VERIFY_MOBILE_CLAIM);
claims.remove(IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM);

if (supportMultipleMobileNumbers) {
if (claims.containsKey(IdentityRecoveryConstants.MOBILE_NUMBER_CLAIM) &&
!claims.get(IdentityRecoveryConstants.MOBILE_NUMBER_CLAIM).isEmpty()) {
String mobileNumber = claims.get(IdentityRecoveryConstants.MOBILE_NUMBER_CLAIM);
List<String> exisitingAllNumbersList = Utils.getMultiValuedClaim(userStoreManager, user,
IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM);
List<String> updatedAllNumbersList =
claims.containsKey(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM)
? getListOfMobileNumbersFromString(
claims.get(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM))
: exisitingAllNumbersList;
if (!updatedAllNumbersList.contains(mobileNumber)) {
updatedAllNumbersList.add(mobileNumber);
claims.put(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM,
String.join(FrameworkUtils.getMultiAttributeSeparator(), updatedAllNumbersList));
}
}
} else {
// Multiple mobile numbers per user support is disabled.
log.debug("Supporting multiple mobile numbers per user is disabled.");
claims.remove(IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM);
claims.remove(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM);
}
return;
}

Expand Down Expand Up @@ -326,7 +303,15 @@ private void preSetUserClaimOnMobileNumberUpdate(Map<String, String> claims, Use
Utils.unsetThreadLocalToSkipSendingSmsOtpVerificationOnUpdate();
}

boolean supportMultipleMobileNumbers = Utils.isMultiEmailsAndMobileNumbersPerUserEnabled();
boolean supportMultipleMobileNumbers =
Utils.isMultiEmailsAndMobileNumbersPerUserEnabled(user.getTenantDomain(), user.getUserStoreDomain());

// Update multiple mobile numbers only if they’re in the claims map.
// This avoids issues with updating the primary mobile number due to user store limitations on multiple
// mobile numbers.
boolean shouldUpdateMultiMobilesRelatedClaims =
claims.containsKey(IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM) ||
claims.containsKey(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM);
String multiAttributeSeparator = FrameworkUtils.getMultiAttributeSeparator();

String mobileNumber = claims.get(IdentityRecoveryConstants.MOBILE_NUMBER_CLAIM);
Expand Down Expand Up @@ -364,10 +349,12 @@ private void preSetUserClaimOnMobileNumberUpdate(Map<String, String> claims, Use
updatedVerifiedNumbersList.removeIf(number -> !updatedAllNumbersList.contains(number));
}

claims.put(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM,
String.join(multiAttributeSeparator, updatedAllNumbersList));
claims.put(IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM,
String.join(multiAttributeSeparator, updatedVerifiedNumbersList));
if (shouldUpdateMultiMobilesRelatedClaims) {
claims.put(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM,
String.join(multiAttributeSeparator, updatedAllNumbersList));
claims.put(IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM,
String.join(multiAttributeSeparator, updatedVerifiedNumbersList));
}
} else {
updatedAllNumbersList = new ArrayList<>();
claims.remove(IdentityRecoveryConstants.MOBILE_NUMBERS_CLAIM);
Expand Down Expand Up @@ -410,7 +397,7 @@ private void preSetUserClaimOnMobileNumberUpdate(Map<String, String> claims, Use
.SkipMobileNumberVerificationOnUpdateStates.SKIP_ON_EXISTING_MOBILE_NUM.toString());
invalidatePendingMobileVerification(user, userStoreManager, claims);

if (supportMultipleMobileNumbers) {
if (supportMultipleMobileNumbers && shouldUpdateMultiMobilesRelatedClaims) {
if (!updatedVerifiedNumbersList.contains(existingMobileNumber)) {
updatedVerifiedNumbersList.add(existingMobileNumber);
claims.put(IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ public void handleEvent(Event event) throws IdentityEventException {
claims = new HashMap<>();
}

boolean supportMultipleEmails = Utils.isMultiEmailsAndMobileNumbersPerUserEnabled();
boolean supportMultipleEmails =
Utils.isMultiEmailsAndMobileNumbersPerUserEnabled(user.getTenantDomain(), user.getUserStoreDomain());

boolean enable = false;

Expand Down Expand Up @@ -131,30 +132,7 @@ public void handleEvent(Event event) throws IdentityEventException {
}
invalidatePendingEmailVerification(user, userStoreManager, claims);
}

if (supportMultipleEmails) {
// Drop the verified email addresses claim as verification on update is not enabled.
claims.remove(IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM);

if (claims.containsKey(IdentityRecoveryConstants.EMAIL_ADDRESS_CLAIM) &&
!claims.get(IdentityRecoveryConstants.EMAIL_ADDRESS_CLAIM).isEmpty()) {

String email = claims.get(IdentityRecoveryConstants.EMAIL_ADDRESS_CLAIM);
List<String> existingAllEmailAddresses = Utils.getMultiValuedClaim(userStoreManager, user,
IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM);

List<String> updatedAllEmailAddresses = claims.containsKey(
IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM)
? getListOfEmailAddressesFromString(
claims.get(IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM))
: existingAllEmailAddresses;
if (!updatedAllEmailAddresses.contains(email)) {
updatedAllEmailAddresses.add(email);
claims.put(IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM,
String.join(FrameworkUtils.getMultiAttributeSeparator(), updatedAllEmailAddresses));
}
}
}
claims.remove(IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM);
claims.remove(IdentityRecoveryConstants.VERIFY_EMAIL_CLIAM);
}
}
Expand Down Expand Up @@ -568,7 +546,15 @@ private void preSetUserClaimsOnEmailUpdate(Map<String, String> claims, UserStore
Utils.unsetThreadLocalToSkipSendingEmailVerificationOnUpdate();
}

boolean supportMultipleEmails = Utils.isMultiEmailsAndMobileNumbersPerUserEnabled();
boolean supportMultipleEmails =
Utils.isMultiEmailsAndMobileNumbersPerUserEnabled(user.getTenantDomain(), user.getUserStoreDomain());
// Update multiple email address related claims only if they’re in the claims map.
// This avoids issues with updating the primary email address due to user store limitations on multiple
// email addresses.
boolean shouldUpdateMultiMobilesRelatedClaims =
claims.containsKey(IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM) ||
claims.containsKey(IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM);

String multiAttributeSeparator = FrameworkUtils.getMultiAttributeSeparator();

String emailAddress = claims.get(IdentityRecoveryConstants.EMAIL_ADDRESS_CLAIM);
Expand Down Expand Up @@ -611,10 +597,12 @@ private void preSetUserClaimsOnEmailUpdate(Map<String, String> claims, UserStore
final List<String> tempUpdatedAllEmailAddresses = new ArrayList<>(updatedAllEmailAddresses);
updatedVerifiedEmailAddresses.removeIf(number -> !tempUpdatedAllEmailAddresses.contains(number));

claims.put(IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM,
StringUtils.join(updatedVerifiedEmailAddresses, multiAttributeSeparator));
claims.put(IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM,
StringUtils.join(updatedAllEmailAddresses, multiAttributeSeparator));
if (shouldUpdateMultiMobilesRelatedClaims) {
claims.put(IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM,
StringUtils.join(updatedVerifiedEmailAddresses, multiAttributeSeparator));
claims.put(IdentityRecoveryConstants.EMAIL_ADDRESSES_CLAIM,
StringUtils.join(updatedAllEmailAddresses, multiAttributeSeparator));
}
} else {
/*
email addresses and verified email addresses should not be updated when support for multiple email
Expand Down Expand Up @@ -655,7 +643,7 @@ private void preSetUserClaimsOnEmailUpdate(Map<String, String> claims, UserStore
.SkipEmailVerificationOnUpdateStates.SKIP_ON_EXISTING_EMAIL.toString());
invalidatePendingEmailVerification(user, userStoreManager, claims);

if (supportMultipleEmails) {
if (supportMultipleEmails && shouldUpdateMultiMobilesRelatedClaims) {
if (!updatedVerifiedEmailAddresses.contains(existingEmail)) {
updatedVerifiedEmailAddresses.add(existingEmail);
claims.put(IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -768,15 +768,19 @@ private UserRecoveryData validateSelfRegistrationCode(String code, String verifi
HashMap<String, String> userClaims = getClaimsListToUpdate(user, verifiedChannelType,
externallyVerifiedClaim, recoveryData.getRecoveryScenario().toString());

boolean supportMultipleEmailsAndMobileNumbers = Utils.isMultiEmailsAndMobileNumbersPerUserEnabled();
boolean supportMultipleEmailsAndMobileNumbers =
Utils.isMultiEmailsAndMobileNumbersPerUserEnabled(user.getTenantDomain(), user.getUserStoreDomain());
String multiAttributeSeparator = FrameworkUtils.getMultiAttributeSeparator();

if (RecoverySteps.VERIFY_EMAIL.equals(recoveryData.getRecoveryStep())) {
String pendingEmailClaimValue = recoveryData.getRemainingSetIds();
if (StringUtils.isNotBlank(pendingEmailClaimValue)) {
eventProperties.put(IdentityEventConstants.EventProperty.VERIFIED_EMAIL, pendingEmailClaimValue);
userClaims.put(IdentityRecoveryConstants.EMAIL_ADDRESS_PENDING_VALUE_CLAIM, StringUtils.EMPTY);
if (supportMultipleEmailsAndMobileNumbers) {
// Only update verified email addresses claim if the recovery scenario is
// EMAIL_VERIFICATION_ON_VERIFIED_LIST_UPDATE.
if (RecoveryScenarios.EMAIL_VERIFICATION_ON_VERIFIED_LIST_UPDATE.equals(
recoveryData.getRecoveryScenario()) && supportMultipleEmailsAndMobileNumbers) {
try {
List<String> verifiedEmails = Utils.getMultiValuedClaim(userStoreManager, user,
IdentityRecoveryConstants.VERIFIED_EMAIL_ADDRESSES_CLAIM);
Expand All @@ -796,9 +800,7 @@ private UserRecoveryData validateSelfRegistrationCode(String code, String verifi
throw new IdentityRecoveryServerException("Error occurred while obtaining existing claim " +
"value for the user : " + user.getUserName(), e);
}
}
if (!RecoveryScenarios.EMAIL_VERIFICATION_ON_VERIFIED_LIST_UPDATE
.equals(recoveryData.getRecoveryScenario())) {
} else {
userClaims.put(IdentityRecoveryConstants.EMAIL_ADDRESS_CLAIM, pendingEmailClaimValue);
}
// Todo passes when email address is properly set here.
Expand All @@ -809,7 +811,8 @@ private UserRecoveryData validateSelfRegistrationCode(String code, String verifi
if (RecoverySteps.VERIFY_MOBILE_NUMBER.equals(recoveryData.getRecoveryStep())) {
String pendingMobileClaimValue = recoveryData.getRemainingSetIds();
if (StringUtils.isNotBlank(pendingMobileClaimValue)) {
if (supportMultipleEmailsAndMobileNumbers) {
if (RecoveryScenarios.MOBILE_VERIFICATION_ON_VERIFIED_LIST_UPDATE.equals(
recoveryData.getRecoveryScenario()) && supportMultipleEmailsAndMobileNumbers) {
try {
List<String> existingVerifiedMobileNumbersList = Utils.getMultiValuedClaim(userStoreManager,
user, IdentityRecoveryConstants.VERIFIED_MOBILE_NUMBERS_CLAIM);
Expand All @@ -835,9 +838,7 @@ private UserRecoveryData validateSelfRegistrationCode(String code, String verifi
throw new IdentityRecoveryServerException("Error occurred while obtaining existing claim " +
"value for the user : " + user.getUserName(), e);
}
}
if (!RecoveryScenarios.MOBILE_VERIFICATION_ON_VERIFIED_LIST_UPDATE
.equals(recoveryData.getRecoveryScenario())) {
} else {
userClaims.put(IdentityRecoveryConstants.MOBILE_NUMBER_CLAIM, pendingMobileClaimValue);
}
userClaims.put(IdentityRecoveryConstants.MOBILE_NUMBER_PENDING_VALUE_CLAIM, StringUtils.EMPTY);
Expand Down Expand Up @@ -990,15 +991,17 @@ public void confirmVerificationCodeMe(String code, Map<String, String> propertie
UserStoreManager userStoreManager = getUserStoreManager(user);
HashMap<String, String> userClaims = new HashMap<>();

boolean supportMultipleEmailsAndMobileNumbers = Utils.isMultiEmailsAndMobileNumbersPerUserEnabled();
boolean supportMultipleEmailsAndMobileNumbers =
Utils.isMultiEmailsAndMobileNumbersPerUserEnabled(user.getTenantDomain(), user.getUserStoreDomain());

String pendingMobileNumberClaimValue = recoveryData.getRemainingSetIds();
if (StringUtils.isNotBlank(pendingMobileNumberClaimValue)) {
/*
Verifying whether user is trying to add a mobile number to http://wso2.org/claims/verifedMobileNumbers
claim.
*/
if (supportMultipleEmailsAndMobileNumbers) {
if (RecoveryScenarios.MOBILE_VERIFICATION_ON_VERIFIED_LIST_UPDATE.equals(
recoveryData.getRecoveryScenario()) && supportMultipleEmailsAndMobileNumbers) {
try {
String multiAttributeSeparator = FrameworkUtils.getMultiAttributeSeparator();
List<String> existingVerifiedMobileNumbersList = Utils.getMultiValuedClaim(userStoreManager,
Expand All @@ -1025,9 +1028,7 @@ public void confirmVerificationCodeMe(String code, Map<String, String> propertie
throw new IdentityRecoveryServerException("Error occurred while obtaining existing claim " +
"value for the user : " + user.getUserName(), e);
}
}
if (!RecoveryScenarios.MOBILE_VERIFICATION_ON_VERIFIED_LIST_UPDATE
.equals(recoveryData.getRecoveryScenario())) {
} else {
userClaims.put(IdentityRecoveryConstants.MOBILE_NUMBER_CLAIM, pendingMobileNumberClaimValue);
}
userClaims.put(NotificationChannels.SMS_CHANNEL.getVerifiedClaimUrl(), Boolean.TRUE.toString());
Expand Down
Loading

0 comments on commit 6f41c3f

Please sign in to comment.