feat(license): 退出授权 / 释放本实例(确认后 deactivate)
设置→授权 Pro 态管理员可退出:在线 LIC- 先调 opsx deactivate(含 activation_token),成功才清本地;失败保留现状。LICOFF- 仅解本机并提示后台名额可能仍占。禁静默清码。
This commit is contained in:
1 parent
f3d27ceb04
commit
cec7c6eeaf
10 files changed
+338
-3
No files matched your search
@@ -188,6 +188,75 @@ func ActivateLicense(key string) (*models.License, error) {
|
||||
return persistLicense(lic)
|
||||
}
|
||||
|
||||
// DeactivateResult 退出授权结果。OfflineLocalOnly 表示仅解本机(LICOFF-),后台名额可能仍占。
|
||||
type DeactivateResult struct {
|
||||
OfflineLocalOnly bool `json:"offlineLocalOnly"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// DeactivateLicense 用户主动退出授权 / 释放本实例。
|
||||
// - 在线 LIC-:先 POST /v1/license/deactivate(带 activation_token),成功才清本地;失败保留现状。
|
||||
// - 离线 LICOFF-:只解本机绑定,并提示后台名额可能仍占。
|
||||
// - 旧 HMAC:仅清本地(无远端座位)。
|
||||
// 禁止在校验失败路径静默清码;本函数仅用户确认后调用。
|
||||
func DeactivateLicense() (*DeactivateResult, error) {
|
||||
db := repository.GetDB()
|
||||
if db == nil {
|
||||
return nil, fmt.Errorf("数据库未就绪")
|
||||
}
|
||||
db.RLock()
|
||||
lic := db.License
|
||||
db.RUnlock()
|
||||
if lic == nil {
|
||||
return nil, fmt.Errorf("当前未激活授权")
|
||||
}
|
||||
// 允许对仍存证的 Pro(含宽限)或刚降级但仍占远端席位的 opsx 证做主动释放
|
||||
key := strings.TrimSpace(lic.LicenseKey)
|
||||
if lic.Plan != "pro" && key == "" {
|
||||
return nil, fmt.Errorf("当前未激活授权")
|
||||
}
|
||||
|
||||
token := lic.ActivationToken
|
||||
instanceID := lic.InstanceID
|
||||
if instanceID == "" {
|
||||
instanceID = GetOrCreateInstanceID()
|
||||
}
|
||||
|
||||
result := &DeactivateResult{}
|
||||
|
||||
if key != "" && isOfflineLicenseKey(key) {
|
||||
clearStoredLicense()
|
||||
result.OfflineLocalOnly = true
|
||||
result.Message = "已解除本机离线授权。后台名额可能仍占用,如需释放请联系运营处理。"
|
||||
return result, nil
|
||||
}
|
||||
|
||||
if key != "" && isOpsxLicenseKey(key) {
|
||||
if err := remoteDeactivateLicence(key, instanceID, token); err != nil {
|
||||
return nil, fmt.Errorf("远端解绑失败,本机授权未清除: %w", err)
|
||||
}
|
||||
clearStoredLicense()
|
||||
result.Message = "已退出授权并释放本实例"
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// HMAC 或无 key 的本地 Pro
|
||||
clearStoredLicense()
|
||||
result.Message = "已清除本机授权"
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func clearStoredLicense() {
|
||||
db := repository.GetDB()
|
||||
if db == nil {
|
||||
return
|
||||
}
|
||||
db.Lock()
|
||||
db.License = nil
|
||||
db.RequestSave()
|
||||
db.Unlock()
|
||||
}
|
||||
|
||||
func persistLicense(lic *models.License) (*models.License, error) {
|
||||
db := repository.GetDB()
|
||||
db.Lock()
|
||||
|
||||
Reference in new issue
Block a user