Skip to content

Commit

Permalink
Merge pull request #689 from HNG-12/teibeina-add-members-to-org
Browse files Browse the repository at this point in the history
feat: implement add users to an organisation.
  • Loading branch information
Am0du authored Mar 2, 2025
2 parents 235e2f2 + 9ba51a1 commit e7df036
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 2 deletions.
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);
}
}

0 comments on commit e7df036

Please sign in to comment.