Commit abf133f8 authored by michael.simon's avatar michael.simon
Browse files

add function to link accounts

add uidNumber to identity.
parent 7efcaf6b
......@@ -21,4 +21,5 @@ public interface IdentityDao extends BaseDao<IdentityEntity, Long> {
List<IdentityEntity> findMissingTwoFaUserId();
List<IdentityEntity> findByMissingPrefferedUser(int limit);
List<IdentityEntity> findMissingUidNumber();
}
......@@ -42,7 +42,13 @@ public class JpaIdentityDao extends JpaBaseDao<IdentityEntity, Long> implements
public List<IdentityEntity> findMissingTwoFaUserId() {
return em.createQuery("select e from IdentityEntity e where e.twoFaUserId is null or e.twoFaUserName is null").getResultList();
}
@Override
@SuppressWarnings({"unchecked"})
public List<IdentityEntity> findMissingUidNumber() {
return em.createQuery("select e from IdentityEntity e where e.uidNumber is null").getResultList();
}
@Override
@SuppressWarnings({"unchecked"})
public List<IdentityEntity> findByMissingPrefferedUser(int limit) {
......
......@@ -43,7 +43,10 @@ public class IdentityEntity extends AbstractBaseEntity {
@ManyToOne(targetEntity = UserEntity.class)
@JoinColumn(name = "pref_user_id")
private UserEntity prefUser;
@Column(name = "uid_number")
private Integer uidNumber;
public Set<UserEntity> getUsers() {
return users;
}
......@@ -83,4 +86,12 @@ public class IdentityEntity extends AbstractBaseEntity {
public void setPrefUser(UserEntity prefUser) {
this.prefUser = prefUser;
}
public Integer getUidNumber() {
return uidNumber;
}
public void setUidNumber(Integer uidNumber) {
this.uidNumber = uidNumber;
}
}
......@@ -125,6 +125,29 @@ public class IdentityServiceImpl extends BaseServiceImpl<IdentityEntity, Long> i
}
logger.info("Add missing 2fa userIds done.");
logger.info("Add missing uidNumbers...");
idList = dao.findMissingUidNumber();
for (IdentityEntity id : idList) {
Set<UserEntity> users = id.getUsers();
if (users == null) {
logger.warn("Identity {} has no users", id.getId());
}
else if (users.size() == 0) {
logger.warn("Identity {} has no users", id.getId());
}
else if (users.size() == 1) {
for(UserEntity user : users) {
id.setUidNumber(user.getUidNumber());
logger.info("Add missing uidNumber {}", id.getUidNumber());
}
}
else {
logger.warn("Add missing uidNumber from identity with more than one account is not supported! Check identity {}", id.getId());
}
}
logger.info("Add missing uidNumbers done.");
logger.info("Migrate ssh pub keys from users to identities...");
List<SshPubKeyEntity> keyList = sshPubKeyDao.findMissingIdentity();
......
......@@ -159,7 +159,8 @@ public class UserCreateServiceImpl implements UserCreateService {
user = samlUserDao.persist(user);
id.setPrefUser(user);
id.setUidNumber(user.getUidNumber());
roleDao.addUserToRole(user, "User");
homeOrgGroupUpdater.updateGroupsForUser(user, attributeMap, auditor);
......
......@@ -13,6 +13,7 @@ package edu.kit.scc.webreg.service.oidc.client;
import java.util.List;
import java.util.Map;
import edu.kit.scc.webreg.entity.identity.IdentityEntity;
import edu.kit.scc.webreg.entity.oidc.OidcUserEntity;
import edu.kit.scc.webreg.exc.UserUpdateException;
......@@ -23,5 +24,8 @@ public interface OidcUserCreateService {
OidcUserEntity preCreateUser(Long rpConfigId,
String locale, Map<String, List<Object>> attributeMap) throws UserUpdateException;
OidcUserEntity createAndLinkUser(IdentityEntity identity, OidcUserEntity user,
Map<String, List<Object>> attributeMap, String executor)
throws UserUpdateException;
}
......@@ -122,18 +122,86 @@ public class OidcUserCreateServiceImpl implements OidcUserCreateService {
return entity;
}
@Override
public OidcUserEntity createAndLinkUser(IdentityEntity identity, OidcUserEntity user,
Map<String, List<Object>> attributeMap, String executor)
throws UserUpdateException {
logger.debug("Creating and link user {} to identity {}", user.getSubjectId(), identity.getId());
identity = identityDao.merge(identity);
UserCreateAuditor auditor = new UserCreateAuditor(auditDao, auditDetailDao, appConfig);
auditor.startAuditTrail(executor);
auditor.setName(getClass().getName() + "-OidcUserCreate-Audit");
auditor.setDetail("Create and link OIDC user " + user.getSubjectId());
createUserInternal(user, attributeMap, executor, auditor);
user.setIdentity(identity);
postCreateUserInternal(user, attributeMap, executor, auditor);
auditor.logAction(user.getEppn(), "CREATE USER", null, null, AuditStatus.SUCCESS);
auditor.finishAuditTrail();
auditor.commitAuditTrail();
UserEvent userEvent = new UserEvent(user);
try {
eventSubmitter.submit(userEvent, EventType.USER_CREATE, executor);
} catch (EventSubmitException e) {
logger.warn("Could not submit event", e);
}
return user;
}
@Override
public OidcUserEntity createUser(OidcUserEntity user,
Map<String, List<Object>> attributeMap, String executor)
throws UserUpdateException {
logger.debug("Creating user {}", user.getSubjectId());
UserCreateAuditor auditor = new UserCreateAuditor(auditDao, auditDetailDao, appConfig);
auditor.startAuditTrail(executor);
auditor.setName(getClass().getName() + "-OidcUserCreate-Audit");
auditor.setDetail("Create OIDC user " + user.getSubjectId());
createUserInternal(user, attributeMap, executor, auditor);
/**
* TODO: Apply mapping rules at this point. At the moment every account gets one
* identity. Should possibly be mapped to existing identity in some cases.
*/
IdentityEntity id = identityDao.createNew();
id = identityDao.persist(id);
user.setIdentity(id);
postCreateUserInternal(user, attributeMap, executor, auditor);
id.setUidNumber(user.getUidNumber());
auditor.logAction(user.getEppn(), "CREATE USER", null, null, AuditStatus.SUCCESS);
auditor.finishAuditTrail();
auditor.commitAuditTrail();
UserEvent userEvent = new UserEvent(user);
try {
eventSubmitter.submit(userEvent, EventType.USER_CREATE, executor);
} catch (EventSubmitException e) {
logger.warn("Could not submit event", e);
}
return user;
}
private void createUserInternal(OidcUserEntity user, Map<String, List<Object>> attributeMap, String executor,
UserCreateAuditor auditor)
throws UserUpdateException {
logger.debug("Creating user {}", user.getSubjectId());
userUpdater.updateUserFromAttribute(user, attributeMap, true, auditor);
/**
......@@ -155,15 +223,11 @@ public class OidcUserCreateServiceImpl implements OidcUserCreateService {
user.setUserStatus(UserStatus.ACTIVE);
user.setLastStatusChange(new Date());
}
/**
* TODO: Apply mapping rules at this point. At the moment every account gets one
* identity. Should possibly be mapped to existing identity in some cases.
*/
IdentityEntity id = identityDao.createNew();
id = identityDao.persist(id);
user.setIdentity(id);
}
private void postCreateUserInternal(OidcUserEntity user, Map<String, List<Object>> attributeMap, String executor,
UserCreateAuditor auditor)
throws UserUpdateException {
user = oidcUserDao.persist(user);
roleDao.addUserToRole(user, "User");
......@@ -172,19 +236,5 @@ public class OidcUserCreateServiceImpl implements OidcUserCreateService {
auditor.setUser(user);
auditor.auditUserCreate();
auditor.logAction(user.getEppn(), "CREATE USER", null, null, AuditStatus.SUCCESS);
auditor.finishAuditTrail();
auditor.commitAuditTrail();
UserEvent userEvent = new UserEvent(user);
try {
eventSubmitter.submit(userEvent, EventType.USER_CREATE, executor);
} catch (EventSubmitException e) {
logger.warn("Could not submit event", e);
}
return user;
}
}
......@@ -24,6 +24,8 @@ import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Inject;
import org.slf4j.Logger;
import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet;
import com.nimbusds.openid.connect.sdk.claims.UserInfo;
......@@ -46,6 +48,9 @@ public class ConnectAccountOidcBean implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private Logger logger;
@Inject
private UserService userService;
......@@ -72,7 +77,7 @@ public class ConnectAccountOidcBean implements Serializable {
@Inject
private UserService service;
private IdentityEntity identity;
private List<UserEntity> userList;
......@@ -122,11 +127,6 @@ public class ConnectAccountOidcBean implements Serializable {
return;
}
if (service.findByEppn(entity.getEppn()) != null) {
errorState = true;
messageGenerator.addResolvedErrorMessage("eppn-blocked", "eppn-blocked-detail", true);
}
IDTokenClaimsSet claims = tokenHelper.claimsFromMap(sessionManager.getAttributeMap());
UserInfo userInfo = tokenHelper.userInfoFromMap(sessionManager.getAttributeMap());
......@@ -145,9 +145,29 @@ public class ConnectAccountOidcBean implements Serializable {
}
public void save() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
public String save() {
logger.debug("Comparing pins {} <-> {}", sessionManager.getAccountLinkingPin(), pin);
if (sessionManager.getAccountLinkingPin() != null && sessionManager.getAccountLinkingPin().equals(pin)) {
/*
* pin is correct, proceed
*/
try {
entity = userCreateService.createAndLinkUser(identity, entity, sessionManager.getAttributeMap(), null);
} catch (UserUpdateException e) {
logger.warn("An error occured whilst creating user", e);
messageGenerator.addResolvedErrorMessage("error_msg", e.toString(), false);
return null;
}
return "user/connect-account-success.xhtml";
}
else {
logger.warn("Pins for identity {} don't match: {} <-> {}", identity.getId(), sessionManager.getAccountLinkingPin(), pin);
messageGenerator.addResolvedErrorMessage("pin-wrong", "pin-wrong-detail", true);
return null;
}
}
public IdentityEntity getIdentity() {
......
......@@ -38,23 +38,31 @@
</p:dataList>
<h3><h:outputText value="#{messages.my_data}:"/></h3>
<div class="panel">
<p:dataTable var="key" value="#{connectAccountOidcBean.printableAttributesList}">
<p:column headerText="#{messages.name}">
#{resourceBundleHelper.resolveMessage(key)}
</p:column>
<p:column headerText="#{messages.value}">
#{connectAccountOidcBean.printableAttributesMap[key]}
</p:column>
</p:dataTable>
</div>
<div class="panel">
<p:dataList var="key" value="#{connectAccountOidcBean.unprintableAttributesMap.keySet().toArray()}">
#{key}: #{connectAccountOidcBean.unprintableAttributesMap[key]}
</p:dataList>
</div>
<p:dataTable var="key" value="#{connectAccountOidcBean.printableAttributesList}">
<p:column headerText="#{messages.name}">
#{resourceBundleHelper.resolveMessage(key)}
</p:column>
<p:column headerText="#{messages.value}">
#{connectAccountOidcBean.printableAttributesMap[key]}
</p:column>
</p:dataTable>
<p:dataList var="key" value="#{connectAccountOidcBean.unprintableAttributesMap.keySet().toArray()}">
#{key}: #{connectAccountOidcBean.unprintableAttributesMap[key]}
</p:dataList>
<h:panelGrid id="oidcBaseData" columns="3" style="margin-top: 8px;">
<p:outputLabel value="#{messages.connect_account_pin}" for="pinBox"/>
<p:inputText id="pinBox" value="#{connectAccountOidcBean.pin}">
<f:validateLength minimum="4"/>
<f:validateRegex pattern="^[a-zA-Z0-9]{4,32}$"/>
</p:inputText>
<p:message for="pinBox"/>
</h:panelGrid>
<p:commandButton id="save" action="#{connectAccountOidcBean.save}" value="#{messages.confirm}" ajax="false"
disabled="#{connectAccountOidcBean.errorState}"/>
disabled="#{connectAccountOidcBean.errorState}" update=":form"/>
</h:form>
</ui:define>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment