diff --git a/src/main/kotlin/app/termora/account/AccountManager.kt b/src/main/kotlin/app/termora/account/AccountManager.kt index 65300c6..12ef524 100644 --- a/src/main/kotlin/app/termora/account/AccountManager.kt +++ b/src/main/kotlin/app/termora/account/AccountManager.kt @@ -42,7 +42,7 @@ class AccountManager private constructor() : ApplicationRunnerExtension { fun getSecretKey() = account.secretKey fun getPublicKey() = account.publicKey fun getPrivateKey() = account.privateKey - fun isSigned() = isFreePlan().not() && accountProperties.signed + fun isSigned() = accountProperties.signed fun isLocally() = account.isLocally fun getLastSynchronizationOn() = accountProperties.lastSynchronizationOn fun getAccessToken() = account.accessToken diff --git a/src/main/kotlin/app/termora/account/AccountOption.kt b/src/main/kotlin/app/termora/account/AccountOption.kt index bf48ae1..b2436b8 100644 --- a/src/main/kotlin/app/termora/account/AccountOption.kt +++ b/src/main/kotlin/app/termora/account/AccountOption.kt @@ -97,7 +97,7 @@ class AccountOption : JPanel(BorderLayout()), OptionsPane.Option, Disposable { planBox.add(Box.createHorizontalStrut(16)) val upgrade = JXHyperlink(object : AnAction(I18n.getString("termora.settings.account.upgrade")) { override fun actionPerformed(evt: AnActionEvent) { - + Application.browse(URI.create("https://www.termora.app/pricing")) } }) upgrade.isFocusable = false diff --git a/src/main/kotlin/app/termora/account/LoginServerDialog.kt b/src/main/kotlin/app/termora/account/LoginServerDialog.kt index 75d0293..c11b949 100644 --- a/src/main/kotlin/app/termora/account/LoginServerDialog.kt +++ b/src/main/kotlin/app/termora/account/LoginServerDialog.kt @@ -362,6 +362,7 @@ class LoginServerDialog(owner: Window) : DialogWrapper(owner) { super.doOKAction() } } catch (e: Exception) { + if (log.isErrorEnabled) log.error(e.message, e) withContext(Dispatchers.Swing) { OptionPane.showMessageDialog( this@LoginServerDialog, diff --git a/src/main/kotlin/app/termora/account/PushService.kt b/src/main/kotlin/app/termora/account/PushService.kt index 5c732ae..b2b7ad1 100644 --- a/src/main/kotlin/app/termora/account/PushService.kt +++ b/src/main/kotlin/app/termora/account/PushService.kt @@ -117,13 +117,23 @@ class PushService private constructor() : SyncService(), Disposable, Application } private fun push(data: Data) { + val encryptedData = encryptData(data.id, data.data, data.ownerId) + if (encryptedData.isBlank()) { + if (log.isErrorEnabled) { + log.error("数据: {} 没有找到对应 ownerId 的密钥,此数据将标记为已同步", data.id) + } + // 标记为已经同步 + updateData(data.id, synced = true) + return + } + val requestData = PushDataRequest( objectId = data.id, ownerId = data.ownerId, ownerType = data.ownerType, version = data.version, type = data.type, - data = encryptData(data.id, data.data), + data = encryptedData, ) val request = Request.Builder().url("${accountManager.getServer()}/v1/data/push") diff --git a/src/main/kotlin/app/termora/account/SyncService.kt b/src/main/kotlin/app/termora/account/SyncService.kt index ef3e09e..61996c8 100644 --- a/src/main/kotlin/app/termora/account/SyncService.kt +++ b/src/main/kotlin/app/termora/account/SyncService.kt @@ -3,6 +3,7 @@ package app.termora.account import app.termora.AES import app.termora.database.* import app.termora.database.Data.Companion.toData +import okhttp3.internal.EMPTY_BYTE_ARRAY import org.apache.commons.codec.binary.Base64 import org.apache.commons.codec.digest.DigestUtils import org.apache.commons.lang3.ObjectUtils @@ -75,14 +76,21 @@ abstract class SyncService { } } - protected fun encryptData(id: String, data: String): String { + protected fun encryptData(id: String, data: String, ownerId: String): String { val iv = DigestUtils.sha256(id).copyOf(12) - return Base64.encodeBase64String( - AES.GCM.encrypt( - accountManager.getSecretKey(), iv, - data.toByteArray() - ) - ) + var secretKey = EMPTY_BYTE_ARRAY + if (ownerId != accountManager.getAccountId()) { + val team = accountManager.getTeams().firstOrNull { it.id == ownerId } + if (team == null) { + return StringUtils.EMPTY + } else { + secretKey = team.secretKey + } + } else if (ownerId == accountManager.getAccountId()) { + secretKey = accountManager.getSecretKey() + } + if (secretKey.isEmpty()) return StringUtils.EMPTY + return Base64.encodeBase64String(AES.GCM.encrypt(secretKey, iv, data.toByteArray())) } protected fun decryptData(id: String, data: String): String { diff --git a/src/main/kotlin/app/termora/highlight/KeywordHighlightDialog.kt b/src/main/kotlin/app/termora/highlight/KeywordHighlightDialog.kt index f50fdcf..85d6768 100644 --- a/src/main/kotlin/app/termora/highlight/KeywordHighlightDialog.kt +++ b/src/main/kotlin/app/termora/highlight/KeywordHighlightDialog.kt @@ -50,7 +50,7 @@ class KeywordHighlightDialog(owner: Window) : DialogWrapper(owner) { ).apply { Disposer.register(disposable, this) } ) - if (accountManager.isSigned()) { + if (accountManager.hasTeamFeature()) { for (team in accountManager.getTeams()) { tabbed.addTab( team.name, diff --git a/src/main/kotlin/app/termora/keymgr/KeyManagerDialog.kt b/src/main/kotlin/app/termora/keymgr/KeyManagerDialog.kt index d550f30..18e8561 100644 --- a/src/main/kotlin/app/termora/keymgr/KeyManagerDialog.kt +++ b/src/main/kotlin/app/termora/keymgr/KeyManagerDialog.kt @@ -63,7 +63,7 @@ class KeyManagerDialog( KeyManagerPanel(AccountOwner(accountManager.getAccountId(), accountManager.getEmail(), OwnerType.User)) ) - if (accountManager.isSigned()) { + if (accountManager.hasTeamFeature()) { for (team in accountManager.getTeams()) { tabbed.addTab( team.name, diff --git a/src/main/kotlin/app/termora/tag/TagDialog.kt b/src/main/kotlin/app/termora/tag/TagDialog.kt index 8b41cf7..c4db73a 100644 --- a/src/main/kotlin/app/termora/tag/TagDialog.kt +++ b/src/main/kotlin/app/termora/tag/TagDialog.kt @@ -51,7 +51,7 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils. ).apply { Disposer.register(disposable, this) } ) - if (accountManager.isSigned()) { + if (accountManager.hasTeamFeature()) { for (team in accountManager.getTeams()) { tabbed.addTab( team.name,