326 lines
13 KiB
Java
326 lines
13 KiB
Java
package com.onekeycall.videotablet.controller.user;
|
|
|
|
import com.google.gson.JsonObject;
|
|
import com.onekeycall.videotablet.config.PushIdConfig;
|
|
import com.onekeycall.videotablet.controller.pub.LoginController;
|
|
import com.onekeycall.videotablet.dto.TokenPair;
|
|
import com.onekeycall.videotablet.entity.*;
|
|
import com.onekeycall.videotablet.gson.GsonUtils;
|
|
import com.onekeycall.videotablet.result.Result;
|
|
import com.onekeycall.videotablet.service.*;
|
|
import com.onekeycall.videotablet.utils.DevicePushUtils;
|
|
import com.onekeycall.videotablet.utils.JwtUtil;
|
|
import com.onekeycall.videotablet.utils.TextUtils;
|
|
import org.apache.commons.lang3.RandomStringUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.function.Consumer;
|
|
|
|
@RestController
|
|
@RequestMapping("/user")
|
|
public class UserController {
|
|
|
|
private final UserService userService;
|
|
private final AuthenticationManager authenticationManager;
|
|
|
|
@Autowired
|
|
private RedisTemplate<String, Object> redisTemplate;
|
|
@Autowired
|
|
private JwtUtil jwtUtil;
|
|
@Autowired
|
|
private DeviceSnService deviceSnService;
|
|
@Autowired
|
|
private DeviceLocationService deviceLocationService;
|
|
@Autowired
|
|
private DeviceApkInfoService deviceApkInfoService;
|
|
@Autowired
|
|
private ApkIconService apkIconService;
|
|
@Autowired
|
|
private ScreenshotService screenshotService;
|
|
|
|
Logger logger = LoggerFactory.getLogger(LoginController.class);
|
|
|
|
@Autowired
|
|
public UserController(UserService userService, AuthenticationManager authenticationManager) {
|
|
this.userService = userService;
|
|
this.authenticationManager = authenticationManager;
|
|
}
|
|
|
|
/**
|
|
* 用户app发送绑定推送到手机
|
|
*
|
|
* @param authHeader
|
|
* @param deviceId
|
|
* @param userId
|
|
* @param sn
|
|
* @return
|
|
*/
|
|
@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) {
|
|
|
|
logger.info("bindSn: authHeader={}, deviceId={}, userId={}, sn={}", authHeader, deviceId, userId, sn);
|
|
if (!authHeader.startsWith("Bearer ")) {
|
|
return Result.error().message("Invalid Authorization header");
|
|
}
|
|
String token = authHeader.substring(7); // 去掉 "Bearer " 前缀
|
|
|
|
if (!jwtUtil.validateAccessToken(userId, token, deviceId)) {
|
|
return Result.error().message("Invalid token");
|
|
}
|
|
|
|
User user = userService.getUserByUserId(userId);
|
|
String userPhone = user.getPhone();
|
|
|
|
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");
|
|
}
|
|
|
|
try {
|
|
String verifyKey = RandomStringUtils.randomAlphanumeric(32);
|
|
JsonObject params = new JsonObject();
|
|
params.addProperty("verify_key", verifyKey);
|
|
params.addProperty("phone", userPhone);
|
|
params.addProperty("expire_time", System.currentTimeMillis() + 60 * 1000);
|
|
|
|
// PushUtils.aliyunAsyncPush("1", params.toString(), sn);
|
|
DevicePushUtils.aliyunAsyncPush(PushIdConfig.BIND_DEVICE, sn, params.toString());
|
|
redisTemplate.opsForValue().set(sn, verifyKey, 1, TimeUnit.MINUTES);
|
|
return Result.ok().message("send message success");
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return Result.error().message(e.getMessage());
|
|
}
|
|
|
|
}
|
|
|
|
@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) {
|
|
logger.info("refreshToken: Authorization={} userId={} deviceId={} refreshToken={}", authHeader, userId, deviceId, refreshToken);
|
|
|
|
try {
|
|
// 验证refreshToken的有效性
|
|
if (!jwtUtil.validateRefreshToken(refreshToken, userId)) {
|
|
return Result.error().message("无效的refresh token");
|
|
}
|
|
|
|
// 从refreshToken中获取用户ID
|
|
TokenPair tokenPair = jwtUtil.refreshAccessToken(refreshToken, deviceId);
|
|
|
|
// 构建返回结果
|
|
Map<String, Object> tokenMap = new HashMap<>();
|
|
tokenMap.put("access_token", tokenPair.getAccess_token());
|
|
|
|
return Result.ok().data(tokenMap);
|
|
} catch (Exception e) {
|
|
logger.error("刷新token失败", e);
|
|
return Result.error().message("刷新token失败: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
|
|
@GetMapping("/get_user_info")
|
|
public Result getUserInfo(
|
|
@RequestHeader("Authorization") String authHeader, @RequestHeader("Device-ID") String deviceId,
|
|
@RequestParam(value = "user_id") String userId
|
|
) {
|
|
|
|
// 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);
|
|
|
|
Map<String, Object> userInfo = new HashMap<>();
|
|
userInfo.put("user_id", user.getUserId());
|
|
userInfo.put("phone", user.getPhone());
|
|
userInfo.put("nickname", user.getNickname());
|
|
userInfo.put("avatar", user.getAvatar());
|
|
userInfo.put("set_password", !TextUtils.isEmpty(user.getPassword()));
|
|
return Result.ok().data("user_info", userInfo);
|
|
}
|
|
|
|
@GetMapping("/get_sn_list")
|
|
public Result register(
|
|
@RequestHeader("Authorization") String authHeader, @RequestHeader("Device-ID") String deviceId,
|
|
@RequestParam(value = "user_id") String userId, @RequestParam(value = "sn", required = false) 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");
|
|
}
|
|
|
|
if (TextUtils.isEmpty(sn)) {
|
|
List<DeviceInfo> deviceInfos = deviceSnService.findByUserId(userId);
|
|
if (deviceInfos == null || deviceInfos.isEmpty()) {
|
|
return Result.notFound().message("sn not found");
|
|
} else {
|
|
return Result.ok().data("deviceInfos", deviceInfos);
|
|
}
|
|
} else {
|
|
DeviceInfo deviceInfo = deviceSnService.findBySn(sn);
|
|
if (deviceInfo == null) {
|
|
return Result.notFound().message("sn not found");
|
|
}
|
|
|
|
if (!deviceInfo.getUserId().equals(userId)) {
|
|
return Result.error().message("sn not belong to user");
|
|
}
|
|
|
|
return Result.ok().data("deviceInfo", deviceInfo);
|
|
}
|
|
}
|
|
|
|
@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("devices_location", deviceLocation);
|
|
}
|
|
|
|
@GetMapping("/get_device_apk_list")
|
|
public Result getDeviceApkList(@RequestParam String sn) {
|
|
|
|
DeviceApkInfo deviceApkInfo = deviceApkInfoService.getDeviceApkInfoBySn(sn);
|
|
if (deviceApkInfo == null || deviceApkInfo.getApkList() == null) {
|
|
return Result.notFound().message("未找到设备APK信息");
|
|
}
|
|
List<ApkInfo> apkList = deviceApkInfo.getApkList();
|
|
apkList.stream().forEach(new Consumer<ApkInfo>() {
|
|
@Override
|
|
public void accept(ApkInfo apkInfo) {
|
|
Optional<ApkIconFileInfo> apkIconFileInfo = apkIconService.findMaxVersionCodeByPackageName(apkInfo.getPackageName());
|
|
apkIconFileInfo.ifPresent(iconFileInfo -> apkInfo.setIconUrl(iconFileInfo.getFileName()));
|
|
}
|
|
});
|
|
return Result.ok().data(deviceApkInfo.getApkList());
|
|
}
|
|
|
|
@PostMapping("/control_app")
|
|
public Result controlApp(@RequestParam String sn,
|
|
@RequestParam(value = "package_name") String packageName,
|
|
@RequestParam String action
|
|
) throws ExecutionException, InterruptedException {
|
|
Map<String, Object> params = new HashMap<>();
|
|
params.put("package_name", packageName);
|
|
switch (action) {
|
|
case "open":
|
|
DevicePushUtils.aliyunAsyncPush(PushIdConfig.OPEN_APP, sn, GsonUtils.toJSONString(params));
|
|
break;
|
|
case "kill":
|
|
DevicePushUtils.aliyunAsyncPush(PushIdConfig.KILL_APP, sn, GsonUtils.toJSONString(params));
|
|
break;
|
|
case "clear":
|
|
DevicePushUtils.aliyunAsyncPush(PushIdConfig.CLEAR_APP, sn, GsonUtils.toJSONString(params));
|
|
break;
|
|
case "uninstall":
|
|
DevicePushUtils.aliyunAsyncPush(PushIdConfig.UNINSTALL_APP, sn, GsonUtils.toJSONString(params));
|
|
break;
|
|
default:
|
|
return Result.error().message("action is empty");
|
|
}
|
|
return Result.ok().message("success");
|
|
}
|
|
|
|
|
|
@PostMapping("/screen_snapshot")
|
|
public Result screenSnapshot(@RequestParam String sn) throws ExecutionException, InterruptedException {
|
|
Map<String, Object> params = new HashMap<>();
|
|
params.put("sn", sn);
|
|
params.put("timestamp", System.currentTimeMillis());
|
|
DevicePushUtils.aliyunAsyncPush(PushIdConfig.SCREEN_SNAPSHOT, sn, GsonUtils.toJSONString(params));
|
|
return Result.ok().message("success");
|
|
}
|
|
|
|
@GetMapping("/get_snapshot")
|
|
public Result getScreenSnapshot(@RequestParam String sn) {
|
|
List<ScreenshotInfo> screenSnapshot = screenshotService.findBySn(sn);
|
|
if (screenSnapshot == null) {
|
|
return Result.notFound().message("Screen snapshot not found");
|
|
}
|
|
return Result.ok().data(screenSnapshot);
|
|
}
|
|
|
|
@PostMapping("/delete_all_snapshot")
|
|
public Result deleteAllScreenSnapshot(@RequestParam String sn) {
|
|
screenshotService.deleteAllBySn(sn);
|
|
return Result.ok().message("success");
|
|
}
|
|
|
|
@PostMapping("/delete_snapshot")
|
|
public Result deleteScreenSnapshot(@RequestParam String sn, @RequestParam Long id) {
|
|
if (screenshotService.existsBySnAndId(sn, id)) {
|
|
boolean deleteSuccess = screenshotService.deleteBySnAndId(sn, id);
|
|
if (deleteSuccess) {
|
|
logger.info("deleteScreenSnapshot success, sn: {}, id: {}", sn, id);
|
|
} else {
|
|
logger.info("deleteScreenSnapshot fail, sn: {}, id: {}", sn, id);
|
|
}
|
|
} else {
|
|
logger.info("deleteScreenSnapshot not found, sn: {}, id: {}", sn, id);
|
|
}
|
|
return Result.ok().message("success");
|
|
}
|
|
}
|