Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
@@ -1,7 +1,8 @@
package hng_java_boilerplate.organisation.controller;

import hng_java_boilerplate.organisation.dto.CreateOrganisationRequestDto;
import hng_java_boilerplate.organisation.dto.CreateOrganisationResponseDto;
import hng_java_boilerplate.organisation.dto.*;
import hng_java_boilerplate.organisation.interfaces.AddUserResponse;
import hng_java_boilerplate.organisation.service.AddUsersToOrganisationService;
import hng_java_boilerplate.organisation.entity.Organisation;
import hng_java_boilerplate.organisation.service.OrganisationService;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -19,6 +20,7 @@
@Tag(name="Organisation", description = "Controller for Organisation")
public class OrganisationController {
private final OrganisationService organisationService;
private final AddUsersToOrganisationService addUsersToOrganisationService;

@PostMapping
@Operation(summary = "create organisation")
Expand All @@ -31,6 +33,18 @@ public ResponseEntity<CreateOrganisationResponseDto> createOrganisation(
);
}

@PostMapping("/{organisationId}/users")
public ResponseEntity<?> addUserToOrganisation(
@PathVariable("organisationId") String organisationId,
@RequestBody @Valid AddUserRequestDTO orgRequest,
Authentication authenticatedUser
) {
AddUserResponse response = addUsersToOrganisationService.addUserToOrganisation(organisationId, orgRequest,
authenticatedUser);

return ResponseEntity.status(HttpStatus.OK).body(response);
}

