提交图

19 次代码提交

作者 SHA1 备注 提交日期
XuqmGroup
8e131906d8 feat(license): 添加应用信息接口并增强验证逻辑
- 在 SecurityConfig 中为 /api/license/app-info 接口添加无需认证访问权限
- 优化 GlobalExceptionHandler 中的参数验证错误信息显示,提供详细的字段错误信息
- 移除 RegisterRequest 和 VerifyRequest 中的注解验证,改用代码手动验证
- 为 register 接口添加 deviceId 非空检查
- 为 verify 接口添加 deviceId 和 token 非空检查
- 移除 RegisterRequest 中对 deviceId 的 @NotBlank 注解验证
- 移除 VerifyRequest 中对 deviceId 和 token 的 @NotBlank 注解验证
2026-05-23 02:23:53 +08:00
XuqmGroup
b7c2f0144f refactor(license): remove server-side package name validation
Package name matching is now entirely the SDK's responsibility.
- DeviceService: drop packageName param from register/verify, delete validatePackageName()
- LicensePublicController: remove matchesPackageName check in resolveAppKey(),
  remove packageName from service calls, add GET /api/license/app-info for
  SDK appKey-only flow to fetch configured package names for local comparison

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:28:51 +08:00
XuqmGroup
0e5558116c feat(system): 添加系统版本查询和数据库迁移功能
- 移除 license-service 中 DeviceEntity 的 device_id 唯一约束注解
- 添加 /api/system/version 接口用于查询当前部署版本
- 实现数据库 schema 版本化迁移机制
- 添加自动执行数据库迁移的功能
- 在前端安全中心界面显示当前版本和迁移状态
- 优化配置文件修复逻辑和代码结构
2026-05-22 23:04:36 +08:00
XuqmGroup
1a0ef7d886 support multi-app device registration per device
- Add composite unique constraint (app_key, device_id) on DeviceEntity
- Remove global unique constraint from device_id column
- Update DeviceRepository: findByAppKeyAndDeviceId returns Optional,
  findByDeviceId returns List for multi-app lookups
- Update DeviceService.register/verify to scope lookups by appKey
  so same physical device can register independently for each app
- Update LicenseInternalController.getDevice to return list

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:47:17 +08:00
XuqmGroup
843ed69f3c license: fix device re-register appKey update, add license file parser
- DeviceService.register(): update appKey when device switches to a different app
  and adjust registered device counters for old/new appKey
- LicenseAdminController: fix updateAppLicense parameter count mismatch
- AppController: add POST /api/apps/license/parse endpoint for license file decryption
- SecurityCenterView: add License file parser UI with upload and paste support
- appApi: add parseLicenseFile() method

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:37:46 +08:00
XuqmGroup
8c9bfb6acd feat: license 文件作为通用凭证支持所有服务 SDK 初始化
- LicenseFileCrypto 移至 common 模块并新增 decrypt() 方法
- LicenseFileCrypto.LicensePayload 携带 appKey / packageName / iosBundleId / harmonyBundleName,matchesPackageName() 支持三端包名任一匹配
- tenant-service downloadLicenseFile:去掉"License 服务已开通"限制,app 创建即可下载;payload 新增 iosBundleId / harmonyBundleName
- im / push / update / license 四个服务 SDK 初始化端点均支持双模式:
  · licenseFile 模式:解密文件取 appKey,比对 packageName(无需调 tenant-service)
  · appKey 模式:调 tenant-service 取 platformInfo 比对 packageName(原有逻辑)
- appKey 参数由必填改为可选(与 licenseFile 二选一)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 16:47:30 +08:00
XuqmGroup
4c0db6e9b7 feat: validate packageName against appKey on SDK and license init
SdkConfigController: require packageName param; reject with 403 if it doesn't
match the platform-specific name registered for the app (skipped when app has
no name configured yet).

LicensePublicController: add required packageName to register/verify requests.
DeviceService: validatePackageName() checks against android/ios/harmony names
stored on AppLicenseEntity; rejects if any are configured and none match.
AppLicenseEntity: add android_package_name, ios_bundle_id, harmony_bundle_name
columns (auto-migrated via ddl-auto=update).
LicenseInternalController/AppLicenseService: accept and persist package names
via upsert endpoint.
LicenseServiceClient/FeatureServiceManager: pass app package names when syncing
license records to license-service.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 16:31:50 +08:00
XuqmGroup
7a530eb35b fix(license): 新设备注册时初始化 lastVerifiedAt 字段
新设备首次注册成功后,lastVerifiedAt 原本为 null,
导致控制台"最后验证时间"始终为空直到缓存过期后的首次 verify 调用。
注册即视为首次验证,同步写入 lastVerifiedAt。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 16:39:30 +08:00
XuqmGroup
b0e7f198db feat(license): 支持修改 License 过期时间 + 修复一键更新三个问题
License 过期时间:
- LicenseAdminController PATCH 接口增加 expiresAt 字段
- AppLicenseService.update() 移除"一旦设置不可修改"限制,支持清空(永久)或更新日期

