Skip to content

Commit 7135696

Browse files
committed
[SYNCOPE-2008] Minimize manager Realms entitlements
1 parent 57d3f18 commit 7135696

7 files changed

Lines changed: 64 additions & 37 deletions

File tree

‎client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public String getJWT() {
220220
public boolean isJWTExpiring() {
221221
return Optional.ofNullable(jwtExpiration).
222222
map(je -> je.isBefore(Instant.now().
223-
plus(SyncopeWebApplication.get().getJwtExpirationMinutesThreshold(), ChronoUnit.MINUTES))).
223+
plus(SyncopeWebApplication.get().getJwtExpirationMinutesThreshold(), ChronoUnit.MINUTES))).
224224
orElse(false);
225225
}
226226

@@ -261,7 +261,7 @@ public boolean authenticate(final String username, final String password) {
261261
flatMap(r -> Optional.ofNullable(r.getHeaderString(RESTHeaders.OWNED_ENTITLEMENTS))).
262262
filter(IdRepoEntitlement.MUST_CHANGE_PASSWORD::equals).
263263
map(code -> clientFactory.setDomain(getDomain()).
264-
create(new BasicAuthenticationHandler(username, password))).
264+
create(new BasicAuthenticationHandler(username, password))).
265265
orElse(null);
266266
if (client != null) {
267267
authenticated = true;
@@ -355,7 +355,10 @@ public UserTO getSelfTO() {
355355
}
356356

357357
public List<String> getAuthRealms() {
358-
return self.entitlements().values().stream().flatMap(Set::stream).distinct().sorted().toList();
358+
return self.entitlements().values().stream().
359+
flatMap(Set::stream).
360+
map(RealmsUtils::getFullPath).
361+
distinct().sorted().toList();
359362
}
360363

361364
public List<String> getSearchableRealms() {

‎client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmsUtils.java‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,8 @@
2626

2727
public final class RealmsUtils {
2828

29-
public static String getFullPath(final String fullpath) {
30-
String display = fullpath;
31-
if (display.indexOf('@') != -1) {
32-
display = StringUtils.substringBefore(display, "@");
33-
}
34-
return display;
29+
public static String getFullPath(final String path) {
30+
return StringUtils.substringBefore(path, "@");
3531
}
3632

3733
public static boolean checkInput(final String input) {

‎client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,10 @@ protected List<Pair<String, RealmTO>> load() {
127127
sorted(Comparator.comparing(Pair::getLeft));
128128
} else {
129129
full = map.entrySet().stream().
130-
map(el -> Pair.of(el.getKey(), el.getValue().getLeft()));
130+
map(pair -> Pair.of(pair.getKey(), pair.getValue().getLeft()));
131131
}
132-
return full.filter(realm -> SyncopeConsoleSession.get().getSearchableRealms().stream().anyMatch(
133-
r -> realm.getValue().getFullPath().startsWith(r))).
134-
collect(Collectors.toList());
132+
return full.filter(realm -> SyncopeConsoleSession.get().getSearchableRealms().stream().
133+
anyMatch(r -> realm.getValue().getFullPath().startsWith(r))).toList();
135134
}
136135
};
137136

‎client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Details.java‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,24 @@ public Details(
7070
final PageReference pageRef) {
7171

7272
this.pageRef = pageRef;
73-
final List<String> authRealms = SyncopeConsoleSession.get().getAuthRealms();
74-
final T inner = wrapper.getInnerObject();
75-
final Fragment fragment;
7673

74+
Fragment fragment;
7775
if (templateMode) {
7876
realm = new AjaxTextFieldPanel(
79-
"destinationRealm", "destinationRealm", new PropertyModel<>(inner, "realm"), false);
77+
"destinationRealm", "destinationRealm",
78+
new PropertyModel<>(wrapper.getInnerObject(), "realm"), false);
8079
AjaxTextFieldPanel.class.cast(realm).enableJexlHelp();
80+
8181
fragment = new Fragment("realmsFragment", "realmsTemplateFragment", this);
8282
} else {
8383
boolean fullRealmsTree = SyncopeWebApplication.get().fullRealmsTree(realmRestClient);
84-
AutoCompleteSettings settings = new AutoCompleteSettings();
85-
settings.setShowCompleteListOnFocusGain(fullRealmsTree);
86-
settings.setShowListOnEmptyInput(fullRealmsTree);
84+
List<String> authRealms = SyncopeConsoleSession.get().getAuthRealms();
8785

8886
realm = new AjaxSearchFieldPanel("destinationRealm", "destinationRealm",
89-
new PropertyModel<>(inner, "realm"), settings) {
87+
new PropertyModel<>(wrapper.getInnerObject(), "realm"),
88+
new AutoCompleteSettings().
89+
setShowCompleteListOnFocusGain(fullRealmsTree).
90+
setShowListOnEmptyInput(fullRealmsTree)) {
9091

9192
private static final long serialVersionUID = -6390474600233486704L;
9293

@@ -99,17 +100,16 @@ protected Iterator<String> getChoices(final String input) {
99100
: realmRestClient.search(RealmsUtils.buildNameQuery(input))).getResult()).
100101
stream().map(RealmTO::getFullPath).
101102
filter(fullPath -> authRealms.stream().anyMatch(
102-
authRealm -> fullPath.startsWith(authRealm))).iterator();
103+
authRealm -> fullPath.startsWith(authRealm))).iterator();
103104
}
104105
};
105106

