Skip to content

Commit

Permalink
Merge pull request #210 from IoTeaTime/develop
Browse files Browse the repository at this point in the history
release: 서버 배포
  • Loading branch information
ywonchae1 authored Nov 29, 2024
2 parents 86d03ff + f5d0375 commit b13ef95
Show file tree
Hide file tree
Showing 15 changed files with 108 additions and 48 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,5 @@ jobs:
envs: IMAGE_FULL_URL, DOCKERHUB_IMAGE_NAME
script: |
echo "${{ secrets.DOCKERHUB_ACCESS_TOKEN }}" | docker login -u "${{ env.DOCKERHUB_USERNAME }}" --password-stdin
docker compose down --remove-orphans
docker compose up --build -d
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import jakarta.validation.Valid;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.LoginResponse;
import org.ioteatime.meonghanyangserver.auth.dto.request.EmailRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.IssuePasswordRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.LoginRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.VerifyEmailRequest;
import org.ioteatime.meonghanyangserver.common.api.Api;
Expand All @@ -27,4 +28,7 @@ public interface AuthApi {

@Operation(summary = "이메일 중복을 확인 합니다.", description = "담당자: 조경재")
Api<?> duplicateEmail(@Valid @RequestBody EmailRequest email);

@Operation(summary = "임시 비밀번호를 발급해줍니다.", description = "담당자: 최민석")
Api<?> issuePassword(@Valid @RequestBody IssuePasswordRequest issuePasswordRequest);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.ioteatime.meonghanyangserver.auth.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.LoginResponse;
import org.ioteatime.meonghanyangserver.auth.dto.request.EmailRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.IssuePasswordRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.LoginRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.VerifyEmailRequest;
import org.ioteatime.meonghanyangserver.auth.service.AuthService;
Expand Down Expand Up @@ -42,6 +44,12 @@ public Api<?> duplicateEmail(@RequestBody EmailRequest emailReq) {
return Api.success(AuthSuccessType.EMAIL_VERIFIED);
}

@PatchMapping("/change-password")
public Api<?> issuePassword(@Valid @RequestBody IssuePasswordRequest issuePasswordRequest) {
authService.issuePassword(issuePasswordRequest);
return Api.success(AuthSuccessType.ISSUE_PASSWORD);
}

@PostMapping("/sign-in")
public Api<LoginResponse> login(LoginRequest loginRequest) {
LoginResponse loginResponse = authService.login(loginRequest);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.ioteatime.meonghanyangserver.auth.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;

@Schema(description = "임시 비밀번호 발급을 위한 요청")
public record IssuePasswordRequest(
@Email @NotNull @Schema(description = "이메일", example = "[email protected]") String email) {}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.ioteatime.meonghanyangserver.auth.service;

import jakarta.transaction.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;
import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.auth.dto.db.LoginWithMemberInfo;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.LoginResponse;
import org.ioteatime.meonghanyangserver.auth.dto.request.IssuePasswordRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.LoginRequest;
import org.ioteatime.meonghanyangserver.auth.mapper.AuthEntityMapper;
import org.ioteatime.meonghanyangserver.auth.mapper.AuthResponseMapper;
Expand Down Expand Up @@ -124,4 +126,27 @@ public void verifyEmailCode(String email, String code) {
throw new UnauthorizedException(AuthErrorType.CODE_NOT_EQUALS);
}
}

@Transactional
public void issuePassword(IssuePasswordRequest issuePasswordRequest) {

MemberEntity memberEntity =
memberRepository
.findByEmail(issuePasswordRequest.email())
.orElseThrow(() -> new NotFoundException(AuthErrorType.NOT_FOUND));
// 임시비밀번호 발급
String password = getCode();

String encodedPassword = bCryptPasswordEncoder.encode(password);

memberEntity.updatePassword(encodedPassword);
String mailSubject = "[\uD83D\uDC36 멍하냥] 임시 비밀번호입니다.";
String mailContent =
"""
<b>임시 비밀번호를 발급받았습니다.</b>
<p>%s</p>
"""
.formatted(password);
sesClient.sendEmail(issuePasswordRequest.email(), mailSubject, mailContent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public enum AuthSuccessType implements SuccessTypeCode {
VERIFY_EMAIL_CODE(200, "OK", "이메일 인증 코드 검증에 성공하였습니다."),
UPDATE_NICKNAME(200, "OK", "닉네임 수정에 성공하였습니다."),
UPDATE_NICKNAME_AND_GROUP_NAME(200, "OK", "닉네임과 그룹 이름 변경에 성공하였습니다."),
SIGN_OUT(200, "OK", "로그아웃에 성공하였습니다.");
SIGN_OUT(200, "OK", "로그아웃에 성공하였습니다."),
ISSUE_PASSWORD(200, "OK", "임시 비밀번호 발급에 성공하였습니다.");

private final Integer code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.ioteatime.meonghanyangserver.group.service;

import jakarta.transaction.Transactional;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.clients.google.FcmClient;
import org.ioteatime.meonghanyangserver.common.exception.BadRequestException;
Expand All @@ -16,9 +15,9 @@
import org.ioteatime.meonghanyangserver.group.mapper.GroupEntityMapper;
import org.ioteatime.meonghanyangserver.group.mapper.GroupResponseMapper;
import org.ioteatime.meonghanyangserver.group.repository.GroupRepository;
import org.ioteatime.meonghanyangserver.groupmember.doamin.GroupMemberEntity;
import org.ioteatime.meonghanyangserver.groupmember.doamin.enums.GroupMemberRole;
import org.ioteatime.meonghanyangserver.groupmember.repository.JpaGroupMemberRepository;
import org.ioteatime.meonghanyangserver.groupmember.service.GroupMemberService;
import org.ioteatime.meonghanyangserver.groupmember.repository.GroupMemberRepository;
import org.ioteatime.meonghanyangserver.member.domain.MemberEntity;
import org.ioteatime.meonghanyangserver.member.repository.MemberRepository;
import org.springframework.stereotype.Service;
Expand All @@ -29,15 +28,14 @@ public class GroupService {
private final FcmClient fcmClient;
private final GroupRepository groupRepository;
private final MemberRepository memberRepository;
private final GroupMemberService groupMemberService;
private final GroupMemberRepository groupMemberRepository;
private final RandomStringGenerator randomStringGenerator;
private final JpaGroupMemberRepository groupUserRepository;

// create group
@Transactional
public CreateGroupResponse createGroup(Long memberId, CreateGroupRequest createGroupRequest) {

boolean groupUserEntity = groupMemberService.existsGroupMember(memberId);
boolean groupUserEntity = groupMemberRepository.existsGroupMember(memberId);
String thingId = createGroupRequest.thingId();
if (groupUserEntity) {
throw new BadRequestException(GroupErrorType.ALREADY_EXISTS);
Expand All @@ -55,8 +53,10 @@ public CreateGroupResponse createGroup(Long memberId, CreateGroupRequest createG
GroupEntity groupEntity = GroupEntityMapper.toEntity(roomName, fcmTopic);

GroupEntity newGroupEntity = groupRepository.save(groupEntity);
groupMemberService.createGroupMember(
newGroupEntity, memberEntity, GroupMemberRole.ROLE_MASTER, thingId);
GroupMemberEntity groupMemberEntity =
GroupMemberEntity.from(
GroupMemberRole.ROLE_MASTER, thingId, newGroupEntity, memberEntity);
groupMemberRepository.save(groupMemberEntity);

// FCM 토픽 구독
fcmClient.subTopic(memberEntity.getFcmToken(), fcmTopic);
Expand All @@ -71,7 +71,8 @@ private String createFcmTopicName(Long memberId) {

public GroupTotalResponse getGroupTotalData(Long memberId) {
GroupEntity groupEntity =
Optional.ofNullable(groupMemberService.getGroup(memberId))
groupMemberRepository
.findGropFromGroupMember(memberId)
.orElseThrow(
() -> new NotFoundException(GroupErrorType.GROUP_MEMBER_NOT_FOUND));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,31 @@
import org.ioteatime.meonghanyangserver.common.api.Api;
import org.ioteatime.meonghanyangserver.common.utils.LoginMember;
import org.ioteatime.meonghanyangserver.groupmember.dto.request.JoinGroupMemberRequest;
import org.ioteatime.meonghanyangserver.groupmember.dto.response.GroupMemberInfoListResponse;
import org.ioteatime.meonghanyangserver.groupmember.dto.response.GroupMemberResponse;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

@Tag(name = "Group Member Api", description = "Group Member 관련 API 목록입니다.")
public interface GroupMemberApi {

@Operation(summary = "참여자가 그룹과 역할을 조회합니다.", description = "담당자: 임지인")
public Api<?> getGroupMemberInfo(@LoginMember Long memberId);
Api<GroupMemberResponse> getGroupMemberInfo(@LoginMember Long memberId);

@Operation(summary = "참여자가 그룹에 입장을 요청합니다.", description = "담당자: 임지인")
public Api<Void> joinGroupAsMember(
Api<?> joinGroupAsMember(
@LoginMember Long memberId, @RequestBody JoinGroupMemberRequest joinGroupMemberRequest);

@Operation(summary = "방장이 그룹에서 참여자를 제외합니다.", description = "담당자: 최민석")
public Api<?> deleteMasterGroupMember(
Api<?> deleteMasterGroupMember(
@LoginMember Long memberId,
@PathVariable Long groupId,
@PathVariable Long groupMemberId);

@Operation(summary = "그룹에서 참여자가 스스로 퇴장합니다.", description = "담당자: 최민석")
public Api<?> deleteGroupMember(@LoginMember Long memberId, @PathVariable Long groupId);
Api<?> deleteGroupMember(@LoginMember Long memberId, @PathVariable Long groupId);

@Operation(summary = "그룹 참여자들의 정보를 조회합니다.", description = "담당자: 최민석")
public Api<?> getGroupMemberInfoList(@LoginMember Long memberId, @PathVariable Long groupId);
Api<GroupMemberInfoListResponse> getGroupMemberInfoList(
@LoginMember Long memberId, @PathVariable Long groupId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ public class GroupMemberController implements GroupMemberApi {
private final GroupMemberService groupMemberService;

@GetMapping
public Api<?> getGroupMemberInfo(@LoginMember Long memberId) {
public Api<GroupMemberResponse> getGroupMemberInfo(@LoginMember Long memberId) {
GroupMemberResponse groupMemberResponse = groupMemberService.getGroupMemberInfo(memberId);
return Api.success(GroupSuccessType.GET_GROUP_MEMBER_INFO, groupMemberResponse);
}

@PostMapping("/viewer")
public Api<Void> joinGroupAsMember(
public Api<?> joinGroupAsMember(
@LoginMember Long memberId,
@RequestBody JoinGroupMemberRequest joinGroupMemberRequest) {
groupMemberService.joinGroupMember(memberId, joinGroupMemberRequest);
Expand All @@ -33,20 +33,22 @@ public Api<Void> joinGroupAsMember(
@DeleteMapping("/{groupId}/member/{groupMemberId}")
public Api<?> deleteMasterGroupMember(
@LoginMember Long memberId,
@PathVariable Long groupId,
@PathVariable Long groupMemberId) {
@PathVariable("groupId") Long groupId,
@PathVariable("groupMemberId") Long groupMemberId) {
groupMemberService.deleteMasterGroupMember(memberId, groupId, groupMemberId);
return Api.success(GroupSuccessType.DELETE_GROUP_MEMBER);
}

@DeleteMapping("/{groupId}/member")
public Api<?> deleteGroupMember(@LoginMember Long memberId, @PathVariable Long groupId) {
public Api<?> deleteGroupMember(
@LoginMember Long memberId, @PathVariable("groupId") Long groupId) {
groupMemberService.deleteGroupMember(memberId, groupId);
return Api.success(GroupSuccessType.DELETE_GROUP_MEMBER);
}

@GetMapping("/{groupId}/member")
public Api<?> getGroupMemberInfoList(@LoginMember Long memberId, @PathVariable Long groupId) {
public Api<GroupMemberInfoListResponse> getGroupMemberInfoList(
@LoginMember Long memberId, @PathVariable("groupId") Long groupId) {
GroupMemberInfoListResponse groupMemberInfoListResponse =
groupMemberService.getGroupMemberInfoList(memberId, groupId);
return Api.success(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,20 @@ public GroupMemberEntity(
this.group = group;
}

@Builder
public GroupMemberEntity(Long id, GroupMemberRole role, String thingId, MemberEntity member) {
this.id = id;
this.role = role;
this.member = member;
this.thingId = thingId;
}

public static GroupMemberEntity from(
GroupMemberRole role, String thingId, GroupEntity group, MemberEntity member) {
return GroupMemberEntity.builder()
.role(role)
.thingId(thingId)
.group(group)
.member(member)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface GroupMemberRepository {

Optional<GroupMemberEntity> findByMemberId(Long memberId);

GroupEntity findGroupMember(Long memberId);
Optional<GroupEntity> findGropFromGroupMember(Long memberId);

void deleteById(Long id);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ public Optional<GroupMemberEntity> findByMemberId(Long memberId) {
}

@Override
public GroupEntity findGroupMember(Long memberId) {
return jpaQueryFactory
.select(groupMemberEntity.group)
.from(groupMemberEntity)
.where(groupMemberEntity.member.id.eq(memberId))
.fetchOne();
public Optional<GroupEntity> findGropFromGroupMember(Long memberId) {
return Optional.ofNullable(
jpaQueryFactory
.select(groupMemberEntity.group)
.from(groupMemberEntity)
.where(groupMemberEntity.member.id.eq(memberId))
.fetchOne());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.ioteatime.meonghanyangserver.groupmember.service;

import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.cctv.dto.response.CctvInviteResponse;
import org.ioteatime.meonghanyangserver.cctv.repository.CctvRepository;
Expand All @@ -19,7 +18,6 @@
import org.ioteatime.meonghanyangserver.groupmember.dto.response.GroupMemberInfoListResponse;
import org.ioteatime.meonghanyangserver.groupmember.dto.response.GroupMemberInfoResponse;
import org.ioteatime.meonghanyangserver.groupmember.dto.response.GroupMemberResponse;
import org.ioteatime.meonghanyangserver.groupmember.mapper.GroupMemberEntityMapper;
import org.ioteatime.meonghanyangserver.groupmember.mapper.GroupMemberResponseMapper;
import org.ioteatime.meonghanyangserver.groupmember.repository.GroupMemberRepository;
import org.ioteatime.meonghanyangserver.member.domain.MemberEntity;
Expand All @@ -30,22 +28,11 @@
@Service
@RequiredArgsConstructor
public class GroupMemberService {
private final GroupMemberRepository groupMemberRepository;
private final MemberRepository memberRepository;
private final CctvRepository cctvRepository;
private final GroupRepository groupRepository;
private final MemberRepository memberRepository;
private final GroupMemberRepository groupMemberRepository;
private final KvsChannelNameGenerator kvsChannelNameGenerator;
private final CctvRepository cctvRepository;

// input user
public void createGroupMember(
GroupEntity groupEntity,
MemberEntity memberEntity,
GroupMemberRole groupMemberRole,
String thingId) {
GroupMemberEntity groupMember =
GroupMemberEntityMapper.from(groupEntity, memberEntity, groupMemberRole, thingId);
groupMemberRepository.save(groupMember);
}

@Transactional
public void joinGroupMember(Long memberId, JoinGroupMemberRequest joinGroupMemberRequest) {
Expand All @@ -64,7 +51,10 @@ public void joinGroupMember(Long memberId, JoinGroupMemberRequest joinGroupMembe
.findById(memberId)
.orElseThrow(() -> new BadRequestException(AuthErrorType.NOT_FOUND));

createGroupMember(groupEntity, memberEntity, GroupMemberRole.ROLE_PARTICIPANT, thingId);
GroupMemberEntity groupMemberEntity =
GroupMemberEntity.from(
GroupMemberRole.ROLE_PARTICIPANT, thingId, groupEntity, memberEntity);
groupMemberRepository.save(groupMemberEntity);
}

public boolean existsGroupMember(Long memberId) {
Expand Down Expand Up @@ -103,7 +93,8 @@ public CctvInviteResponse generateCctvInvite(Long memberId) {
}

public GroupEntity getGroup(Long memberId) {
return Optional.ofNullable(groupMemberRepository.findGroupMember(memberId))
return groupMemberRepository
.findGropFromGroupMember(memberId)
.orElseThrow(() -> new NotFoundException(GroupErrorType.GROUP_MEMBER_NOT_FOUND));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,9 @@ public MemberEntity updateNickname(String nickname) {
this.nickname = nickname;
return this;
}

public MemberEntity updatePassword(String encodedPassword) {
this.password = encodedPassword;
return this;
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ spring:
format_sql: true
default_batch_fetch_size: 100
hibernate:
ddl-auto: create
ddl-auto: update

0 comments on commit b13ef95

Please sign in to comment.