From 503b44d92d9103c99d53e5eed63fee6348cf4666 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Fri, 8 Aug 2025 20:12:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 11 +++ sql/video_tablet_db.sql | 54 +++++++++++++ .../videotablet/config/SecurityConfig.java | 2 + .../videotablet/config/WebSocketConfig.java | 30 +++++++ .../controller/BindSnController.java | 56 +++++++++++++ .../controller/LoginController.java | 78 +++++++------------ .../controller/WebSocketController.java | 25 ++++++ .../videotablet/entity/DeviceInfo.java | 8 +- .../handler/CustomWebSocketHandler.java | 64 +++++++++++++++ .../handler/GlobalExceptionHandler.java | 10 +++ .../videotablet/handler/SignalingHandler.java | 36 +++++++++ .../interceptor/AuthHandshakeInterceptor.java | 35 +++++++++ .../repository/DeviceSnRepository.java | 8 ++ .../repository/UserRepository.java | 1 + .../videotablet/service/DeviceSnService.java | 20 +++++ .../videotablet/service/UserService.java | 4 + .../videotablet/utils/PushUtils.java | 4 + 17 files changed, 391 insertions(+), 55 deletions(-) create mode 100644 sql/video_tablet_db.sql create mode 100644 src/main/java/com/onekeycall/videotablet/config/WebSocketConfig.java create mode 100644 src/main/java/com/onekeycall/videotablet/controller/BindSnController.java create mode 100644 src/main/java/com/onekeycall/videotablet/controller/WebSocketController.java create mode 100644 src/main/java/com/onekeycall/videotablet/handler/CustomWebSocketHandler.java create mode 100644 src/main/java/com/onekeycall/videotablet/handler/SignalingHandler.java create mode 100644 src/main/java/com/onekeycall/videotablet/interceptor/AuthHandshakeInterceptor.java create mode 100644 src/main/java/com/onekeycall/videotablet/repository/DeviceSnRepository.java create mode 100644 src/main/java/com/onekeycall/videotablet/service/DeviceSnService.java create mode 100644 src/main/java/com/onekeycall/videotablet/utils/PushUtils.java diff --git a/pom.xml b/pom.xml index 7abf7f3..531abb2 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,17 @@ org.springframework.boot spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-websocket + + + + + org.springframework + spring-messaging + org.springdoc springdoc-openapi-starter-webmvc-ui diff --git a/sql/video_tablet_db.sql b/sql/video_tablet_db.sql new file mode 100644 index 0000000..f912d13 --- /dev/null +++ b/sql/video_tablet_db.sql @@ -0,0 +1,54 @@ +/* + Navicat Premium Data Transfer + + Source Server : local_mariadb + Source Server Type : MariaDB + Source Server Version : 110702 (11.7.2-MariaDB-ubu2404) + Source Host : localhost:3305 + Source Schema : video_tablet_db + + Target Server Type : MariaDB + Target Server Version : 110702 (11.7.2-MariaDB-ubu2404) + File Encoding : 65001 + + Date: 07/08/2025 11:47:20 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for devices_sn +-- ---------------------------- +DROP TABLE IF EXISTS `devices_sn`; +CREATE TABLE `devices_sn` ( + `sn` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '设备唯一标识', + `device_model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备型号', + `device_alias` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绑定用户给设备的备注', + `user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绑定的用户id', + `bind_phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绑定用户的手机', + `add_time` datetime NOT NULL COMMENT '添加时间', + `activation_time` datetime NULL DEFAULT NULL COMMENT '激活时间', + PRIMARY KEY (`sn`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for ordinary_users +-- ---------------------------- +DROP TABLE IF EXISTS `ordinary_users`; +CREATE TABLE `ordinary_users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `device_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_time` datetime NULL DEFAULT NULL, + `last_login_time` datetime(6) NOT NULL, + `update_time` datetime(6) NOT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `UKdu5v5sr43g5bfnji4vb8hg5s3`(`phone`) USING BTREE, + UNIQUE INDEX `UK2ty1xmrrgtn89xt7kyxx6ta7h`(`nickname`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java index db14cbb..c1c438a 100644 --- a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java +++ b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java @@ -25,6 +25,8 @@ public class SecurityConfig { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth + .requestMatchers("/ws/**").permitAll() + .requestMatchers("/api/ws/**", "/topic/**").permitAll() .requestMatchers("/public/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") // .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN") diff --git a/src/main/java/com/onekeycall/videotablet/config/WebSocketConfig.java b/src/main/java/com/onekeycall/videotablet/config/WebSocketConfig.java new file mode 100644 index 0000000..a508813 --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/config/WebSocketConfig.java @@ -0,0 +1,30 @@ +package com.onekeycall.videotablet.config; + +import com.onekeycall.videotablet.handler.CustomWebSocketHandler; +import com.onekeycall.videotablet.interceptor.AuthHandshakeInterceptor; +import com.onekeycall.videotablet.utils.JwtUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + @Autowired + private JwtUtil jwtUtil; + + private final CustomWebSocketHandler webSocketHandler; + + public WebSocketConfig(CustomWebSocketHandler webSocketHandler) { + this.webSocketHandler = webSocketHandler; + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(webSocketHandler, "/ws") // 客户端连接端点 + .setAllowedOrigins("*") // 允许跨域 + .addInterceptors(new AuthHandshakeInterceptor(jwtUtil)); // 握手拦截器(如JWT校验) + } +} diff --git a/src/main/java/com/onekeycall/videotablet/controller/BindSnController.java b/src/main/java/com/onekeycall/videotablet/controller/BindSnController.java new file mode 100644 index 0000000..33cf7fd --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/controller/BindSnController.java @@ -0,0 +1,56 @@ +package com.onekeycall.videotablet.controller; + +import com.onekeycall.videotablet.entity.DeviceInfo; +import com.onekeycall.videotablet.entity.User; +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 com.onekeycall.videotablet.utils.TextUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/public") +public class BindSnController { + + @Autowired + private JwtUtil jwtUtil; + @Autowired + private UserService userService; + @Autowired + private DeviceSnService deviceSnService; + + @PostMapping("/bind_sn") + public Result bindSn( + @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); + String userPhone = user.getPhone(); + + // 3. 校验 sn 是否存在 + DeviceInfo deviceInfo = deviceSnService.findBySn(sn); + if (deviceInfo == null) { + return Result.error().message("sn not found"); + } + + if (!TextUtils.isEmpty(deviceInfo.getBindPhone())) { + return Result.error().message("sn already bind"); + } + + + + return Result.ok(); + } +} diff --git a/src/main/java/com/onekeycall/videotablet/controller/LoginController.java b/src/main/java/com/onekeycall/videotablet/controller/LoginController.java index 27fea31..dd9bc29 100644 --- a/src/main/java/com/onekeycall/videotablet/controller/LoginController.java +++ b/src/main/java/com/onekeycall/videotablet/controller/LoginController.java @@ -5,15 +5,11 @@ import com.onekeycall.videotablet.entity.User; import com.onekeycall.videotablet.result.Result; import com.onekeycall.videotablet.service.UserService; import com.onekeycall.videotablet.utils.JwtUtil; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; import java.util.*; @@ -37,15 +33,34 @@ public class LoginController { } @PostMapping("/register") - public ResponseEntity registerUser(@RequestBody RegisterRequest registerRequest) { + public Result registerUser(@RequestHeader("Device-ID") String deviceId, + @RequestParam(value = "user_id") String userId, @RequestParam String password) { try { - userService.registerUser(registerRequest.getUsername(), registerRequest.getPassword()); - return new ResponseEntity<>("User registered successfully", HttpStatus.CREATED); + userService.registerUser(userId, password); + return Result.ok().message("User registered successfully"); } catch (RuntimeException e) { - return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + return Result.error().message(e.getMessage()); } } + @PostMapping("/login") + public Result login( + @RequestHeader("Device-ID") String deviceId, + @RequestParam(value = "user_id") String userId, @RequestParam String password) { + // 1. 创建认证令牌 + Authentication authenticationToken = new UsernamePasswordAuthenticationToken(userId, password); + + // 2. 使用 AuthenticationManager 进行认证(核心步骤) + Authentication authentication = authenticationManager.authenticate(authenticationToken); + + // 3. 认证成功后生成 JWT + User userDetails = (User) authentication.getPrincipal(); + TokenPair tokenPair = jwtUtil.generateTokenPair(userDetails.getUserId(), deviceId); + + // 4. 返回 Token + return Result.ok().data(Collections.singletonMap("token", tokenPair.toMap())); + } + @PostMapping("/phone_login") public Result phoneLogin( @RequestHeader("Device-ID") String deviceId, @@ -74,48 +89,6 @@ public class LoginController { } } - @PostMapping("/login") - public ResponseEntity login( - @RequestHeader("Device-ID") String deviceId, - @RequestParam(value = "user_id") String userId, @RequestParam String password) { - // 1. 创建认证令牌 - Authentication authenticationToken = new UsernamePasswordAuthenticationToken(userId, password); - - // 2. 使用 AuthenticationManager 进行认证(核心步骤) - Authentication authentication = authenticationManager.authenticate(authenticationToken); - - // 3. 认证成功后生成 JWT - User userDetails = (User) authentication.getPrincipal(); - TokenPair tokenPair = jwtUtil.generateTokenPair(userDetails.getUserId(), deviceId); - - // 4. 返回 Token - return ResponseEntity.ok(Collections.singletonMap("token", tokenPair.toMap())); - } - - // 注册请求参数类 - public static class RegisterRequest { - private String username; - private String password; - - // Getters and Setters - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - } - @PostMapping("/phone_register") public Result registerByPhone( @RequestParam String phone, @RequestParam String code, @@ -185,6 +158,9 @@ public class LoginController { return Result.error().message("verify key is expired"); } } - +// @PostMapping("/device_login") +// public Result loginByDeviceSn(){ +// +// } } \ No newline at end of file diff --git a/src/main/java/com/onekeycall/videotablet/controller/WebSocketController.java b/src/main/java/com/onekeycall/videotablet/controller/WebSocketController.java new file mode 100644 index 0000000..912c168 --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/controller/WebSocketController.java @@ -0,0 +1,25 @@ +package com.onekeycall.videotablet.controller; + +import com.onekeycall.videotablet.handler.CustomWebSocketHandler; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/ws") +public class WebSocketController { + + private final CustomWebSocketHandler webSocketHandler; + + public WebSocketController(CustomWebSocketHandler webSocketHandler) { + this.webSocketHandler = webSocketHandler; + } + + @PostMapping("/broadcast") + public ResponseEntity broadcast(@RequestBody String message) { + webSocketHandler.broadcast(message); + return ResponseEntity.ok("广播发送成功"); + } +} diff --git a/src/main/java/com/onekeycall/videotablet/entity/DeviceInfo.java b/src/main/java/com/onekeycall/videotablet/entity/DeviceInfo.java index 9c4e412..f2fe8b0 100644 --- a/src/main/java/com/onekeycall/videotablet/entity/DeviceInfo.java +++ b/src/main/java/com/onekeycall/videotablet/entity/DeviceInfo.java @@ -14,7 +14,7 @@ public class DeviceInfo { private String sn; @Column(name = "device_model", nullable = false) - private String device_model; + private String deviceModel; @Column(name = "device_alias") private String deviceAlias; @@ -23,12 +23,12 @@ public class DeviceInfo { private String userId; @Column(name = "bind_phone") - private String bind_phone; + private String bindPhone; @Column(name = "add_time", nullable = false) - private Date add_time; + private Date addTime; @Column(name = "activation_time") - private Date activation_time; + private Date activationTime; } diff --git a/src/main/java/com/onekeycall/videotablet/handler/CustomWebSocketHandler.java b/src/main/java/com/onekeycall/videotablet/handler/CustomWebSocketHandler.java new file mode 100644 index 0000000..d99e40a --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/handler/CustomWebSocketHandler.java @@ -0,0 +1,64 @@ +package com.onekeycall.videotablet.handler; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +@Component +public class CustomWebSocketHandler extends TextWebSocketHandler { + + // 存储活跃会话(线程安全) + private final Map sessions = new ConcurrentHashMap<>(); + + @Override + public void afterConnectionEstablished(WebSocketSession session) { + String sessionId = session.getId(); + sessions.put(sessionId, session); + log.info("✅ 连接建立: ID={}, 当前连接数: {}", sessionId, sessions.size()); + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) { + String payload = message.getPayload(); + log.info("📩 收到消息: {}", payload); + + // 示例:回复客户端 + String reply = "服务器已接收: " + payload; + try { + session.sendMessage(new TextMessage(reply)); + } catch (IOException e) { + log.error("回复失败: ID={}", session.getId(), e); + } + + // 可选:广播给所有客户端 + // broadcast("用户" + sessionId + "说: " + payload); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { + String sessionId = session.getId(); + sessions.remove(sessionId); + log.info("❌ 连接关闭: ID={}, 原因: {}", sessionId, status.getReason()); + } + + // 广播消息给所有客户端 + public void broadcast(String message) { + sessions.values().stream() + .filter(WebSocketSession::isOpen) + .forEach(session -> { + try { + session.sendMessage(new TextMessage(message)); + } catch (IOException e) { + log.error("广播失败: ID={}", session.getId(), e); + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java b/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java index 2572cd2..a84fa7f 100644 --- a/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java +++ b/src/main/java/com/onekeycall/videotablet/handler/GlobalExceptionHandler.java @@ -3,6 +3,7 @@ package com.onekeycall.videotablet.handler; import com.onekeycall.videotablet.result.Result; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; @@ -98,4 +99,13 @@ public class GlobalExceptionHandler { // }); // return errors; // } + + @ResponseBody + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(InvalidTokenException.class) + public Result handleInvalidTokenException(InvalidTokenException e) { + // 控制台打印异常 + e.printStackTrace(); + return Result.error().message(e.getMessage()); + } } \ No newline at end of file diff --git a/src/main/java/com/onekeycall/videotablet/handler/SignalingHandler.java b/src/main/java/com/onekeycall/videotablet/handler/SignalingHandler.java new file mode 100644 index 0000000..ace7de2 --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/handler/SignalingHandler.java @@ -0,0 +1,36 @@ +package com.onekeycall.videotablet.handler; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SignalingHandler extends TextWebSocketHandler { + private static final Map sessions = new ConcurrentHashMap<>(); + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) { + // 使用 Jackson 解析 + ObjectMapper mapper = new ObjectMapper(); + try { + JsonNode json = mapper.readTree(message.getPayload()); + String targetId = json.get("targetId").asText();// 目标用户ID + if (sessions.containsKey(targetId)) { + sessions.get(targetId).sendMessage(message); // 转发信令 + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void afterConnectionEstablished(WebSocketSession session) { + String deviceId = session.getHandshakeHeaders().getFirst("device-id"); + sessions.put(deviceId, session); // 保存会话 + } +} diff --git a/src/main/java/com/onekeycall/videotablet/interceptor/AuthHandshakeInterceptor.java b/src/main/java/com/onekeycall/videotablet/interceptor/AuthHandshakeInterceptor.java new file mode 100644 index 0000000..898a1a1 --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/interceptor/AuthHandshakeInterceptor.java @@ -0,0 +1,35 @@ +package com.onekeycall.videotablet.interceptor; + +import com.onekeycall.videotablet.utils.JwtUtil; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.HandshakeInterceptor; + +import java.util.Map; + +public class AuthHandshakeInterceptor implements HandshakeInterceptor { + + private final JwtUtil jwtUtil; + + public AuthHandshakeInterceptor(JwtUtil jwtUtil) { + this.jwtUtil = jwtUtil; + } + + @Override + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { + String userId = request.getHeaders().getFirst("user_id"); + String authHeader = request.getHeaders().getFirst("Authorization"); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + return false; + } + String token = authHeader.substring(7); // 去掉 "Bearer " 前缀 + String deviceId = request.getHeaders().getFirst("Device-ID"); + return jwtUtil.validateAccessToken(userId, token, deviceId); // 自定义校验逻辑 + } + + @Override + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { + + } +} diff --git a/src/main/java/com/onekeycall/videotablet/repository/DeviceSnRepository.java b/src/main/java/com/onekeycall/videotablet/repository/DeviceSnRepository.java new file mode 100644 index 0000000..957cbab --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/repository/DeviceSnRepository.java @@ -0,0 +1,8 @@ +package com.onekeycall.videotablet.repository; + +import com.onekeycall.videotablet.entity.DeviceInfo; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DeviceSnRepository extends JpaRepository { + DeviceInfo findBySn(String deviceId); +} diff --git a/src/main/java/com/onekeycall/videotablet/repository/UserRepository.java b/src/main/java/com/onekeycall/videotablet/repository/UserRepository.java index 9cb1dd2..49dccd6 100644 --- a/src/main/java/com/onekeycall/videotablet/repository/UserRepository.java +++ b/src/main/java/com/onekeycall/videotablet/repository/UserRepository.java @@ -11,4 +11,5 @@ public interface UserRepository extends JpaRepository { boolean existsByUserId(String userId); boolean existsPasswordByUserId(String userId); Optional findUserByPhone(String phone); + Optional findUserByUserId(String userId); } \ No newline at end of file diff --git a/src/main/java/com/onekeycall/videotablet/service/DeviceSnService.java b/src/main/java/com/onekeycall/videotablet/service/DeviceSnService.java new file mode 100644 index 0000000..54efaad --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/service/DeviceSnService.java @@ -0,0 +1,20 @@ +package com.onekeycall.videotablet.service; + +import com.onekeycall.videotablet.entity.DeviceInfo; +import com.onekeycall.videotablet.repository.DeviceSnRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DeviceSnService { + private final DeviceSnRepository deviceSnRepository; + + @Autowired + public DeviceSnService(DeviceSnRepository deviceSnRepository) { + this.deviceSnRepository = deviceSnRepository; + } + + public DeviceInfo findBySn(String sn) { + return deviceSnRepository.findBySn(sn); + } +} diff --git a/src/main/java/com/onekeycall/videotablet/service/UserService.java b/src/main/java/com/onekeycall/videotablet/service/UserService.java index ae36159..fb32df5 100644 --- a/src/main/java/com/onekeycall/videotablet/service/UserService.java +++ b/src/main/java/com/onekeycall/videotablet/service/UserService.java @@ -109,4 +109,8 @@ public class UserService implements UserDetailsService { return Result.ok().message("change password success"); } } + + public User getUserByUserId(String userId) { + return userRepository.findUserByUserId(userId).orElseThrow(() -> new RuntimeException("User not found with userId: " + userId)); + } } \ No newline at end of file diff --git a/src/main/java/com/onekeycall/videotablet/utils/PushUtils.java b/src/main/java/com/onekeycall/videotablet/utils/PushUtils.java new file mode 100644 index 0000000..0b25cba --- /dev/null +++ b/src/main/java/com/onekeycall/videotablet/utils/PushUtils.java @@ -0,0 +1,4 @@ +package com.onekeycall.videotablet.utils; + +public class PushUtils { +}