Untitled
unknown
plain_text
a year ago
24 kB
7
Indexable
package com.trendmicro.serapis.admin.apiservice.api.emailnotification;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.forescout.soarcore.model.EmailNotificationResponse;
import com.forescout.soarcore.model.SoarEmailRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import com.trendmicro.serapis.apiservice.api.exceptions.EntityNotFoundException;
import com.trendmicro.serapis.apiservice.security.AdminSecureApi;
import com.trendmicro.serapis.apiservice.security.IdParam;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.RequestBody;
@Path("/admin/accounts/{accountId}/emailnotifications")
@Produces({MediaType.TEXT_PLAIN})
@io.swagger.annotations.Api()
@Component
public class SoarEmailNotificationAdminApi {
private final SoarEmailNotificationAdminApiService delegate;
public SoarEmailNotificationAdminApi(SoarEmailNotificationAdminApiService delegate) {
this.delegate = delegate;
}
@POST
@Path("/send")
@Produces({MediaType.APPLICATION_JSON})
@AdminSecureApi(hasAccountIdParameter = true)
public Response publishNotification(@ApiParam(value = "Id of the account",
required = true) @PathParam("accountId") @IdParam String accountId,
@RequestBody SoarEmailRequest soarEmailRequest)
throws EntityNotFoundException {
try {
delegate.validateRecipients(soarEmailRequest.recipients());
EmailNotificationResponse emailNotificationResponse = delegate.sendEmailNotification(accountId,soarEmailRequest);
return Response.status(Response.Status.OK).entity(emailNotificationResponse).build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Error sending email: " + e.getMessage()).build();
}
}
}
package com.trendmicro.serapis.admin.apiservice.api.emailnotification;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.forescout.soarcore.model.EmailNotificationData;
import com.forescout.soarcore.model.EmailNotificationDetails;
import com.forescout.soarcore.model.EmailNotificationRecipients;
import com.forescout.soarcore.model.EmailNotificationResponse;
import com.forescout.soarcore.model.SoarEmailRequest;
import com.trendmicro.serapis.admin.apiservice.api.accounts.AccountsAdminApiService;
import com.trendmicro.serapis.apiservice.api.inappnotifications.model.NotificationAttributes;
import com.trendmicro.serapis.apiservice.database.UserRepositoryService;
import com.trendmicro.serapis.apiservice.database.entities.UserDao;
import com.trendmicro.serapis.apiservice.util.NotificationPublisher;
import com.trendmicro.serapis.apiservice.util.UuidUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.trendmicro.serapis.apiservice.api.accounts.model.Account;
import com.trendmicro.serapis.apiservice.api.exceptions.EntityNotFoundException;
import com.trendmicro.serapis.apiservice.database.AccountRepositoryService;
import com.trendmicro.serapis.apiservice.database.InAppNotificationRepositoryService;
@Service
public class SoarEmailNotificationAdminApiService {
private static final Logger log = LoggerFactory.getLogger(SoarEmailNotificationAdminApiService.class);
private final InAppNotificationRepositoryService inAppNotificationRepositoryService;
@Autowired
private final AccountsAdminApiService accountRepositoryService;
private final NotificationPublisher notificationPublisher;
private final UserRepositoryService userRepositoryService;
public SoarEmailNotificationAdminApiService(InAppNotificationRepositoryService inAppNotificationRepositoryService,
AccountsAdminApiService accountRepositoryService,
NotificationPublisher notificationPublisher,
UserRepositoryService userRepositoryService) throws EntityNotFoundException {
this.inAppNotificationRepositoryService = inAppNotificationRepositoryService;
this.accountRepositoryService = accountRepositoryService;
this.notificationPublisher = notificationPublisher;
this.userRepositoryService = userRepositoryService;
}
public EmailNotificationResponse sendEmailNotification(String accountId, SoarEmailRequest soarEmailRequest) throws EntityNotFoundException {
List<Account> accounts = getAccountDetails(soarEmailRequest.recipients());
Account account = accountRepositoryService.getAccount(accountId);
return sendEmailNotificationPrivileged(accountId, soarEmailRequest, accounts, account);
}
private EmailNotificationResponse sendEmailNotificationPrivileged(String accountId, SoarEmailRequest soarEmailRequest, List<Account> accounts, Account account) throws EntityNotFoundException {
Set<UserDao> setOfUsers = getUserDaosPrivileged(accounts);
Set<EmailNotificationRecipients> recipients = getRecipients(setOfUsers);
EmailNotificationDetails emailNotificationDetails = new EmailNotificationDetails(soarEmailRequest.emailSubject(), soarEmailRequest.emailBody());
notifyEmailNotificationsToRecipients(recipients,emailNotificationDetails,account.getName());
EmailNotificationResponse response = new EmailNotificationResponse();
response.setAccountId(accountId);
response.setSubject(emailNotificationDetails.subject());
response.setBody(emailNotificationDetails.body());
log.info("Email notification sent successfully to {} recipients for account {}", recipients.size(), account.getId());
return response;
}
public List<Account> getAccountDetails(List<String> accountIds) throws EntityNotFoundException {
List<Account> accounts = new ArrayList<>();
for (String accountId : accountIds) {
Account account = accountRepositoryService.getAccount(accountId);
accounts.add(account);
}
return accounts;
}
public void validateRecipients(List<String> accountIds) throws EntityNotFoundException {
for (String accountId : accountIds) {
Account account = accountRepositoryService.getAccount(accountId);
if (account == null) {
throw new EntityNotFoundException("Account ID not found: " + accountId);
}
}
}
private Set<UserDao> getUserDaosPrivileged(List<Account> accounts) {
Set<Set<String>> userIds = accounts.stream().map(acc -> acc.getUserIds()).collect(Collectors.toSet());
Set<List<UserDao>> users = userIds.stream().map(u -> {
try {
return userRepositoryService.readUserDaosByIds(u);
} catch (EntityNotFoundException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toSet());
Set<UserDao> setOfUsers = new HashSet<>();
for (List<UserDao> userList : users) {
setOfUsers.addAll(userList);
}
return setOfUsers;
}
private Set<EmailNotificationRecipients> getRecipients(Set<UserDao> setOfUsers) {
return setOfUsers.stream().map(usr -> new EmailNotificationRecipients(UuidUtils.toStringNoDashes(usr.getId()), usr.getEmail())).collect(Collectors.toSet());
}
private void notifyEmailNotificationsToRecipients(Set<EmailNotificationRecipients> recipients, EmailNotificationDetails notificationDetails, String accountName) {
EmailNotificationData notificationData = new EmailNotificationData(notificationDetails, recipients);
NotificationAttributes attributes = new NotificationAttributes(false, true);
if (!recipients.isEmpty()) {
notificationPublisher
.notifyEmailNotificationsToRecipients(notificationData, attributes);
} else {
log.warn(
"There are no users to notify while attempting to notify the email notifications to the users. Account Name- {}",
accountName);
}
}
}
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.forescout.soarcore.model.EmailNotificationData;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
@@ -251,6 +252,19 @@ public void notifyUserGroupUnassignedFromAccount(Set<String> emailsToNotify,
publishNotification(NotificationType.USER_GROUP_REMOVED_FROM_ACCOUNT, data);
}
public void notifyEmailNotificationsToRecipients(EmailNotificationData messageData, NotificationAttributes attributes) {
log.debug("NotificationPublisher: notifyEmailNotificationsToRecipients");
final String data = getDataForEmailNotification(messageData);
publishNotification(NotificationType.SOAR_ACTION_EXECUTION_NOTIFICATION, data, attributes.isEmail(), attributes.isInApp());
}
private String getDataForEmailNotification(EmailNotificationData data) {
// Use a LinkedHashMap to maintain order of the properties.
// The properties are displayed in the email in the order they are added to the map.
final Map<String, Object> notificationProperties = new LinkedHashMap<>();
notificationProperties.put(NotificationAttribute.RECIPIENTS.getDisplayName(), data.recipients());
notificationProperties.put(NotificationAttribute.NOTIFICATION_DETAILS.getDisplayName(), data.notification());
return convertNotificationPropertiesToJsonString(notificationProperties);
}
public void notifyUserAddedToAccount(Set<String> emailsToNotify,
String userEmail,
String roleName,
package com.trendmicro.serapis.admin.apiservice.emailnotification;
import com.trendmicro.serapis.admin.apiservice.api.accounts.AccountsAdminApiService;
import com.trendmicro.serapis.admin.apiservice.api.emailnotification.SoarEmailNotificationAdminApiService;
import com.trendmicro.serapis.apiservice.ApiServiceApplication;
import com.trendmicro.serapis.apiservice.api.exceptions.AccountManagerException;
import com.trendmicro.serapis.apiservice.api.exceptions.ElasticsearchException;
import com.trendmicro.serapis.apiservice.api.exceptions.GroupApiException;
import com.trendmicro.serapis.apiservice.api.exceptions.InvalidParameterException;
import com.trendmicro.serapis.apiservice.api.users.model.User;
import com.trendmicro.serapis.apiservice.database.AccountRepositoryService;
import com.trendmicro.serapis.apiservice.security.SecurityUtil;
import com.trendmicro.serapis.apiservice.testutils.RandomStringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.forescout.soarcore.model.*;
import com.trendmicro.serapis.apiservice.api.accounts.model.Account;
import com.trendmicro.serapis.apiservice.api.exceptions.EntityNotFoundException;
import com.trendmicro.serapis.apiservice.database.AccountRepositoryService;
import com.trendmicro.serapis.apiservice.database.InAppNotificationRepositoryService;
import com.trendmicro.serapis.apiservice.database.UserRepositoryService;
import com.trendmicro.serapis.apiservice.database.entities.UserDao;
import com.trendmicro.serapis.apiservice.util.NotificationPublisher;
import com.trendmicro.serapis.apiservice.util.UuidUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import java.io.IOException;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
@SpringBootTest(classes = ApiServiceApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(value = "h2test")
public class SoarEmailNotificationAdminApiServiceTest {
@Mock
private AccountsAdminApiService accountRepositoryService;
@Mock
private NotificationPublisher notificationPublisher;
@Mock
private UserRepositoryService userRepositoryService;
@InjectMocks
private SoarEmailNotificationAdminApiService soarEmailNotificationAdminApiService;
@Autowired
private SecurityUtil securityUtil;
private String accountId;
private SoarEmailRequest soarEmailRequest;
private static final String TEST_ACCOUNT_ID = UuidUtils.toStringNoDashes(UUID.randomUUID());
private List<Account> mockAccounts;
private Set<UserDao> mockUserDaos;
private List<String> mockAccountIds;
private Set<EmailNotificationRecipients> mockRecipients;
private Account account;
private User administratorUser;
private User editorUser;
@BeforeEach
void setUp() throws EntityNotFoundException, InvalidParameterException, AccountManagerException, GroupApiException, IOException, ElasticsearchException {
MockitoAnnotations.openMocks(this);
// Common test data
accountId = "test-account-id";
Pair<Account, User> jUnitUser = securityUtil.createAuthenticationAndAccount("junit@test.com",
"JUnit_User",
RandomStringUtils.randomAlphanumeric(20),
"fake-es-address-1",
RandomStringUtils.generateDomainListFromEmails(Arrays.asList("junit@test.com")));
account = jUnitUser.getLeft();
accountId = account.getId();
editorUser = jUnitUser.getRight();
mockAccounts = Arrays.asList(account);
mockAccountIds = Arrays.asList(accountId);
soarEmailRequest = new SoarEmailRequest(
"Test Subject",
"Test Body",
List.of(accountId)
);
// Mocking dependencies
when(accountRepositoryService.getAccount(accountId)).thenReturn(account);
// when(accountRepositoryService.read("recipient-account-id")).thenReturn(mockAccount);
// when(userRepositoryService.readUserDaosByIds(Set.of("user-1"))).thenReturn(List.of(new UserDao("user-1", "user1@example.com")));
}
@Test
void testSendEmailNotification_Success() throws EntityNotFoundException {
// when(soarEmailNotificationAdminApiService.getAccountDetails(mockAccountIds)).thenReturn(mockAccounts);
EmailNotificationResponse response = soarEmailNotificationAdminApiService.sendEmailNotification(accountId, soarEmailRequest);
assertEquals(accountId, response.getAccountId());
assertEquals("Test Subject", response.getSubject());
assertEquals("Test Body", response.getBody());
verify(notificationPublisher, times(1))
.notifyEmailNotificationsToRecipients(any(EmailNotificationData.class), any());
}
@Test
void testSendEmailNotification_EntityNotFoundException() throws EntityNotFoundException {
when(accountRepositoryService.getAccount(accountId)).thenThrow(new EntityNotFoundException("Account ID not found"));
SoarEmailRequest invalidRequest = new SoarEmailRequest(
"Subject",
"Body",
List.of(accountId)
);
assertThrows(EntityNotFoundException.class, () ->
soarEmailNotificationAdminApiService.sendEmailNotification(accountId, invalidRequest));
}
@Test
void testValidateRecipients_ValidRecipients() throws EntityNotFoundException {
soarEmailNotificationAdminApiService.validateRecipients(mockAccountIds);
verify(accountRepositoryService, times(1)).getAccount("recipient-account-id");
}
@Test
void testValidateRecipients_InvalidRecipient() throws EntityNotFoundException {
when(accountRepositoryService.getAccount("invalid-account-id")).thenThrow(new EntityNotFoundException("Account ID not found"));
List<String> invalidAccountIds = List.of("invalid-account-id");
assertThrows(EntityNotFoundException.class, () ->
soarEmailNotificationAdminApiService.validateRecipients(invalidAccountIds));
}
// @Test
// void testNotifyEmailNotificationsToRecipients_NoRecipients() {
// Set<EmailNotificationRecipients> emptyRecipients = Collections.emptySet();
// soarEmailNotificationAdminApiService.notifyEmailNotificationsToRecipients(emptyRecipients, new EmailNotificationDetails("Test", "Body"), "Test Account");
//
// verify(notificationPublisher, never()).notifyEmailNotificationsToRecipients(any(), any());
// }
}
package com.trendmicro.serapis.admin.apiservice.emailnotification;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doNothing;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import com.forescout.soarcore.model.EmailNotificationResponse;
import com.forescout.soarcore.model.SoarEmailRequest;
import com.trendmicro.serapis.admin.apiservice.api.emailnotification.SoarEmailNotificationAdminApiService;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.trendmicro.serapis.apiclient.TaskSchedulerApiClient;
import com.trendmicro.serapis.apiservice.ApiServiceApplication;
import com.trendmicro.serapis.apiservice.api.accounts.model.Account;
import com.trendmicro.serapis.apiservice.api.exceptions.AccountManagerException;
import com.trendmicro.serapis.apiservice.api.exceptions.ElasticsearchException;
import com.trendmicro.serapis.apiservice.api.exceptions.EntityNotFoundException;
import com.trendmicro.serapis.apiservice.api.exceptions.GroupApiException;
import com.trendmicro.serapis.apiservice.api.exceptions.InvalidParameterException;
import com.trendmicro.serapis.apiservice.api.users.model.User;
import com.trendmicro.serapis.apiservice.security.SecurityUtil;
import com.trendmicro.serapis.apiservice.util.UuidUtils;
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ApiServiceApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(value = "h2test")
public class SoarEmailNotificationAdminApiTests {
@Autowired
private TestRestTemplate restClient;
private static final String TEST_ACCOUNT_ID = UuidUtils.toStringNoDashes(UUID.randomUUID());
private HttpHeaders headers;
@Autowired
private SecurityUtil securityUtil;
private Account account;
@MockBean
private SoarEmailNotificationAdminApiService delegate;
private SoarEmailRequest testEmailRequest;
@BeforeEach
void setup() throws InvalidParameterException, EntityNotFoundException, IOException,
AccountManagerException, ElasticsearchException, GroupApiException {
Pair<Account, User> result = securityUtil.createAuthenticationAndAccount();
User user = result.getRight();
account = result.getLeft();
headers = securityUtil.createAuthorizedHttpHeaders(user.getUsername());
testEmailRequest = new SoarEmailRequest(
"Test Subject",
"Test Body",
List.of(TEST_ACCOUNT_ID)
);
}
@Test
void testPublishNotificationSuccess() throws EntityNotFoundException {
// Arrange
doNothing().when(delegate).validateRecipients(testEmailRequest.recipients());
EmailNotificationResponse responseMock = new EmailNotificationResponse(TEST_ACCOUNT_ID,"success", "Done", Instant.now());
Mockito.when(delegate.sendEmailNotification(Mockito.eq(TEST_ACCOUNT_ID), Mockito.any()))
.thenReturn(responseMock);
HttpEntity<SoarEmailRequest> requestEntity = new HttpEntity<>(testEmailRequest, headers);
// Act
ResponseEntity<EmailNotificationResponse> response = restClient.exchange(
String.format("/api/admin/accounts/%s/emailnotifications/send", TEST_ACCOUNT_ID),
HttpMethod.POST,
requestEntity,
EmailNotificationResponse.class
);
// Assert
assertEquals(HttpStatus.OK, response.getStatusCode());
}
@Test
void testPublishNotificationValidationFailure() throws EntityNotFoundException {
// Arrange
Mockito.doThrow(new IllegalArgumentException())
.when(delegate)
.validateRecipients(Mockito.any());
HttpEntity<SoarEmailRequest> requestEntity = new HttpEntity<>(testEmailRequest, headers);
// Act
ResponseEntity<String> response = restClient.exchange(
String.format("/api/admin/accounts/%s/emailnotifications/send", TEST_ACCOUNT_ID),
HttpMethod.POST,
requestEntity,
String.class
);
// Assert
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
}
@Test
void testPublishNotificationEntityNotFound() throws EntityNotFoundException {
// Arrange
Mockito.doNothing().when(delegate).validateRecipients(Mockito.any());
Mockito.doThrow(new RuntimeException())
.when(delegate)
.sendEmailNotification(Mockito.eq(TEST_ACCOUNT_ID), Mockito.any());
HttpEntity<SoarEmailRequest> requestEntity = new HttpEntity<>(testEmailRequest, headers);
// Act
ResponseEntity<String> response = restClient.exchange(
String.format("/api/admin/accounts/%s/emailnotifications/send", TEST_ACCOUNT_ID),
HttpMethod.POST,
requestEntity,
String.class
);
// Assert
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
}
@Test
void testPublishNotificationMissingAccountId() {
// Act
ResponseEntity<String> response = restClient.exchange(
"/api/admin/accounts//emailnotifications/send",
HttpMethod.POST,
new HttpEntity<>(testEmailRequest, headers),
String.class
);
// Assert
assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
}
}Editor is loading...
Leave a Comment