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

Add groups enrollment logic to be applied after users registration #793

Merged
merged 11 commits into from
Jul 25, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ public static class RegistrationProperties {

Map<String, RegistrationFieldProperties> fields;

List<DefaultGroup> defaultGroups;

public boolean isShowRegistrationButtonInLoginPage() {
return showRegistrationButtonInLoginPage;
}
Expand Down Expand Up @@ -287,6 +289,14 @@ public Map<String, RegistrationFieldProperties> getFields() {
public void setFields(Map<String, RegistrationFieldProperties> fields) {
this.fields = fields;
}

public List<DefaultGroup> getDefaultGroups() {
return defaultGroups;
}

public void setDefaultGroups(List<DefaultGroup> defaultGroups) {
this.defaultGroups = defaultGroups;
}
}

public static class DeviceCodeProperties {
Expand Down Expand Up @@ -559,6 +569,27 @@ public void setTrackLastUsed(boolean trackLastUsed) {
}
}

public static class DefaultGroup {
private String name;
private String enrollment = "INSERT";

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEnrollment() {
return enrollment;
}

public void setEnrollment(String enrollment) {
this.enrollment = enrollment;
}
}

private String host;

private String issuer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.Objects;

import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
Expand All @@ -51,6 +52,9 @@
import it.infn.mw.iam.audit.events.account.group.GroupMembershipRemovedEvent;
import it.infn.mw.iam.audit.events.account.label.AccountLabelRemovedEvent;
import it.infn.mw.iam.audit.events.account.label.AccountLabelSetEvent;
import it.infn.mw.iam.config.IamProperties;
import it.infn.mw.iam.config.IamProperties.DefaultGroup;
import it.infn.mw.iam.core.group.DefaultIamGroupService;
import it.infn.mw.iam.core.user.exception.CredentialAlreadyBoundException;
import it.infn.mw.iam.core.user.exception.InvalidCredentialException;
import it.infn.mw.iam.core.user.exception.UserAlreadyExistsException;
Expand Down Expand Up @@ -83,12 +87,15 @@ public class DefaultIamAccountService implements IamAccountService, ApplicationE
private final OAuth2TokenEntityService tokenService;
private final IamAccountClientRepository accountClientRepo;
private final NotificationFactory notificationFactory;
private final IamProperties iamProperties;
private final DefaultIamGroupService iamGroupService;

public DefaultIamAccountService(Clock clock, IamAccountRepository accountRepo,
IamGroupRepository groupRepo, IamAuthoritiesRepository authoritiesRepo,
PasswordEncoder passwordEncoder, ApplicationEventPublisher eventPublisher,
OAuth2TokenEntityService tokenService, IamAccountClientRepository accountClientRepo,
NotificationFactory notificationFactory) {
NotificationFactory notificationFactory, IamProperties iamProperties,
DefaultIamGroupService iamGroupService) {

this.clock = clock;
this.accountRepo = accountRepo;
Expand All @@ -99,6 +106,8 @@ public DefaultIamAccountService(Clock clock, IamAccountRepository accountRepo,
this.tokenService = tokenService;
this.accountClientRepo = accountClientRepo;
this.notificationFactory = notificationFactory;
this.iamProperties = iamProperties;
this.iamGroupService = iamGroupService;
}

private void labelSetEvent(IamAccount account, IamLabel label) {
Expand Down Expand Up @@ -181,10 +190,22 @@ public IamAccount createAccount(IamAccount account) {

eventPublisher.publishEvent(new AccountCreatedEvent(this, account,
"Account created for user " + account.getUsername()));


addToDefaultGroups(account);
return account;
}

private void addToDefaultGroups(IamAccount account) {
List<DefaultGroup> defaultGroups = iamProperties.getRegistration().getDefaultGroups();
if (Objects.nonNull(defaultGroups)) {
defaultGroups.forEach(group -> {
if ("INSERT".equalsIgnoreCase(group.getEnrollment())) {
iamGroupService.findByName(group.getName()).ifPresent(iamGroup -> addToGroup(account, iamGroup));
}
});
}
}

protected void removeClientLinks(IamAccount account) {

accountClientRepo.deleteByAccount(account);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.junit.Before;
Expand All @@ -59,13 +60,18 @@
import com.google.common.collect.Sets;

import it.infn.mw.iam.audit.events.account.AccountEndTimeUpdatedEvent;
import it.infn.mw.iam.config.IamProperties;
import it.infn.mw.iam.config.IamProperties.DefaultGroup;
import it.infn.mw.iam.core.group.DefaultIamGroupService;
import it.infn.mw.iam.core.time.TimeProvider;
import it.infn.mw.iam.core.user.DefaultIamAccountService;
import it.infn.mw.iam.core.user.exception.CredentialAlreadyBoundException;
import it.infn.mw.iam.core.user.exception.InvalidCredentialException;
import it.infn.mw.iam.core.user.exception.UserAlreadyExistsException;
import it.infn.mw.iam.notification.NotificationFactory;
import it.infn.mw.iam.persistence.model.IamAccount;
import it.infn.mw.iam.persistence.model.IamAccountGroupMembership;
import it.infn.mw.iam.persistence.model.IamGroup;
import it.infn.mw.iam.persistence.model.IamOidcId;
import it.infn.mw.iam.persistence.model.IamSamlId;
import it.infn.mw.iam.persistence.model.IamSshKey;
Expand All @@ -78,6 +84,8 @@
@RunWith(MockitoJUnitRunner.class)
public class IamAccountServiceTests extends IamAccountServiceTestSupport {

private static final String TEST_GROUP_1 = "Test-group-1";

public static final Instant NOW = Instant.parse("2021-01-01T00:00:00.00Z");

@Mock
Expand Down Expand Up @@ -111,6 +119,14 @@ public class IamAccountServiceTests extends IamAccountServiceTestSupport {

private DefaultIamAccountService accountService;

@Mock
private DefaultIamGroupService iamGroupService;

@Mock
private IamProperties iamProperties;

private IamProperties.RegistrationProperties registrationProperties = new IamProperties.RegistrationProperties();

@Captor
private ArgumentCaptor<ApplicationEvent> eventCaptor;

Expand All @@ -130,9 +146,10 @@ public void setup() {
when(authoritiesRepo.findByAuthority(anyString())).thenReturn(Optional.empty());
when(authoritiesRepo.findByAuthority("ROLE_USER")).thenReturn(Optional.of(ROLE_USER_AUTHORITY));
when(passwordEncoder.encode(any())).thenReturn(PASSWORD);
when(iamProperties.getRegistration()).thenReturn(registrationProperties);

accountService = new DefaultIamAccountService(clock, accountRepo, groupRepo, authoritiesRepo,
passwordEncoder, eventPublisher, tokenService, accountClientRepo, notificationFactory);
passwordEncoder, eventPublisher, tokenService, accountClientRepo, notificationFactory, iamProperties, iamGroupService);
}

@Test(expected = NullPointerException.class)
Expand Down Expand Up @@ -847,4 +864,41 @@ public void testSetEndTimeWorksForNonNullDate() {
assertThat(e.getAccount().getEndTime(), is(newEndTime));
}

@Test
public void testNewAccountAddedToDefaultGroups() {
IamAccount account = cloneAccount(CICCIO_ACCOUNT);

IamGroup testGroup = new IamGroup();
testGroup.setName(TEST_GROUP_1);
DefaultGroup defaultGroup = new DefaultGroup();
defaultGroup.setName(TEST_GROUP_1);
defaultGroup.setEnrollment("INSERT");
List<DefaultGroup> defaultGroups = Arrays.asList(defaultGroup);

registrationProperties.setDefaultGroups(defaultGroups);
when(iamGroupService.findByName(TEST_GROUP_1)).thenReturn(Optional.of(testGroup));

account = accountService.createAccount(account);

assertTrue(getGroup(account).equals(testGroup));
}

private IamGroup getGroup(IamAccount account) {
Optional<IamAccountGroupMembership> groupMembershipOptional = account.getGroups().stream().findFirst();
if (groupMembershipOptional.isPresent()) {
return groupMembershipOptional.get().getGroup();
}
return null;
}

@Test
public void testNoDefaultGroupsAddedWhenDefaultGroupsNotGiven() {
IamAccount account = cloneAccount(CICCIO_ACCOUNT);

account = accountService.createAccount(account);

Optional<IamAccountGroupMembership> groupMembershipOptional = account.getGroups().stream().findFirst();
assertFalse(groupMembershipOptional.isPresent());
}

enricovianello marked this conversation as resolved.
Show resolved Hide resolved
}
Loading