Skip to content

Commit

Permalink
Merge pull request #156 from JNU-econovation/feat/147
Browse files Browse the repository at this point in the history
[FEAT] #147 #151
  • Loading branch information
inferior3x authored Jan 15, 2025
2 parents 6f4437c + c1c35d0 commit d1cd713
Show file tree
Hide file tree
Showing 41 changed files with 701 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.whoz_in.api_query_jpa.device;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import java.util.List;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Subselect;

@Entity
@Getter
@Subselect("SELECT d.id , d.member_id "
+ "FROM device_entity d")
@Immutable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Device {

@Id
@Column(name = "id", nullable = false)
private UUID id;

@Column(name ="member_id", nullable = false)
private UUID memberId;

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "device_id", referencedColumnName = "id")
private List<DeviceInfo> deviceInfos;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.whoz_in.api_query_jpa.device;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Subselect;

@Entity
@Getter
@Subselect("SELECT di.id, di.device_id, di.mac, di.ssid "
+ "FROM device_info_entity di")
@Immutable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class DeviceInfo {

@Id
private Long id;

private UUID deviceId;

private String mac;

private String ssid;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.whoz_in.api_query_jpa.device;

import com.whoz_in.main_api.query.device.view.DeviceInfoViewer;
import com.whoz_in.main_api.query.device.view.RegisteredSsids;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;


@Component
@RequiredArgsConstructor
public class DeviceInfoJpaViewer implements DeviceInfoViewer {
private final DeviceInfoRepository deviceInfoRepository;
@Override
public RegisteredSsids findRegisteredSsids(UUID ownerId, String room, String mac) {
return new RegisteredSsids(
deviceInfoRepository.findAllByMac(ownerId, room, mac).stream()
.map(DeviceInfo::getSsid)
.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.whoz_in.api_query_jpa.device;

import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface DeviceInfoRepository extends JpaRepository<DeviceInfo, Long> {
@Query(value = "SELECT di.id, di.device_id AS deviceId, di.mac, di.ssid " +
"FROM device_entity d " +
"JOIN device_info_entity di ON d.id = di.device_id " +
"WHERE d.member_id = :ownerId " +
"AND di.room = :room " +
"AND di.mac = :mac",
nativeQuery = true)
List<DeviceInfo> findAllByMac(@Param("ownerId") UUID ownerId, @Param("room") String room, @Param("mac") String mac);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.whoz_in.main_api.command.device.application;

import com.whoz_in.domain.device.DeviceRepository;
import com.whoz_in.domain.device.model.DeviceInfo;
import com.whoz_in.domain.device.model.MacAddress;
import com.whoz_in.domain.device.service.DeviceOwnershipService;
import com.whoz_in.domain.member.model.MemberId;
import com.whoz_in.domain.member.service.MemberFinderService;
Expand All @@ -11,6 +9,8 @@
import com.whoz_in.domain.network_log.MonitorLogRepository;
import com.whoz_in.main_api.command.shared.application.CommandHandler;
import com.whoz_in.main_api.shared.application.Handler;
import com.whoz_in.main_api.shared.caching.device.TempDeviceInfo;
import com.whoz_in.main_api.shared.caching.device.TempDeviceInfoStore;
import com.whoz_in.main_api.shared.utils.RequesterInfo;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
Expand All @@ -20,7 +20,7 @@
@RequiredArgsConstructor
public class DeviceInfoAddHandler implements CommandHandler<DeviceInfoAdd, Void> {
private final RequesterInfo requesterInfo;
private final DeviceInfoStore deviceInfoStore;
private final TempDeviceInfoStore tempDeviceInfoStore;
private final MemberFinderService memberFinderService;
private final DeviceOwnershipService deviceOwnershipService;
private final DeviceRepository deviceRepository;
Expand All @@ -41,9 +41,9 @@ public Void handle(DeviceInfoAdd req) {
String mac = managedLog.getMac();

//등록할 DeviceInfo 생성
DeviceInfo deviceInfo = DeviceInfo.create(req.room(), managedLog.getSsid(), MacAddress.create(mac));
TempDeviceInfo deviceInfo = new TempDeviceInfo(req.room(), managedLog.getSsid(), mac);
//이미 등록된 DeviceInfo가 아닌지 미리 확인
deviceInfoStore.mustNotExist(requesterId, deviceInfo);
tempDeviceInfoStore.mustNotExist(requesterId.id(), deviceInfo);

//모니터 로그에서 현재 접속 중인 맥이 있는지 확인 (넉넉하게 15분)
monitorLogRepository.mustExistAfter(mac, LocalDateTime.now().minusMinutes(15));
Expand All @@ -56,7 +56,7 @@ public Void handle(DeviceInfoAdd req) {
});

//마침내! DeviceInfo를 추가한다.
deviceInfoStore.add(requesterId, deviceInfo);
tempDeviceInfoStore.add(requesterId.id(), deviceInfo);

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import com.whoz_in.domain.device.DeviceRepository;
import com.whoz_in.domain.device.model.Device;
import com.whoz_in.domain.device.model.DeviceInfo;
import com.whoz_in.domain.device.model.MacAddress;
import com.whoz_in.domain.member.model.MemberId;
import com.whoz_in.domain.member.service.MemberFinderService;
import com.whoz_in.domain.shared.event.EventBus;
import com.whoz_in.main_api.command.shared.application.CommandHandler;
import com.whoz_in.main_api.shared.application.Handler;
import com.whoz_in.main_api.shared.caching.device.TempDeviceInfoStore;
import com.whoz_in.main_api.shared.utils.RequesterInfo;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -17,7 +19,7 @@
@RequiredArgsConstructor
public class DeviceRegisterHandler implements CommandHandler<DeviceRegister, Void> {
private final RequesterInfo requesterInfo;
private final DeviceInfoStore deviceInfoStore;
private final TempDeviceInfoStore tempDeviceInfoStore;
private final MemberFinderService memberFinderService;
private final DeviceRepository deviceRepository;
private final EventBus eventBus;
Expand All @@ -28,9 +30,12 @@ public Void handle(DeviceRegister cmd) {
MemberId requesterId = requesterInfo.getMemberId();
memberFinderService.mustExist(requesterId);

deviceInfoStore.verifyAllAdded(requesterId, cmd.room());
tempDeviceInfoStore.verifyAllAdded(requesterId.id(), cmd.room());

List<DeviceInfo> deviceInfos = deviceInfoStore.takeout(requesterId);
List<DeviceInfo> deviceInfos = tempDeviceInfoStore.takeout(requesterId.id())
.stream()
.map(cdi-> DeviceInfo.create(cdi.getRoom(), cdi.getSsid(), MacAddress.create(cdi.getMac())))
.toList();

Device device = Device.create(requesterId, deviceInfos, cmd.deviceName());
deviceRepository.save(device);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import com.whoz_in.main_api.command.device.application.DeviceRegister;
import com.whoz_in.main_api.command.shared.application.CommandBus;
import com.whoz_in.main_api.command.shared.presentation.CommandController;
import com.whoz_in.main_api.shared.presentation.ResponseEntityGenerator;
import com.whoz_in.main_api.shared.presentation.SuccessBody;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -22,12 +24,12 @@ public DeviceController(CommandBus commandBus) {
@PostMapping("/device/info")
public ResponseEntity<SuccessBody<Void>> addDeviceInfo(@RequestBody DeviceInfoAdd request) {
dispatch(request);
return null;
return ResponseEntityGenerator.success("기기 정보 등록 완료", HttpStatus.CREATED);
}

@PostMapping("/device")
public ResponseEntity<SuccessBody<Void>> registerDevice(@RequestBody DeviceRegister request) {
dispatch(request);
return null;
return ResponseEntityGenerator.success("기기 등록 완료", HttpStatus.CREATED);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.whoz_in.main_api.command.private_ip;

import com.whoz_in.main_api.command.shared.application.CommandBus;
import com.whoz_in.main_api.command.shared.presentation.CommandController;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1")
public class PrivateIpController extends CommandController {

public PrivateIpController(CommandBus commandBus) {
super(commandBus);
}

@PutMapping("/private-ip")
public void updatePrivateIp(@RequestBody PrivateIpUpdate req){
dispatch(req);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.whoz_in.main_api.command.private_ip;

import com.whoz_in.domain.device.model.IpAddress;
import com.whoz_in.main_api.command.shared.application.Command;
import java.util.Map;

public record PrivateIpUpdate(
String room,
Map<String, String> privateIpList //Map<와이파이이름, 아이피>
) implements Command {

public PrivateIpUpdate {
privateIpList.values().forEach(IpAddress::create); //아이피 형식 검증
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.whoz_in.main_api.command.private_ip;

import com.whoz_in.main_api.command.shared.application.CommandHandler;
import com.whoz_in.main_api.shared.application.Handler;
import com.whoz_in.main_api.shared.caching.private_ip.PrivateIpStore;
import lombok.RequiredArgsConstructor;

@Handler
@RequiredArgsConstructor
public class PrivateIpUpdateHandler implements CommandHandler<PrivateIpUpdate, Void> {
private final PrivateIpStore privateIpStore;

@Override
public Void handle(PrivateIpUpdate command) {
privateIpStore.put(command.room(), command.privateIpList());
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ public FilterRegistrationBean<JwtAuthenticationFilter> jwtAuthenticationFilterRe
return registrationBean;
}

//위와 동일한 이유로 추가
@Bean
public FilterRegistrationBean<ServerAuthenticationFilter> serverAuthenticationFilterRegistration(
ServerAuthenticationFilter serverAuthenticationFilter) {
FilterRegistrationBean<ServerAuthenticationFilter> registrationBean = new FilterRegistrationBean<>(serverAuthenticationFilter);
registrationBean.setEnabled(false);
return registrationBean;
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,25 @@ public class SecurityFilterChainConfig {
private final ClientRegistrationRepository clientRegistrationRepository;
private final LoginSuccessHandler loginSuccessHandler;
private final LoginFailureHandler loginFailureHandler;
private final ServerAuthenticationFilter serverAuthenticationFilter;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final CorsConfigurationSource corsConfigurationSource;

@Bean
@Order(0)
public SecurityFilterChain serverToServerFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.securityMatcher(
"/api/v1/private-ip"
);

commonConfigurations(httpSecurity);
httpSecurity.logout(AbstractHttpConfigurer::disable);
//TODO: ip 화이트 리스트
httpSecurity.addFilterAt(serverAuthenticationFilter, LogoutFilter.class);

return httpSecurity.build();
}

@Bean
@Order(1)
public SecurityFilterChain oauth2FilterChain(HttpSecurity httpSecurity) throws Exception {
Expand All @@ -50,7 +66,7 @@ public SecurityFilterChain oauth2FilterChain(HttpSecurity httpSecurity) throws E
return httpSecurity.build();
}

//POST, PUT, PATCH, DELETE 중 인증인가 필요 없는 엔드포인트
//인증인가 필요 없는 엔드포인트
@Bean
@Order(2)
public SecurityFilterChain noAuthenticationFilterChain(HttpSecurity httpSecurity) throws Exception {
Expand All @@ -77,6 +93,10 @@ public SecurityFilterChain authenticationFilterChain(HttpSecurity httpSecurity)
);
httpSecurity.authorizeHttpRequests(auth-> {
//인증 필요
auth.requestMatchers(HttpMethod.GET,
"/api/v1/device/info-status",
"/api/v1/private-ip/*"
).authenticated();
auth.requestMatchers(HttpMethod.POST,
"/api/v1/device",
"/api/v1/device/info"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.whoz_in.main_api.config.security;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class ServerAuthenticationFilter extends OncePerRequestFilter {
private final String apiKey;

public ServerAuthenticationFilter(@Value("${api-key}") String apiKey) {
this.apiKey = apiKey;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
Optional<String> extractedKey = extractApiKey(request);

if (extractedKey.filter(apiKey::equals).isEmpty()) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid API Key");
return;
}

filterChain.doFilter(request, response);
}

private Optional<String> extractApiKey(HttpServletRequest request){
return Optional.ofNullable(request.getHeader("Authorization"));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.whoz_in.main_api.shared.utils;
package com.whoz_in.main_api.config.security;

import com.whoz_in.domain.member.model.MemberId;
import com.whoz_in.main_api.config.security.JwtAuthentication;
import com.whoz_in.main_api.shared.utils.RequesterInfo;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
Expand Down
Loading

0 comments on commit d1cd713

Please sign in to comment.