一键更新 (SystemUpdateService) 修复:
1. 改用 docker compose (v2) 替换 docker-compose (v1)
2. isRunning/getCurrentImage 去掉 project=xuqm 标签过滤
   (deploy.sh 不传 -p 参数,实际 project 标签为目录名)
3. 拉取前读取 deployRoot/.env 中的 REGISTRY 凭据并执行 docker login

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 16:26:01 +08:00
XuqmGroup
8a3c41d5ff feat(license): 租户自主管理最大设备数,ops 彻底移除 license 管理
license-service:
- LicenseAdminController: 新增 PATCH /api/license/admin/apps/{appKey},
  租户可直接修改 maxDevices / isActive / remark

tenant-service:
- OpsController: 移除 GET /api/ops/apps/{appKey}/license 和
  PUT /api/ops/apps/{appKey}/license/max-devices 两个端点,
  同时移除 licenseServiceClient 字段注入
- LicenseServiceClient: 移除 updateMaxDevices() 和 getAppLicenseStatus()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 12:45:33 +08:00
XuqmGroup
02ad5aad06 fix(private): 私有化部署 CORS 放开所有 Origin
私有化部署时客户使用自定义域名,原硬编码的 *.xuqinmin.com 白名单
导致 WebSocket 握手和跨域请求被 Spring Security CORS 过滤器拒绝(426/403)。
检测 DEPLOYMENT_MODE=PRIVATE 环境变量,私有化模式下允许所有 Origin。
影响范围:im-service / file-service / license-service / update-service。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 10:44:33 +08:00
XuqmGroup
450a44de68 fix: isolate private deployment databases and fix store review refresh bugs
application.yml — all services:
- Replace hardcoded jdbc:mysql://39.107.53.187 with ${SPRING_DATASOURCE_URL:fallback}
- Same for SPRING_DATASOURCE_USERNAME/PASSWORD
- im-service: replace hardcoded redisdev.xuqinmin.com with ${SPRING_DATA_REDIS_*}
  This ensures docker-compose environment overrides take effect; without these
  placeholders, Spring Boot's relaxed binding couldn't override the YAML values
  and the private deployment connected to production databases.

StoreSubmissionService.refreshStoreReviewStatus — two bugs fixed:
1. MI/UNDER_REVIEW_XIAOMI branch now guards against downgrading APPROVED state.
   Xiaomi's poll API returns UNDER_REVIEW_XIAOMI when the submitted version is
   not yet the live version, even after the store approves it. Previously this
   caused the manual refresh to overwrite a webhook-confirmed APPROVED with
   UNDER_REVIEW on every click.
2. When the poll returns APPROVED but currentSubmissionLive=false (another version
   is live on the store), no longer overwrite an existing APPROVED (from webhook)
   with nonCurrentRelease=true. The webhook is authoritative; the live version
   difference just means distribution is pending, not that this is a non-current
   release. Only adds nonCurrentRelease when transitioning FROM a non-APPROVED
   state (true pre-existing detection).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 18:25:50 +08:00
XuqmGroup
3bc8a39d0f fix: return 401 (not 403) for unauthenticated requests across all services
Spring Security's default Http403ForbiddenEntryPoint was returning 403
for all auth failures. Frontend clients treat 403 as a permission error
(not an auth error), so silent loops occurred instead of proper re-login.
Adding a custom AuthenticationEntryPoint that returns 401 makes clients
handle auth failures correctly (show login page on 401).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:31:24 +08:00
XuqmGroup
57ad8f7f25 fix: app_key backfill on re-registration + notify after tx commit
- LicenseDeviceService: update app_key on re-registration if blank,
  fixing devices that registered before the app_key column was added
- FeatureServiceManager: send activation IM notification in afterCommit()
  hook so the frontend refresh sees the committed DB state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:04:57 +08:00
XuqmGroup
10f0043f15 License服务改造:平台无关、ops管理最大设备数、有效期不可变
- LICENSE审批只创建1条FeatureServiceEntity记录(不分平台)
- FeatureServiceManager扩展平台无关查询到LICENSE
- LicenseServiceClient新增getAppLicenseStatus/updateMaxDevices方法
- OpsController新增license管理接口(GET状态、PUT最大设备数)
- AppLicenseService.update中expiresAt一旦设置不可修改
- 审批流程支持传入expiresAt参数

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 22:38:46 +08:00
XuqmGroup
bc1165d22e Align license service with app model 2026-05-15 21:42:10 +08:00
XuqmGroup
4f59fead0a Store license check user info 2026-05-15 21:29:48 +08:00
XuqmGroup
d5b8f03996 Fix license service activation visibility 2026-05-15 21:25:58 +08:00
XuqmGroup
acfc2cbfbe Add license service and tenant integration 2026-05-15 21:00:24 +08:00