Skip to content
Closed
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
6 changes: 3 additions & 3 deletions src/main/java/com/acc/local/controller/docs/ProjectDocs.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public interface ProjectDocs {
{
"userId": "de15e36af072460da2e39a74be3595b6",
"userName": "Acc_test_Admin1",
"userEmail": null,
"userEmail": "admin@ajou.ac.kr",
"userPhoneNumber": null,
"role": "PROJECT_ADMIN"
}
Expand Down Expand Up @@ -151,7 +151,7 @@ ResponseEntity<List<ProjectResponse>> getProjects(
+ " {\n"
+ " \"userId\": \"de15e36af072460da2e39a74be3595b6\",\n"
+ " \"userName\": \"${SUPER_ADMIN_USER_NAME}\",\n"
+ " \"userEmail\": null,\n"
+ " \"userEmail\": \"admin@ajou.ac.kr\",\n"
+ " \"userPhoneNumber\": \"010-0000-0000\",\n"
+ " \"role\": \"PROJECT_ADMIN\"\n"
+ " }\n"
Expand Down Expand Up @@ -204,7 +204,7 @@ ResponseEntity<List<ProjectResponse>> getProjects(
{
"userId": "de15e36af072460da2e39a74be3595b6",
"userName": "Acc_test_Admin1",
"userEmail": null,
"userEmail": "admin@ajou.ac.kr",
"userPhoneNumber": null,
"role": "PROJECT_ADMIN"
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/acc/local/dto/project/ProjectOwnerDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
@Builder
public record ProjectOwnerDto(
String userId,
String userName
String userName,
String userEmail
) {
public static ProjectOwnerDto from(UserKeystoneDto createdBy) {
return ProjectOwnerDto.builder()
.userId(createdBy.id())
.userName(createdBy.name())
.userEmail(createdBy.email())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ public record ProjectParticipantDto(
ProjectRole role
) {
public static ProjectParticipantDto from(ProjectParticipantEntity dbProjectParticipant) {
return from(dbProjectParticipant, null);
}

public static ProjectParticipantDto from(ProjectParticipantEntity dbProjectParticipant, String userEmail) {
return ProjectParticipantDto.builder()
.userId(dbProjectParticipant.getUserDetail().getUserId())
.userName(dbProjectParticipant.getUserDetail().getUserName())
// .userEmail(dbProjectParticipant.getUserDetail().getUserEmail()) // TODO: User 도메인과 협의필요
.userEmail(userEmail)
.userPhoneNumber(dbProjectParticipant.getUserDetail().getUserPhoneNumber())
.role(dbProjectParticipant.getRole())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public static ProjectResponse from(ProjectRequestDto projectRequestDto, UserKeys
ProjectParticipantDto.builder()
.userId(projectRequestUser.id())
.userName(projectRequestUser.name())
.userEmail(projectRequestUser.email())
.role(ProjectRole.PROJECT_ADMIN)
.build()
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import lombok.Builder;

@Builder
@Builder(toBuilder = true)
public record ProjectServiceDto(
String projectId,
String projectName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

import com.acc.local.dto.project.*;
import com.acc.local.entity.UserDbExtraEntity;
import com.acc.local.repository.dto.UserDBDto;
import com.acc.local.external.dto.keystone.UpdateKeystoneProjectRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -306,10 +308,14 @@ public ProjectServiceDto getProjectDetail(String projectId, String scopedToken)
ProjectComputeQuotaDto projectComputeQuotaDetail = getProjectComputeQuotaDetail(projectId, scopedToken);
ProjectStorageQuotaDto projectStorageQuotaDetail = getProjectStorageQuotaDetail(projectId, scopedToken);

return ProjectServiceDto.from(
ProjectServiceDto projectServiceDto = ProjectServiceDto.from(
databaseProject, openstackProject,
projectComputeQuotaDetail, projectStorageQuotaDetail
);

return projectServiceDto.toBuilder()
.participants(getProjectParticipantList(projectId))
.build();
}

@Transactional
Expand Down Expand Up @@ -417,8 +423,25 @@ public void updateProjectStorageQuota(String adminToken, String projectId, int s
// ============ Participant ============
public List<ProjectParticipantDto> getProjectParticipantList(String projectId) {
List<ProjectParticipantEntity> projectParticipants = projectParticipantRepositoryPort.findByProjectId(projectId);
if (projectParticipants.isEmpty()) {
return new ArrayList<>();
}

List<String> participantUserIds = projectParticipants.stream()
.map(participant -> participant.getUserDetail().getUserId())
.toList();
Map<String, String> emailByUserId = userRepositoryPort.findUserDBsByUserIds(participantUserIds).stream()
.collect(Collectors.toMap(
UserDBDto::getUserId,
user -> user.userIdentity().getUserEmail(),
(existing, ignored) -> existing
));

return projectParticipants.stream()
.map(ProjectParticipantDto::from)
.map(participant -> ProjectParticipantDto.from(
participant,
emailByUserId.get(participant.getUserDetail().getUserId())
))
.collect(Collectors.toCollection(ArrayList::new));
}

Expand Down
23 changes: 23 additions & 0 deletions src/test/java/com/acc/local/dto/project/ProjectResponseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.acc.local.domain.enums.project.ProjectRequestStatus;
import com.acc.local.domain.enums.project.ProjectRequestType;
import com.acc.local.domain.enums.project.ProjectRole;
import com.acc.local.dto.auth.UserKeystoneDto;
import com.acc.local.dto.project.quota.ProjectGlobalQuotaDto;
import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -58,4 +59,26 @@ void fromProjectRequestDtoSerializesQuotaWithoutDeprecatedProjectBrief() throws
assertThat(json.has("projectBrief")).isFalse();
assertThat(json.has("quota")).isTrue();
}

@Test
void fromProjectRequestIncludesRequesterEmailInOwnerAndParticipant() {
ProjectRequestDto request = ProjectRequestDto.builder()
.projectName("project-name")
.projectType(ProjectRequestType.ETC)
.status(ProjectRequestStatus.PENDING)
.createdAt(LocalDateTime.now())
.build();
UserKeystoneDto requester = UserKeystoneDto.builder()
.id("user-id")
.name("user-name")
.email("user@ajou.ac.kr")
.build();

ProjectResponse response = ProjectResponse.from(request, requester);

assertThat(response.createdBy().userEmail()).isEqualTo("user@ajou.ac.kr");
assertThat(response.participants()).hasSize(1);
assertThat(response.participants().get(0).userEmail()).isEqualTo("user@ajou.ac.kr");
assertThat(response.participants().get(0).role()).isEqualTo(ProjectRole.PROJECT_ADMIN);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,29 @@
import static org.mockito.Mockito.verify;

import com.acc.global.common.PageRequest;
import com.acc.local.domain.enums.auth.AuthType;
import com.acc.local.domain.enums.project.ProjectRequestStatus;
import com.acc.local.domain.enums.project.ProjectRequestType;
import com.acc.local.domain.enums.project.ProjectRole;
import com.acc.local.dto.project.ProjectParticipantDto;
import com.acc.local.dto.project.ProjectCreateDto;
import com.acc.local.dto.project.ProjectRequestDto;
import com.acc.local.dto.project.ProjectRequestListServiceDto;
import com.acc.local.dto.project.quota.ProjectQuotaRequest;
import com.acc.local.entity.ProjectEntity;
import com.acc.local.entity.ProjectParticipantEntity;
import com.acc.local.entity.ProjectRequestEntity;
import com.acc.local.entity.UserDbExtraEntity;
import com.acc.local.entity.UserIdentityEntity;
import com.acc.local.entity.id.ProjectParticipantId;
import com.acc.local.entity.id.UserIdentityId;
import com.acc.local.external.dto.keystone.CreateKeystoneProjectRequest;
import com.acc.local.external.dto.keystone.KeystoneProject;
import com.acc.local.external.modules.keystone.KeystoneUserAPIModule;
import com.acc.local.external.ports.KeystoneAPIExternalPort;
import com.acc.local.external.ports.VolumeQuotaExternalPort;
import com.acc.local.external.ports.compute.ComputeQuotaExternalPort;
import com.acc.local.repository.dto.UserDBDto;
import com.acc.local.repository.ports.ProjectParticipantRepositoryPort;
import com.acc.local.repository.ports.ProjectRepositoryPort;
import com.acc.local.repository.ports.ProjectRequestRepositoryPort;
Expand Down Expand Up @@ -188,6 +196,67 @@ void givenProjectCreateDtoWithProjectType_whenCreateProject_thenSaveProjectType(
assertThat(projectCaptor.getValue().getProjectType()).isEqualTo(ProjectRequestType.MAJOR_LECTURE);
}

@Test
@DisplayName("프로젝트 참여자 목록 조회 시 사용자 인증정보의 이메일을 응답에 포함한다.")
void givenParticipantIdentities_whenGetProjectParticipantList_thenReturnUserEmail() {
UserDbExtraEntity user = UserDbExtraEntity.builder()
.userId("user-id")
.userName("user-name")
.userPhoneNumber("010-0000-0000")
.isAdmin(false)
.build();
UserIdentityEntity identity = UserIdentityEntity.builder()
.id(new UserIdentityId("user-id", AuthType.GOOGLE.getCode()))
.userEmail("user@ajou.ac.kr")
.department("department")
.studentId("2026001")
.createdAt(LocalDateTime.now())
.build();
ProjectParticipantEntity participant = ProjectParticipantEntity.builder()
.projectParticipantId(new ProjectParticipantId("project-id", "user-id"))
.userDetail(user)
.role(ProjectRole.PROJECT_ADMIN)
.build();

given(projectParticipantRepositoryPort.findByProjectId("project-id"))
.willReturn(List.of(participant));
given(userRepositoryPort.findUserDBsByUserIds(List.of("user-id")))
.willReturn(List.of(new UserDBDto(identity, user)));

List<ProjectParticipantDto> result = projectModule.getProjectParticipantList("project-id");

assertThat(result).hasSize(1);
assertThat(result.get(0).userId()).isEqualTo("user-id");
assertThat(result.get(0).userEmail()).isEqualTo("user@ajou.ac.kr");
assertThat(result.get(0).role()).isEqualTo(ProjectRole.PROJECT_ADMIN);
}

@Test
@DisplayName("프로젝트 참여자 인증정보가 없으면 이메일은 null로 유지한다.")
void givenNoParticipantIdentity_whenGetProjectParticipantList_thenReturnNullEmail() {
UserDbExtraEntity user = UserDbExtraEntity.builder()
.userId("user-id")
.userName("user-name")
.userPhoneNumber("010-0000-0000")
.isAdmin(false)
.build();
ProjectParticipantEntity participant = ProjectParticipantEntity.builder()
.projectParticipantId(new ProjectParticipantId("project-id", "user-id"))
.userDetail(user)
.role(ProjectRole.PROJECT_ADMIN)
.build();

given(projectParticipantRepositoryPort.findByProjectId("project-id"))
.willReturn(List.of(participant));
given(userRepositoryPort.findUserDBsByUserIds(List.of("user-id")))
.willReturn(List.of());

List<ProjectParticipantDto> result = projectModule.getProjectParticipantList("project-id");

assertThat(result).hasSize(1);
assertThat(result.get(0).userEmail()).isNull();
}

private ProjectRequestEntity entity(String id) {
return ProjectRequestEntity.builder()
.projectRequestId(id)
Expand Down
Loading