From 49572f46d7ea7d358615c7301d300f145558c764 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Tue, 26 Aug 2025 09:23:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8A=E4=BC=A0=E5=92=8C?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=AE=9A=E4=BD=8D=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../videotablet/config/SecurityConfig.java | 1 + .../controller/ContactController.java | 5 +- .../controller/DevicesController.java | 50 ++++++++++++++++++- .../controller/UserController.java | 47 ++++++++++++++++- .../videotablet/entity/Contact.java | 26 ++++++++++ .../videotablet/entity/DeviceLocation.java | 50 +++++++++++++++++++ .../repository/DeviceLocationRepository.java | 27 ++++++++++ .../service/DeviceLocationService.java | 29 +++++++++++ 8 files changed, 229 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/onekeycall/videotablet/entity/DeviceLocation.java create mode 100644 src/main/java/com/onekeycall/videotablet/repository/DeviceLocationRepository.java create mode 100644 src/main/java/com/onekeycall/videotablet/service/DeviceLocationService.java diff --git a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java index a3ee6eb..5964931 100644 --- a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java +++ b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java @@ -35,6 +35,7 @@ public class SecurityConfig { .requestMatchers("/admin/**").hasRole("ADMIN") // .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN") .requestMatchers("/user/**").permitAll() + .requestMatchers("/contact/**").permitAll() .anyRequest().authenticated() ); return http.build(); diff --git a/src/main/java/com/onekeycall/videotablet/controller/ContactController.java b/src/main/java/com/onekeycall/videotablet/controller/ContactController.java index 0f3d696..392da27 100644 --- a/src/main/java/com/onekeycall/videotablet/controller/ContactController.java +++ b/src/main/java/com/onekeycall/videotablet/controller/ContactController.java @@ -7,6 +7,7 @@ import com.onekeycall.videotablet.result.Result; import com.onekeycall.videotablet.service.DeviceSnService; import com.onekeycall.videotablet.service.UserService; import com.onekeycall.videotablet.utils.JwtUtil; +import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -31,8 +32,8 @@ public class ContactController { @PostMapping("/user_add_contact") public Result userAddContact( @RequestHeader("Authorization") String authHeader, @RequestHeader("Device-ID") String deviceId, - @RequestParam(value = "user_id") String userId, @RequestParam(value = "sn") String sn - , @RequestBody Contact contact) { + @RequestParam(value = "user_id") String userId, @RequestParam(value = "sn") String sn, + @Valid @RequestBody Contact contact) { if (!authHeader.startsWith("Bearer ")) { return Result.error().message("Invalid Authorization header"); diff --git a/src/main/java/com/onekeycall/videotablet/controller/DevicesController.java b/src/main/java/com/onekeycall/videotablet/controller/DevicesController.java index 726934b..12a81d1 100644 --- a/src/main/java/com/onekeycall/videotablet/controller/DevicesController.java +++ b/src/main/java/com/onekeycall/videotablet/controller/DevicesController.java @@ -1,14 +1,21 @@ package com.onekeycall.videotablet.controller; +import com.onekeycall.videotablet.entity.Contact; import com.onekeycall.videotablet.entity.DeviceInfo; +import com.onekeycall.videotablet.entity.DeviceLocation; import com.onekeycall.videotablet.result.Result; +import com.onekeycall.videotablet.service.DeviceLocationService; import com.onekeycall.videotablet.service.DeviceSnService; import com.onekeycall.videotablet.utils.JwtUtil; import com.onekeycall.videotablet.utils.TextUtils; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/sn") @@ -17,6 +24,8 @@ public class DevicesController { private JwtUtil jwtUtil; @Autowired private DeviceSnService deviceSnService; + @Autowired + private DeviceLocationService deviceLocationService; @GetMapping("/get_sn_list") public Result register(@RequestHeader("Authorization") String authHeader, @RequestHeader("Device-ID") String deviceId, @@ -39,17 +48,54 @@ public class DevicesController { } else { return Result.ok().data("deviceInfos", deviceInfos); } - }else { + } else { DeviceInfo deviceInfo = deviceSnService.findBySn(sn); if (deviceInfo == null) { return Result.notFound().message("sn not found"); } - if(!deviceInfo.getUserId().equals(userId)) { + if (!deviceInfo.getUserId().equals(userId)) { return Result.error().message("sn not belong to user"); } return Result.ok().data("deviceInfo", deviceInfo); } } + + @PostMapping("/update_location") + public Result getBindStatus( + @RequestHeader("Device-Token") String deviceToken, @RequestHeader("Device-ID") String deviceId, + @RequestHeader("Device-Sig") String deviceSig, + @Valid @RequestBody DeviceLocation deviceLocation + ) { + String sn = deviceLocation.getSn(); + + if (!jwtUtil.validateDeviceToken(deviceToken, deviceId, sn)) { + return Result.error().message("Invalid token"); + } + + DeviceInfo deviceInfo = deviceSnService.findBySn(sn); + if (deviceInfo == null) { + return Result.notFound().message("sn not found"); + } + + if (!deviceInfo.getBindSig().equals(deviceSig)) { + return Result.error().message("device sig not match"); + } + + if (TextUtils.isEmpty(deviceInfo.getBindPhone())) { + return Result.error().message("sn not bind"); + } + if (deviceLocationService.isExist(sn)) { + DeviceLocation deviceLocationDB=deviceLocationService.getDeviceLocation(sn); + deviceLocation.setId(deviceLocationDB.getId()); + deviceLocation.setUpdateTime(new Date(System.currentTimeMillis())); + deviceLocationService.save(deviceLocation); + } else { + deviceLocation.setUpdateTime(new Date(System.currentTimeMillis())); + deviceLocation.setCreateTime(new Date(System.currentTimeMillis())); + deviceLocationService.save(deviceLocation); + } + return Result.ok(); + } } diff --git a/src/main/java/com/onekeycall/videotablet/controller/UserController.java b/src/main/java/com/onekeycall/videotablet/controller/UserController.java index 94f5bfe..76e0dac 100644 --- a/src/main/java/com/onekeycall/videotablet/controller/UserController.java +++ b/src/main/java/com/onekeycall/videotablet/controller/UserController.java @@ -3,8 +3,11 @@ package com.onekeycall.videotablet.controller; import com.nimbusds.openid.connect.sdk.claims.UserInfo; import com.onekeycall.videotablet.dto.TokenPair; import com.onekeycall.videotablet.entity.DeviceInfo; +import com.onekeycall.videotablet.entity.DeviceLocation; import com.onekeycall.videotablet.entity.User; import com.onekeycall.videotablet.result.Result; +import com.onekeycall.videotablet.service.DeviceLocationService; +import com.onekeycall.videotablet.service.DeviceSnService; import com.onekeycall.videotablet.service.UserService; import com.onekeycall.videotablet.utils.JwtUtil; import org.slf4j.Logger; @@ -28,6 +31,10 @@ public class UserController { private RedisTemplate redisTemplate; @Autowired private JwtUtil jwtUtil; + @Autowired + private DeviceSnService deviceSnService; + @Autowired + private DeviceLocationService deviceLocationService; Logger logger = LoggerFactory.getLogger(LoginController.class); @@ -41,7 +48,7 @@ public class UserController { @PostMapping("/refresh_token") public Result refreshToken( @RequestHeader(value = "Authorization", required = false) String authHeader, @RequestHeader("Device-ID") String deviceId, - @RequestParam (value = "user_id") String userId, @RequestParam("refresh_token") String refreshToken) { + @RequestParam(value = "user_id") String userId, @RequestParam("refresh_token") String refreshToken) { logger.info("refreshToken: Authorization={} userId={} deviceId={} refreshToken={}", authHeader, userId, deviceId, refreshToken); try { @@ -65,7 +72,6 @@ public class UserController { } - @GetMapping("/get_user_info") public Result getUserInfo( @RequestHeader("Authorization") String authHeader, @RequestHeader("Device-ID") String deviceId, @@ -92,4 +98,41 @@ public class UserController { userInfo.put("avatar", user.getAvatar()); return Result.ok().data("user_info", userInfo); } + + @GetMapping("/get_sn_location") + public Result getSnLocation( + @RequestHeader("Authorization") String authHeader, @RequestHeader("Device-ID") String deviceId, + @RequestParam(value = "user_id") String userId, @RequestParam(value = "sn") String sn + ) { + + // 1. 校验 Authorization 头 + if (!authHeader.startsWith("Bearer ")) { + return Result.error().message("Invalid Authorization header"); + } + String token = authHeader.substring(7); // 去掉 "Bearer " 前缀 + + // 2. 校验 Token + if (!jwtUtil.validateAccessToken(userId, token, deviceId)) { + return Result.error().message("Invalid token"); + } + + User user = userService.getUserByUserId(userId); + if (user == null) { + return Result.error().message("User not found"); + } + DeviceInfo deviceInfo = deviceSnService.findBySn(sn); + if (deviceInfo == null) { + return Result.error().message("Device not found"); + } + if (!deviceInfo.getUserId().equals(userId)) { + return Result.error().message("Device not belong to user"); + } + + DeviceLocation deviceLocation = deviceLocationService.getDeviceLocation(sn); + if (deviceLocation == null) { + return Result.error().message("Device location not found"); + } + + return Result.ok().data("device_location", deviceLocation); + } } diff --git a/src/main/java/com/onekeycall/videotablet/entity/Contact.java b/src/main/java/com/onekeycall/videotablet/entity/Contact.java index 2bcdff4..f44797b 100644 --- a/src/main/java/com/onekeycall/videotablet/entity/Contact.java +++ b/src/main/java/com/onekeycall/videotablet/entity/Contact.java @@ -1,6 +1,7 @@ package com.onekeycall.videotablet.entity; import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data @@ -12,6 +13,31 @@ public class Contact { @Column(name = "id",unique = true, nullable = false) private Long id; + @NotBlank(message = "姓名不能为空") + @Column + private String name; + + @NotBlank(message = "手机号不能为空") + @Column + private String phone_number; + + @Column + private String avatar; + + @Column + private String tag; + + @Column + private String wxid; + + @Column + private String qq; + + @Column + private String sn; + + @Column(name = "user_id") + private String userId; } diff --git a/src/main/java/com/onekeycall/videotablet/entity/DeviceLocation.java b/src/main/java/com/onekeycall/videotablet/entity/DeviceLocation.java new file mode 100644 index 0000000..2fcb68f --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/entity/DeviceLocation.java @@ -0,0 +1,50 @@ +package com.onekeycall.videotablet.entity; + +import jakarta.persistence.*; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +@Entity +@Table(name = "device_location") +public class DeviceLocation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false) + private Long id; + + @Column(name = "sn", unique = true, nullable = false) + String sn; + + @Column(name = "address", nullable = false) + String address; + + @Column(name = "location_describe") + String location_describe; + + @Column(name = "ad_code") + String ad_code; + + @Column(name = "coor_type") + String coor_type; + + @Column(name = "longitude", nullable = false, precision = 12, scale = 6) + BigDecimal longitude; + + @Column(name = "latitude", nullable = false, precision = 12, scale = 6) + BigDecimal latitude; + + @Column(name = "update_time") + Date updateTime; + + @Column(name = "create_time") + Date createTime; + + @PrePersist + protected void onCreate() { + createTime = new Date(System.currentTimeMillis()); + updateTime = new Date(System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/onekeycall/videotablet/repository/DeviceLocationRepository.java b/src/main/java/com/onekeycall/videotablet/repository/DeviceLocationRepository.java new file mode 100644 index 0000000..c21bad8 --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/repository/DeviceLocationRepository.java @@ -0,0 +1,27 @@ +package com.onekeycall.videotablet.repository; + +import com.onekeycall.videotablet.entity.DeviceLocation; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface DeviceLocationRepository extends JpaRepository { +// @Modifying +// @Transactional +// @Query(value = "INSERT INTO device_location (sn, address, longitude, latitude, update_time, create_time) " + +// "VALUES (:#{#deviceLocation.sn}, :#{#deviceLocation.address}, :#{#deviceLocation.longitude}, :#{#deviceLocation.latitude}, :#{#deviceLocation.updateTime}, :#{#deviceLocation.createTime}) " + +// "ON DUPLICATE KEY UPDATE " + +// "address = VALUES(address), " + +// "longitude = VALUES(longitude), " + +// "latitude = VALUES(latitude), " + +// "update_time = VALUES(update_time), " + +// "create_time = VALUES(create_time)", +// nativeQuery = true) +// void upsertBySn(@Param("deviceLocation") DeviceLocation deviceLocation); + boolean existsBySn(String sn); + DeviceLocation findBySn(String sn); +} diff --git a/src/main/java/com/onekeycall/videotablet/service/DeviceLocationService.java b/src/main/java/com/onekeycall/videotablet/service/DeviceLocationService.java new file mode 100644 index 0000000..05b0751 --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/service/DeviceLocationService.java @@ -0,0 +1,29 @@ +package com.onekeycall.videotablet.service; + +import com.onekeycall.videotablet.entity.DeviceLocation; +import com.onekeycall.videotablet.repository.DeviceLocationRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DeviceLocationService { + private final DeviceLocationRepository deviceSnRepository; + + @Autowired + public DeviceLocationService(DeviceLocationRepository deviceSnRepository) { + this.deviceSnRepository = deviceSnRepository; + } + + public DeviceLocation getDeviceLocation(String sn) { + return deviceSnRepository.findBySn(sn); + } + + public boolean isExist(String sn) { + return deviceSnRepository.existsBySn(sn); + } + + public void save(DeviceLocation deviceLocation) { + deviceSnRepository.save(deviceLocation); + } + +}