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

DST-16098 Send Domain Event when username is changed #797

Merged
merged 6 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package uk.co.bconline.ndelius.model.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.time.LocalDateTime;

@Getter
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "DOMAIN_EVENT")
public class DomainEventEntity
{
@Id
@Column(name = "DOMAIN_EVENT_ID")
@SequenceGenerator(name = "DOMAIN_EVENT_ID_SEQ", sequenceName = "DOMAIN_EVENT_ID_SEQ", allocationSize = 1)
@GeneratedValue(generator = "DOMAIN_EVENT_ID_SEQ")
private Long id;

@Column(name = "MESSAGE_BODY")
private String messageBody;

@Column(name = "MESSAGE_ATTRIBUTES")
private String messageAttributes;

@ManyToOne()
@JoinColumn(name = "DOMAIN_EVENT_TYPE_ID", insertable = false, updatable = false)
private ReferenceDataEntity domainEventType;

@Column(name = "DOMAIN_EVENT_TYPE_ID")
private Long domainEventTypeId;

@Column(name = "CREATED_DATETIME")
private LocalDateTime createdDateTime;

@Column(name = "FAILED_PUBLISHING")
private Boolean failedPublishing;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package uk.co.bconline.ndelius.model.notification;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DomainEvent
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we delete this now too?

{
private Long id;
private String messageBody;
private String messageAttributes;
private Long domainEventTypeId;
private LocalDateTime createdDateTime;
private Boolean failedPublishing;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package uk.co.bconline.ndelius.model.notification;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class HmppsDomainEvent
{
private String eventType;
private int version;
private String description;
private String occurredAt;
private Map<String, String> additionalInformation;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package uk.co.bconline.ndelius.model.notification;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum HmppsDomainEventType
{
UMT_USERNAME_CHANGED("probation-user.username.changed", "The username for a probation user has been changed");

private final String eventType;
private final String eventDescription;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package uk.co.bconline.ndelius.repository.db;

import org.springframework.data.jpa.repository.JpaRepository;
import uk.co.bconline.ndelius.model.entity.DomainEventEntity;

public interface DomainEventRepository extends JpaRepository<DomainEventEntity, Long>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package uk.co.bconline.ndelius.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import uk.co.bconline.ndelius.model.notification.HmppsDomainEventType;

import java.util.Map;

public interface DomainEventService
{
void insertDomainEvent(HmppsDomainEventType eventType, Map<String, String> attributes) throws JsonProcessingException;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.co.bconline.ndelius.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import uk.co.bconline.ndelius.model.SearchResult;
import uk.co.bconline.ndelius.model.entry.GroupEntry;
import uk.co.bconline.ndelius.model.entry.UserEntry;
Expand All @@ -19,5 +20,5 @@ public interface UserEntryService
Set<GroupEntry> getUserGroups(String username);
Map<String, UserEntry> export();
void save(UserEntry user);
void save(String username, UserEntry user);
void save(String username, UserEntry user) throws JsonProcessingException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package uk.co.bconline.ndelius.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import uk.co.bconline.ndelius.model.entity.DomainEventEntity;
import uk.co.bconline.ndelius.model.notification.HmppsDomainEvent;
import uk.co.bconline.ndelius.model.notification.HmppsDomainEventType;
import uk.co.bconline.ndelius.repository.db.DomainEventRepository;
import uk.co.bconline.ndelius.repository.db.ReferenceDataRepository;
import uk.co.bconline.ndelius.service.DomainEventService;

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

@Slf4j
@Service
public class DomainEventServiceImpl implements DomainEventService
{
private final ReferenceDataRepository referenceDataRepository;

private final DomainEventRepository domainEventRepository;

private final ObjectMapper mapper;

private static final String DOMAIN_EVENT_TYPE_REF_DATA_CODE_SET = "DOMAIN EVENT TYPE";

@Autowired
public DomainEventServiceImpl(
ReferenceDataRepository referenceDataRepository,
DomainEventRepository domainEventRepository,
ObjectMapper mapper) {
this.referenceDataRepository = referenceDataRepository;
this.domainEventRepository = domainEventRepository;
this.mapper = mapper;
}

@Override
public void insertDomainEvent(HmppsDomainEventType eventType, Map<String, String> additionalInformation) throws JsonProcessingException
{
val type = referenceDataRepository.findByCodeAndReferenceDataMasterCodeSetName(eventType.getEventType(), DOMAIN_EVENT_TYPE_REF_DATA_CODE_SET)
.orElseThrow(() -> new IllegalStateException("Reference data for domain event type " + eventType.getEventType() + " not found"));
val message = HmppsDomainEvent.builder()
.eventType(eventType.getEventType())
.description(eventType.getEventDescription())
.occurredAt(ZonedDateTime.now().format(DateTimeFormatter.ISO_ZONED_DATE_TIME))
.additionalInformation(additionalInformation)
.version(1)
.build();
val attributes = Map.of("eventType", Map.of("Type", "String", "Value", eventType.getEventType()));
val entity = DomainEventEntity.builder()
.messageBody(mapper.writeValueAsString(message))
.messageAttributes(mapper.writeValueAsString(attributes))
.domainEventTypeId(type.getId())
.createdDateTime(LocalDateTime.now())
.build();

domainEventRepository.save(entity);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.co.bconline.ndelius.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
Expand All @@ -20,15 +21,18 @@
import uk.co.bconline.ndelius.model.entry.UserEntry;
import uk.co.bconline.ndelius.model.entry.UserPreferencesEntry;
import uk.co.bconline.ndelius.model.entry.projections.UserHomeAreaProjection;
import uk.co.bconline.ndelius.model.notification.HmppsDomainEventType;
import uk.co.bconline.ndelius.repository.ldap.UserEntryRepository;
import uk.co.bconline.ndelius.repository.ldap.UserPreferencesRepository;
import uk.co.bconline.ndelius.service.DomainEventService;
import uk.co.bconline.ndelius.service.GroupService;
import uk.co.bconline.ndelius.service.UserEntryService;
import uk.co.bconline.ndelius.service.UserRoleService;
import uk.co.bconline.ndelius.transformer.SearchResultTransformer;
import uk.co.bconline.ndelius.util.SearchUtils;

import javax.naming.Name;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -68,6 +72,7 @@ public class UserEntryServiceImpl implements UserEntryService, UserDetailsServic
private final LdapTemplate ldapTemplate;
private final LdapTemplate exportLdapTemplate;
private final SearchResultTransformer searchResultTransformer;
private final DomainEventService domainEventService;

@Autowired
public UserEntryServiceImpl(
Expand All @@ -77,14 +82,16 @@ public UserEntryServiceImpl(
GroupService groupService,
LdapTemplate ldapTemplate,
@Qualifier("exportLdapTemplate") LdapTemplate exportLdapTemplate,
SearchResultTransformer searchResultTransformer) {
SearchResultTransformer searchResultTransformer,
DomainEventService domainEventService) {
this.userRepository = userRepository;
this.preferencesRepository = preferencesRepository;
this.userRoleService = userRoleService;
this.groupService = groupService;
this.ldapTemplate = ldapTemplate;
this.exportLdapTemplate = exportLdapTemplate;
this.searchResultTransformer = searchResultTransformer;
this.domainEventService = domainEventService;
}

@Override
Expand Down Expand Up @@ -253,7 +260,8 @@ public void save(UserEntry user) {
}

@Override
public void save(String existingUsername, UserEntry user) {
public void save(String existingUsername, UserEntry user) throws JsonProcessingException
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry - could we annotate insertDomainEvent with @SneakyThrows so that we don't have to declare this exception all the way up?

Suggested change
public void save(String existingUsername, UserEntry user) throws JsonProcessingException
{
public void save(String existingUsername, UserEntry user)
{

// Keep hold of the new username, if it's different we'll rename it later
val newUsername = user.getUsername();
user.setUsername(existingUsername);
Expand All @@ -267,6 +275,13 @@ public void save(String existingUsername, UserEntry user) {
val newDn = LdapNameBuilder.newInstance(getDn(newUsername)).build();
log.debug("Renaming LDAP entry from {} to {}", oldDn, newDn);
ldapTemplate.rename(oldDn, newDn);

// Send Domain event
val additionalInformation = Map.of(
"fromUsername", existingUsername,
"toUsername", newUsername
);
domainEventService.insertDomainEvent(HmppsDomainEventType.UMT_USERNAME_CHANGED, additionalInformation);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package uk.co.bconline.ndelius.transformer;

import org.springframework.stereotype.Component;
import uk.co.bconline.ndelius.model.entity.DomainEventEntity;
import uk.co.bconline.ndelius.model.notification.DomainEvent;

import static java.util.Optional.ofNullable;

@Component
public class DomainEventTransformer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we delete this class now?

{
public DomainEventEntity map(DomainEvent domainEvent)
{
return ofNullable(domainEvent)
.map(de -> DomainEventEntity.builder()
.messageBody(de.getMessageBody())
.messageAttributes(de.getMessageAttributes())
.domainEventTypeId(de.getDomainEventTypeId())
.createdDateTime(de.getCreatedDateTime())
.failedPublishing(de.getFailedPublishing())
.build())
.orElse(null);
}

}
Loading