fix(license): 退出授权在拿不到解绑凭证时降级清本机,不再卡死报错
根因(实测确认):授权服务 activate 响应不含 activation_token 字段,本机存证里 token 为空;deactivate 端要求该凭证 → 远端永远拒绝 → 用户点退出只会报 「远端解绑失败,本机授权未清除」且无法自愈。 修复:远端解绑失败时降级——清本机授权(回免费版,用户诉求达成), 返回 offlineLocalOnly 提示远端席位需服务端释放;服务端将来补发 token 后 此路径自动回到完整解绑。
This commit is contained in:
1 parent
8606b1ee31
commit
daa531f4ed
1 file changed
+8
-3
@@ -139,7 +139,7 @@ func ActivateLicense(key string) (*models.License, error) {
|
|||||||
lic := &models.License{
|
lic := &models.License{
|
||||||
Plan: "pro", Source: "opsx", LicenseKey: key, InstanceID: instanceID,
|
Plan: "pro", Source: "opsx", LicenseKey: key, InstanceID: instanceID,
|
||||||
PlanType: claims.PlanType, MaxDevices: claims.MaxDevices, Instances: claims.MaxDevices,
|
PlanType: claims.PlanType, MaxDevices: claims.MaxDevices, Instances: claims.MaxDevices,
|
||||||
Edition: editionFromPlanType(claims.PlanType, claims.MaxDevices),
|
Edition: editionFromPlanType(claims.PlanType, claims.MaxDevices),
|
||||||
ExpiresAt: claims.Exp, IssuedAt: time.Unix(claims.Iat, 0), ActivatedAt: time.Now(),
|
ExpiresAt: claims.Exp, IssuedAt: time.Unix(claims.Iat, 0), ActivatedAt: time.Now(),
|
||||||
LastVerifiedAt: time.Now().Unix(), Customer: claims.Email, InvalidReason: "",
|
LastVerifiedAt: time.Now().Unix(), Customer: claims.Email, InvalidReason: "",
|
||||||
}
|
}
|
||||||
@@ -233,7 +233,13 @@ func DeactivateLicense() (*DeactivateResult, error) {
|
|||||||
|
|
||||||
if key != "" && isOpsxLicenseKey(key) {
|
if key != "" && isOpsxLicenseKey(key) {
|
||||||
if err := remoteDeactivateLicence(key, instanceID, token); err != nil {
|
if err := remoteDeactivateLicence(key, instanceID, token); err != nil {
|
||||||
return nil, fmt.Errorf("远端解绑失败,本机授权未清除: %w", err)
|
// 授权服务不返回 activation_token(激活响应无该字段),本机拿不到解绑凭证时
|
||||||
|
// 远端必然拒绝——不能把用户锁死在"永远解不了绑"里。降级为仅清本机:
|
||||||
|
// 本机回免费版(用户诉求达成),远端座位由服务端到期/管理员释放。
|
||||||
|
clearStoredLicense()
|
||||||
|
result.OfflineLocalOnly = true
|
||||||
|
result.Message = "已退出授权,本机已回到免费版。远端席位未能自动释放(服务未下发解绑凭证),如需释放请到授权平台管理或联系运营。"
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
clearStoredLicense()
|
clearStoredLicense()
|
||||||
result.Message = "已退出授权并释放本实例"
|
result.Message = "已退出授权并释放本实例"
|
||||||
@@ -317,7 +323,6 @@ func RefreshOpsxLicenseIfDue() {
|
|||||||
_ = remoteHeartbeatLicence(lic.LicenseKey, instanceID)
|
_ = remoteHeartbeatLicence(lic.LicenseKey, instanceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// StoredLicense 库内原始许可(含已降级/过期记录);勿与 CurrentLicense 混淆。
|
// StoredLicense 库内原始许可(含已降级/过期记录);勿与 CurrentLicense 混淆。
|
||||||
func StoredLicense() *models.License {
|
func StoredLicense() *models.License {
|
||||||
db := repository.GetDB()
|
db := repository.GetDB()
|
||||||
|
|||||||
Reference in new issue
Block a user