@GetMapping("/{organisationId}")
public ResponseEntity<?> getOrganisationById(@PathVariable String organisationId) {
Organisation organisation = organisationService.getOrganisationById(organisationId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package hng_java_boilerplate.organisation.dto;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.Builder;

import java.util.List;

@Builder
public record AddUserRequestDTO(
@NotEmpty(message = "User ID cannot be empty")
@Size(min = 1, message = "Provide a valid user ID")
List<String> user_ids
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package hng_java_boilerplate.organisation.dto;

import hng_java_boilerplate.organisation.interfaces.AddUserResponse;
import lombok.Builder;

import java.util.List;

@Builder
public record AddUserResponseDTO(
String status,
String message,
String organization_id,
List<String> users_added_to_organisation,
Integer status_code
) implements AddUserResponse {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package hng_java_boilerplate.organisation.interfaces;

public interface AddUserResponse {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package hng_java_boilerplate.organisation.service;

import hng_java_boilerplate.exception.ConflictException;
import hng_java_boilerplate.exception.NotFoundException;
import hng_java_boilerplate.exception.UnAuthorizedException;
import hng_java_boilerplate.organisation.dto.AddUserRequestDTO;
import hng_java_boilerplate.organisation.dto.AddUserResponseDTO;
import hng_java_boilerplate.organisation.entity.Organisation;
import hng_java_boilerplate.organisation.interfaces.AddUserResponse;
import hng_java_boilerplate.organisation.repository.OrganisationRepository;
import hng_java_boilerplate.user.entity.User;
import hng_java_boilerplate.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class AddUsersToOrganisationService {
private final OrganisationRepository organisationRepository;
private final UserRepository userRepository;

@Transactional
public AddUserResponse addUserToOrganisation(
String organisationId,
AddUserRequestDTO orgRequest,
Authentication authenticatedUser
) {
Organisation organisation = organisationRepository.findById(organisationId).
orElseThrow(() -> new NotFoundException("Organisation with id " + organisationId + " does not exist"));

User user = (User) authenticatedUser.getPrincipal();

if (!organisation.getOwner().equals(user.getId())) {
throw new UnAuthorizedException("User is not owner of the organisation");
}

List<String> addedUserIds = new ArrayList<>();

for (String userId : orgRequest.user_ids()) {
if (organisation.getUsers().stream().anyMatch(user1 -> user1.getId().equals(userId))) {
throw new ConflictException("User with id " + userId + " is already in the organisation");
}

var userExists = userRepository.findById(userId);
if (userExists.isEmpty()) {
throw new NotFoundException("User with id " + userId + " does not exist");
}

organisation.getUsers().add(userExists.get());
userExists.get().getOrganisations().add(organisation);
addedUserIds.add(userId);
}

organisationRepository.save(organisation);

return AddUserResponseDTO.builder()
.status("success")
.message("Users added to organisation")
.organization_id(organisation.getId())
.users_added_to_organisation(addedUserIds)
.status_code(HttpStatus.OK.value())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package hng_java_boilerplate.organisation.service;

import hng_java_boilerplate.exception.ConflictException;
import hng_java_boilerplate.exception.NotFoundException;
import hng_java_boilerplate.exception.UnAuthorizedException;
import hng_java_boilerplate.organisation.dto.AddUserRequestDTO;
import hng_java_boilerplate.organisation.dto.AddUserResponseDTO;
import hng_java_boilerplate.organisation.entity.Organisation;
import hng_java_boilerplate.organisation.repository.OrganisationRepository;
import hng_java_boilerplate.user.entity.User;
import hng_java_boilerplate.user.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.Authentication;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class AddUsersToOrganisationServiceTest {

@Mock
private OrganisationRepository organisationRepository;

@Mock
private UserRepository userRepository;

@Mock
private Authentication authenticatedUser;

@InjectMocks
private AddUsersToOrganisationService addUsersToOrganisationService;

private AddUserRequestDTO orgRequest;
private User user;

@Test
void testAddUserToOrganisation_OrganisationNotFound() {
String organisationId = "b1e009c5-a197-42f9-b9a3-98fc357b5f08";
AddUserRequestDTO orgRequest = new AddUserRequestDTO(List.of("user1", "user2", "user3"));

when(organisationRepository.findById(organisationId)).thenReturn(Optional.empty());

NotFoundException exception = assertThrows(NotFoundException.class, () ->
addUsersToOrganisationService.addUserToOrganisation(organisationId, orgRequest, authenticatedUser));
assertEquals("Organisation with id " + organisationId + " does not exist", exception.getMessage());

verify(organisationRepository).findById(organisationId);
verifyNoMoreInteractions(organisationRepository);
verifyNoInteractions(userRepository);
verifyNoInteractions(authenticatedUser);
}

@Test
void testAddUserToOrganisation_UserNotOwner() {
String organisationId = "b1e009c5-a197-42f9-b9a3-98fc357b5f08";
AddUserRequestDTO orgRequest = new AddUserRequestDTO(List.of("user1", "user2", "user3"));
User activeUser = new User();
activeUser.setId("user-123");

Organisation organisation = new Organisation();
organisation.setOwner("user-456");

when(organisationRepository.findById(organisationId)).thenReturn(Optional.of(organisation));
when(authenticatedUser.getPrincipal()).thenReturn(activeUser);

UnAuthorizedException exception = assertThrows(UnAuthorizedException.class, () ->
addUsersToOrganisationService.addUserToOrganisation(organisationId, orgRequest, authenticatedUser));
assertEquals("User is not owner of the organisation", exception.getMessage());

verify(organisationRepository).findById(organisationId);
verify(authenticatedUser).getPrincipal();
verifyNoMoreInteractions(organisationRepository);
verifyNoMoreInteractions(authenticatedUser);
verifyNoInteractions(userRepository);
}

@Test
void testAddUserToOrganisation_UserAlreadyInOrganisation() {
String organisationId = "b1e009c5-a197-42f9-b9a3-98fc357b5f08";
AddUserRequestDTO orgRequest = new AddUserRequestDTO(List.of("user1", "user2", "user3"));
User activeUser = new User();
activeUser.setId("user-123");

User existingUser = new User();
existingUser.setId("user1");

Organisation organisation = new Organisation();
organisation.setId(organisationId);
organisation.setOwner("user-123");
organisation.setUsers(List.of(existingUser));

when(organisationRepository.findById(organisationId)).thenReturn(Optional.of(organisation));
when(authenticatedUser.getPrincipal()).thenReturn(activeUser);

ConflictException exception = assertThrows(ConflictException.class, () ->
addUsersToOrganisationService.addUserToOrganisation(organisationId, orgRequest, authenticatedUser));
assertEquals("User with id user1 is already in the organisation", exception.getMessage());

verify(organisationRepository).findById(organisationId);
verify(authenticatedUser).getPrincipal();
verifyNoMoreInteractions(organisationRepository);
verifyNoMoreInteractions(authenticatedUser);
verifyNoInteractions(userRepository);
}

@Test
void testAddUserToOrganisation_UserDoesNotExist() {
String organisationId = "b1e009c5-a197-42f9-b9a3-98fc357b5f08";
AddUserRequestDTO orgRequest = new AddUserRequestDTO(List.of("user2"));
User activeUser = new User();
activeUser.setId("user-123");

Organisation organisation = new Organisation();
organisation.setId(organisationId);
organisation.setOwner("user-123");
organisation.setUsers(new ArrayList<>());

when(organisationRepository.findById(organisationId)).thenReturn(Optional.of(organisation));
when(authenticatedUser.getPrincipal()).thenReturn(activeUser);
when(userRepository.findById("user2")).thenReturn(Optional.empty());

NotFoundException exception = assertThrows(NotFoundException.class, () ->
addUsersToOrganisationService.addUserToOrganisation(organisationId, orgRequest, authenticatedUser));
assertEquals("User with id user2 does not exist", exception.getMessage());

verify(organisationRepository).findById(organisationId);
verify(authenticatedUser).getPrincipal();
verify(userRepository).findById("user2");
verifyNoMoreInteractions(organisationRepository);
verifyNoMoreInteractions(authenticatedUser);
verifyNoMoreInteractions(userRepository);
}

@Test
void testAddUserToOrganisation_Successful() {
String organisationId = "b1e009c5-a197-42f9-b9a3-98fc357b5f08";
AddUserRequestDTO orgRequest = new AddUserRequestDTO(List.of("user1", "user2"));
User activeUser = new User();
activeUser.setId("user-123");

Organisation organisation = new Organisation();
organisation.setId(organisationId);
organisation.setOwner("user-123");
organisation.setUsers(new ArrayList<>());

User user1 = new User();
user1.setId("user1");
user1.setOrganisations(new ArrayList<>());

User user2 = new User();
user2.setId("user2");
user2.setOrganisations(new ArrayList<>());

when(organisationRepository.findById(organisationId)).thenReturn(Optional.of(organisation));
when(authenticatedUser.getPrincipal()).thenReturn(activeUser);
when(userRepository.findById("user1")).thenReturn(Optional.of(user1));
when(userRepository.findById("user2")).thenReturn(Optional.of(user2));

var response = (AddUserResponseDTO) addUsersToOrganisationService.addUserToOrganisation(organisationId,
orgRequest, authenticatedUser);

assertEquals("success", response.status());
assertEquals("Users added to organisation", response.message());
assertEquals(organisationId, response.organization_id());
assertEquals(List.of("user1", "user2"), response.users_added_to_organisation());
assertEquals(200, response.status_code());

verify(organisationRepository).findById(organisationId);
verify(authenticatedUser).getPrincipal();
verify(userRepository).findById("user1");
verify(userRepository).findById("user2");
verify(organisationRepository).save(organisation);
verifyNoMoreInteractions(organisationRepository);
verifyNoMoreInteractions(authenticatedUser);
verifyNoMoreInteractions(userRepository);
}
}
Loading