106107
fragment = new Fragment("realmsFragment", "realmsSearchFragment", this);
107108
}
108109
fragment.addOrReplace(realm);
109110
addOrReplace(fragment);
110-
add(getGeneralStatusInformation("generalStatusInformation", inner).
111+
add(getGeneralStatusInformation("generalStatusInformation", wrapper.getInnerObject()).
111112
setEnabled(includeStatusPanel).setVisible(includeStatusPanel).setRenderBodyOnly(true));
112-
113113
}
114114

115115
public Details<T> disableRealmSpecification() {

‎core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserSelfLogic.java‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.time.OffsetDateTime;
2222
import java.util.HashSet;
2323
import java.util.List;
24+
import java.util.Map;
2425
import java.util.Optional;
2526
import java.util.Set;
2627
import java.util.stream.Collectors;
@@ -55,6 +56,8 @@
5556
import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
5657
import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
5758
import org.apache.syncope.core.persistence.api.entity.user.User;
59+
import org.apache.syncope.core.persistence.api.utils.RealmUtils.ManagerRealm;
60+
import org.apache.syncope.core.persistence.api.utils.RealmUtils.NormalizedRealms;
5861
import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
5962
import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
6063
import org.apache.syncope.core.provisioning.api.jexl.TemplateUtils;
@@ -64,6 +67,7 @@
6467
import org.apache.syncope.core.spring.policy.PasswordPolicyException;
6568
import org.apache.syncope.core.spring.security.AuthContextUtils;
6669
import org.apache.syncope.core.spring.security.SecurityProperties;
70+
import org.apache.syncope.core.spring.security.SyncopeGrantedAuthority;
6771
import org.apache.syncope.core.spring.security.throttle.PasswordResetRequestThrottler;
6872
import org.apache.syncope.core.spring.security.throttle.ThrottlerAttempts;
6973
import org.springframework.security.access.prepost.PreAuthorize;
@@ -81,6 +85,8 @@ protected static void throwMfaWasSet(final String username) {
8185
throw sce;
8286
}
8387

88+
protected final SecurityProperties securityProperties;
89+
8490
protected final DelegationDAO delegationDAO;
8591

8692
protected final AccessTokenDAO accessTokenDAO;
@@ -115,6 +121,7 @@ public UserSelfLogic(
115121
provisioningManager,
116122
encryptorManager,
117123
confParamOps);
124+
this.securityProperties = securityProperties;
118125
this.delegationDAO = delegationDAO;
119126
this.accessTokenDAO = accessTokenDAO;
120127
this.resourceDAO = resourceDAO;
@@ -131,9 +138,34 @@ public UserSelfLogic(
131138
public Self read() {
132139
UserTO authenticated = binder.getAuthenticatedUserTO();
133140

141+
Map<String, Set<String>> authorizations;
142+
if (securityProperties.getAnonymousUser().equals(AuthContextUtils.getUsername())) {
143+
authorizations = AuthContextUtils.getAuthorizations();
144+
} else {
145+
// group manager Realms together, to avoid unwanted enumeration of managed anys
146+
authorizations = AuthContextUtils.getAuthorities().stream().
147+
map(authority -> {
148+
NormalizedRealms normalized = NormalizedRealms.of(authority.getRealms());
149+
150+
SyncopeGrantedAuthority updated = new SyncopeGrantedAuthority(authority.getAuthority());
151+
updated.addRealms(normalized.realms());
152+
153+
normalized.managerRealms().stream().
154+
map(ManagerRealm::of).
155+
flatMap(Optional::stream).
156+
filter(r -> !updated.getRealms().contains(r.realmPath())).
157+
map(r -> r.realmPath() + '@').
158+
forEach(updated::addRealm);
159+
160+
return updated;
161+
}).
162+
filter(authority -> !authority.getRealms().isEmpty()).
163+
collect(Collectors.toMap(SyncopeGrantedAuthority::getAuthority, SyncopeGrantedAuthority::getRealms));
164+
}
165+
134166
return new Self(
135167
authenticated,
136-
POJOHelper.serialize(AuthContextUtils.getAuthorizations()),
168+
POJOHelper.serialize(authorizations),
137169
POJOHelper.serialize(delegationDAO.findValidDelegating(authenticated.getKey(), OffsetDateTime.now())));
138170
}
139171

‎core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ public static Map<String, Set<String>> getAuthorizations() {
9292
map(authentication -> authentication.getAuthorities().stream().
9393
filter(SyncopeGrantedAuthority.class::isInstance).
9494
map(SyncopeGrantedAuthority.class::cast).
95-
collect(Collectors.toMap(SyncopeGrantedAuthority::getAuthority,
95+
collect(Collectors.toMap(
96+
SyncopeGrantedAuthority::getAuthority,
9697
SyncopeGrantedAuthority::getRealms))).
9798
orElseGet(Map::of);
9899
}

‎fit/core-reference/src/test/java/org/apache/syncope/fit/core/ManagerITCase.java‎

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Optional;
2828
import java.util.Set;
2929
import java.util.function.Consumer;
30+
import org.apache.commons.lang3.StringUtils;
3031
import org.apache.syncope.client.lib.SyncopeClient;
3132
import org.apache.syncope.client.lib.SyncopeClient.Self;
3233
import org.apache.syncope.common.lib.SyncopeClientException;
@@ -39,12 +40,10 @@
3940
import org.apache.syncope.common.lib.to.MembershipTO;
4041
import org.apache.syncope.common.lib.to.PagedResult;
4142
import org.apache.syncope.common.lib.to.UserTO;
42-
import org.apache.syncope.common.lib.types.AnyTypeKind;
4343
import org.apache.syncope.common.lib.types.ClientExceptionType;
4444
import org.apache.syncope.common.lib.types.IdRepoEntitlement;
4545
import org.apache.syncope.common.rest.api.beans.AnyQuery;
4646
import org.apache.syncope.common.rest.api.service.UserService;
47-
import org.apache.syncope.core.persistence.api.utils.RealmUtils;
4847
import org.apache.syncope.fit.AbstractITCase;
4948
import org.junit.jupiter.api.Test;
5049

@@ -75,10 +74,8 @@ private static void check(
7574
Self self = managerClient.self();
7675
Set<String> managerRealms = self.entitlements().get(IdRepoEntitlement.USER_SEARCH);
7776
assertEquals(1, managerRealms.size());
78-
RealmUtils.ManagerRealm realm = RealmUtils.ManagerRealm.of(managerRealms.iterator().next()).orElseThrow();
79-
assertEquals(SyncopeConstants.ROOT_REALM, realm.realmPath());
80-
assertEquals(AnyTypeKind.USER, realm.kind());
81-
assertEquals(managedKey, realm.anyKey());
77+
assertTrue(managerRealms.iterator().next().endsWith("@"));
78+
assertEquals(SyncopeConstants.ROOT_REALM, StringUtils.substringBefore(managerRealms.iterator().next(), "@"));
8279

8380
selfCheck.ifPresent(checker -> checker.accept(self));
8481

@@ -152,11 +149,10 @@ public void uManager() {
152149
Optional.of(self -> {
153150
Set<String> managerRealms = self.entitlements().get(IdRepoEntitlement.GROUP_READ);
154151
assertEquals(1, managerRealms.size());
155-
RealmUtils.ManagerRealm realm = RealmUtils.ManagerRealm.of(managerRealms.iterator().next()).
156-
orElseThrow();
157-
assertEquals(SyncopeConstants.ROOT_REALM, realm.realmPath());
158-
assertEquals(AnyTypeKind.GROUP, realm.kind());
159-
assertEquals(group.getKey(), realm.anyKey());
152+
assertTrue(managerRealms.iterator().next().endsWith("@"));
153+
assertEquals(
154+
SyncopeConstants.ROOT_REALM,
155+
StringUtils.substringBefore(managerRealms.iterator().next(), "@"));
160156
}));
161157
}
162158

0 commit comments

Comments
 (0)