Skip to content

Commit

Permalink
fix: 머지 충돌 해결 (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
seok019283501 committed Nov 22, 2024
2 parents 1663aa6 + b3453ac commit a604bae
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 13 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ dependencies {
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.777'

// IOT
implementation 'software.amazon.awssdk:iot:2.29.17'
implementation 'com.amazonaws:aws-java-sdk-iot:1.12.778'
implementation 'software.amazon.awssdk.iotdevicesdk:aws-iot-device-sdk:1.21.0'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.ioteatime.meonghanyangserver.cctv.dto.response.CctvInfoListResponse;
import org.ioteatime.meonghanyangserver.common.api.Api;
import org.ioteatime.meonghanyangserver.common.utils.LoginMember;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -12,5 +13,5 @@ public interface CctvApi {
Api<?> out(@LoginMember Long userId, @PathVariable Long cctvId);

@Operation(summary = "CCTV 정보 목록 조회", description = "담당자: 최민석")
Api<?> cctvInfoList(@LoginMember Long memberId, @PathVariable Long groupId);
Api<CctvInfoListResponse> cctvInfoList(@LoginMember Long memberId, @PathVariable Long groupId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public interface CctvRepository {

Optional<CctvEntity> findById(Long cctvId);

void deleteByCctvId(Long groupId);
void deleteByGroupId(Long groupId);

Optional<CctvEntity> findByCctvId(Long thingId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public Optional<CctvEntity> findById(Long cctvId) {
}

@Override
public void deleteByCctvId(Long groupId) {
public void deleteByGroupId(Long groupId) {
jpaCctvRepository.deleteByGroupId(groupId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.ioteatime.meonghanyangserver.cctv.dto.response.CctvInfoResponse;
import org.ioteatime.meonghanyangserver.cctv.mapper.CctvResponseMapper;
import org.ioteatime.meonghanyangserver.cctv.repository.CctvRepository;
import org.ioteatime.meonghanyangserver.clients.iot.IotShadowMqttClient;
import org.ioteatime.meonghanyangserver.clients.kvs.KvsClient;
import org.ioteatime.meonghanyangserver.common.exception.BadRequestException;
import org.ioteatime.meonghanyangserver.common.exception.NotFoundException;
Expand All @@ -24,8 +25,9 @@
public class CctvService {
private final KvsClient kvsClient;
private final CctvRepository cctvRepository;
private final GroupMemberRepository groupMemberRepository;
private final GroupRepository groupRepository;
private final IotShadowMqttClient iotShadowMqttClient;
private final GroupMemberRepository groupMemberRepository;

public void createCctv(CreateCctvRequest createCctvRequest) {

Expand Down Expand Up @@ -64,7 +66,9 @@ public void outById(Long memberId, Long cctvId) {
.orElseThrow(() -> new NotFoundException(CctvErrorType.NOT_FOUND));
// 1. KVS 시그널링 채널 삭제
kvsClient.deleteSignalingChannel(cctv.getKvsChannelName());
// 2. CCTV 테이블에서 삭제
// 2. IoT desired -> 삭제되었음을 알림
iotShadowMqttClient.updateShadow(cctv.getThingId(), "kvsChannelDeleteRequested", true);
// 3. CCTV 테이블에서 삭제
cctvRepository.deleteById(cctvId);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.ioteatime.meonghanyangserver.clients.iot;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.crt.mqtt.QualityOfService;
import software.amazon.awssdk.iot.iotshadow.IotShadowClient;
import software.amazon.awssdk.iot.iotshadow.model.ShadowState;
import software.amazon.awssdk.iot.iotshadow.model.UpdateShadowRequest;

@Service
@RequiredArgsConstructor
public class IotShadowMqttClient {
private final IotShadowClient iotShadowClient;

public void updateShadow(String thingName, String key, boolean value) {
ShadowState shadowState = new ShadowState();
shadowState.desired.put(key, value);
shadowState.reportedIsNullable = true;

UpdateShadowRequest updateShadowRequest = new UpdateShadowRequest();
updateShadowRequest.state = shadowState;

updateShadowRequest.thingName = thingName;

iotShadowClient.PublishUpdateShadow(updateShadowRequest, QualityOfService.AT_LEAST_ONCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
import lombok.extern.slf4j.Slf4j;
import org.ioteatime.meonghanyangserver.common.exception.InternalServerException;
import org.ioteatime.meonghanyangserver.common.type.AwsErrorType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.crt.CRT;
import software.amazon.awssdk.crt.mqtt.MqttClientConnection;
import software.amazon.awssdk.crt.mqtt.MqttClientConnectionEvents;
import software.amazon.awssdk.iot.AwsIotMqttConnectionBuilder;
import software.amazon.awssdk.iot.iotshadow.IotShadowClient;

@Slf4j
@Configuration
Expand Down Expand Up @@ -92,7 +94,7 @@ public String getAWSSecretKey() {
}

@Bean
public MqttClientConnection awsIotMqttClient() {
public AWSIot awsIot() {
AWSCredentials awsCredentials =
new AWSCredentials() {
@Override
Expand All @@ -106,12 +108,14 @@ public String getAWSSecretKey() {
}
};

AWSIot awsIot =
AWSIotClient.builder()
.withRegion(Regions.AP_NORTHEAST_2)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
return AWSIotClient.builder()
.withRegion(Regions.AP_NORTHEAST_2)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}

@Bean
public MqttClientConnection awsIotMqttClient(@Autowired AWSIot awsIot) {
// 키 생성 및 정책 추가
CreateKeysAndCertificateResult keysAndCertificate =
getCreateKeysAndCertificateResult(awsIot);
Expand All @@ -123,6 +127,11 @@ public String getAWSSecretKey() {
return connection;
}

@Bean
public IotShadowClient iotShadowClient(@Autowired MqttClientConnection awsIotMqttClient) {
return new IotShadowClient(awsIotMqttClient);
}

private CreateKeysAndCertificateResult getCreateKeysAndCertificateResult(AWSIot awsIot) {
// 키 생성
CreateKeysAndCertificateResult keysAndCertificate =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public void deleteGroupMember(Long memberId, Long groupId) {
if (groupMember.getRole().equals(GroupMemberRole.ROLE_MASTER)) {
// 방장 퇴장
groupMemberRepository.deleteByGroupId(groupId);
cctvRepository.deleteByCctvId(groupId);
cctvRepository.deleteByGroupId(groupId);
groupRepository.deleteById(groupId);
} else {
// 참여자 퇴장
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package org.ioteatime.meonghanyangserver.member.service;

import java.util.Date;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.RefreshResponse;
import org.ioteatime.meonghanyangserver.auth.mapper.AuthResponseMapper;
import org.ioteatime.meonghanyangserver.cctv.domain.CctvEntity;
import org.ioteatime.meonghanyangserver.cctv.repository.CctvRepository;
import org.ioteatime.meonghanyangserver.clients.iot.IotShadowMqttClient;
import org.ioteatime.meonghanyangserver.clients.kvs.KvsClient;
import org.ioteatime.meonghanyangserver.common.exception.BadRequestException;
import org.ioteatime.meonghanyangserver.common.exception.NotFoundException;
import org.ioteatime.meonghanyangserver.common.type.AuthErrorType;
import org.ioteatime.meonghanyangserver.common.type.GroupErrorType;
import org.ioteatime.meonghanyangserver.common.utils.JwtUtils;
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.GroupMemberRepository;
import org.ioteatime.meonghanyangserver.member.domain.MemberEntity;
import org.ioteatime.meonghanyangserver.member.dto.request.ChangePasswordRequest;
import org.ioteatime.meonghanyangserver.member.dto.response.MemberDetailResponse;
Expand All @@ -17,16 +27,25 @@
import org.ioteatime.meonghanyangserver.redis.AccessTokenRepository;
import org.ioteatime.meonghanyangserver.redis.RefreshToken;
import org.ioteatime.meonghanyangserver.redis.RefreshTokenRepository;
import org.ioteatime.meonghanyangserver.video.repository.VideoRepository;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import software.amazon.awssdk.iot.iotshadow.IotShadowClient;

@Service
@RequiredArgsConstructor
public class MemberService {
private final JwtUtils jwtUtils;
private final KvsClient kvsClient;
private final CctvRepository cctvRepository;
private final GroupRepository groupRepository;
private final IotShadowClient iotShadowClient;
private final VideoRepository videoRepository;
private final MemberRepository memberRepository;
private final IotShadowMqttClient iotShadowMqttClient;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final GroupMemberRepository groupMemberRepository;
private final RefreshTokenRepository refreshTokenRepository;
private final AccessTokenRepository accessTokenRepository;

Expand All @@ -39,7 +58,50 @@ public MemberDetailResponse getMemberDetail(Long memberId) {
return MemberResponseMapper.from(memberEntity);
}

// NOTE.
// 1. Master는 권한을 위임하지 않는다. -> Master가 탈퇴하면 그룹이 삭제된다.
// 2. 회원은 하나의 그룹에만 소속된다.
@Transactional
public void deleteMember(Long memberId) {
// MemberId 기준으로 GroupMember 조회
GroupMemberEntity groupMemberEntity =
groupMemberRepository
.findByMemberId(memberId)
.orElseThrow(
() -> new NotFoundException(GroupErrorType.GROUP_MEMBER_NOT_FOUND));
// 탈퇴하는 사람이 MASTER이면 Group을 삭제
if (groupMemberEntity.getRole() == GroupMemberRole.ROLE_MASTER) {
// MemberId 기준으로 GroupMember 통해 GroupId 조회
Long groupId = groupMemberEntity.getGroup().getId();
// GroupId 기준으로 video 조회하여 삭제 (S3 배치 작업 추가 필요)
videoRepository.deleteAllByGroupId(groupId);

// KVS 채널 삭제는 rollback이 어려우므로 최대한 마지막에 처리
// GroupId 기준으로 cctv 조회하여 정보 목록 확인
List<CctvEntity> cctvEntities = cctvRepository.findByGroupId(groupId);
// CCTV 목록을 순회하여 KVS 채널 삭제
cctvEntities.forEach(
cctv -> {
kvsClient.deleteSignalingChannel(cctv.getKvsChannelName());

// CCTV 상태 shadow에서 kvsChannelDeleteRequested 필드 true로 pub -> (iot 기기 삭제는
// 모바일에서)
iotShadowMqttClient.updateShadow(
cctv.getThingId(), "kvsChannelDeleteRequested", true);
});
// CCTV 목록 삭제
cctvRepository.deleteByGroupId(groupId);

// GroupMember 삭제
groupMemberRepository.deleteById(groupMemberEntity.getId());

// group 삭제
groupRepository.deleteById(groupId);
} else {
// GroupMember 삭제만 진행 (PARTICIPANT인 경우)
groupMemberRepository.deleteById(groupMemberEntity.getId());
}
// member 삭제 (PARTICIPANT도 해당)
memberRepository.deleteById(memberId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
import org.ioteatime.meonghanyangserver.video.domain.VideoEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface JpaVideoRepository extends JpaRepository<VideoEntity, Long> {}
public interface JpaVideoRepository extends JpaRepository<VideoEntity, Long> {
void deleteAllByGroupId(Long groupId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@

public interface VideoRepository {
Optional<VideoEntity> findById(Long videoId);

void deleteAllByGroupId(Long groupId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ public class VideoRepositoryImpl implements VideoRepository {
public Optional<VideoEntity> findById(Long videoId) {
return jpaVideoRepository.findById(videoId);
}

@Override
public void deleteAllByGroupId(Long groupId) {
jpaVideoRepository.deleteAllByGroupId(groupId);
}
}

0 comments on commit a604bae

Please sign in to comment.