mirror of
https://github.com/TermoraDev/termora.git
synced 2026-03-31 21:32:20 +08:00
feat: Add guest mode support and permission controls
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
package app.termora
|
package app.termora
|
||||||
|
|
||||||
import app.termora.account.AccountOwner
|
import app.termora.account.AccountOwner
|
||||||
|
import app.termora.account.TeamRole
|
||||||
import app.termora.actions.AnAction
|
import app.termora.actions.AnAction
|
||||||
import app.termora.actions.AnActionEvent
|
import app.termora.actions.AnActionEvent
|
||||||
|
import app.termora.database.OwnerType
|
||||||
import app.termora.protocol.*
|
import app.termora.protocol.*
|
||||||
import app.termora.transfer.ScaleIcon
|
import app.termora.transfer.ScaleIcon
|
||||||
import com.formdev.flatlaf.extras.components.FlatToolBar
|
import com.formdev.flatlaf.extras.components.FlatToolBar
|
||||||
@@ -13,9 +15,11 @@ import kotlinx.coroutines.swing.Swing
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||||
|
import org.jdesktop.swingx.SwingXUtilities
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
import java.awt.CardLayout
|
import java.awt.CardLayout
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
|
import java.awt.Graphics
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
|
|
||||||
@@ -144,10 +148,33 @@ class NewHostDialogV2(
|
|||||||
val provider = extension.getProtocolProvider()
|
val provider = extension.getProtocolProvider()
|
||||||
testConnectionBtn.isVisible = provider is ProtocolTester
|
testConnectionBtn.isVisible = provider is ProtocolTester
|
||||||
|
|
||||||
|
preventImportantData()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun preventImportantData() {
|
||||||
|
if (visitorMode()) {
|
||||||
|
for (component in SwingUtils.getDescendantsOfType(JComponent::class.java, cardPanel)) {
|
||||||
|
if (component is OutlinePasswordField) {
|
||||||
|
component.styleMap = component.styleMap.toMutableMap().apply {
|
||||||
|
put("showRevealButton", false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitorMode(): Boolean {
|
||||||
|
return accountOwner.isVisitorMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createActions(): List<AbstractAction> {
|
override fun createActions(): List<AbstractAction> {
|
||||||
return listOf(createOkAction(), testConnectionAction, CancelAction())
|
val actions = mutableListOf<AbstractAction>()
|
||||||
|
if (visitorMode().not()) {
|
||||||
|
actions.add(createOkAction())
|
||||||
|
actions.add(testConnectionAction)
|
||||||
|
}
|
||||||
|
actions.add(CancelAction())
|
||||||
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createJButtonForAction(action: Action): JButton {
|
override fun createJButtonForAction(action: Action): JButton {
|
||||||
@@ -238,5 +265,4 @@ class NewHostDialogV2(
|
|||||||
super.doOKAction()
|
super.doOKAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,8 @@ object AccountHttp {
|
|||||||
throw ResponseException(response.code, response)
|
throw ResponseException(response.code, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
val text = response.use { response.body.use { it?.string() } }
|
val text = response.use { response.body.use { it.string() } }
|
||||||
if (text.isNullOrBlank()) {
|
if (text.isBlank()) {
|
||||||
throw ResponseException(response.code, "response body is empty", response)
|
throw ResponseException(response.code, "response body is empty", response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,24 +54,24 @@ class AccountManager private constructor() : ApplicationRunnerExtension {
|
|||||||
fun getOwnerIds() = account.teams.map { it.id }.toMutableList().apply { add(getAccountId()) }.toSet()
|
fun getOwnerIds() = account.teams.map { it.id }.toMutableList().apply { add(getAccountId()) }.toSet()
|
||||||
fun getOwners(): Set<AccountOwner> {
|
fun getOwners(): Set<AccountOwner> {
|
||||||
val owners = mutableSetOf<AccountOwner>()
|
val owners = mutableSetOf<AccountOwner>()
|
||||||
owners.add(AccountOwner(getAccountId(), getEmail(), OwnerType.User))
|
owners.add(AccountOwner(getAccountId(), getEmail(), OwnerType.User, StringUtils.EMPTY))
|
||||||
for (team in getTeams()) {
|
for (team in getTeams()) {
|
||||||
owners.add(AccountOwner(team.id, team.name, OwnerType.Team))
|
owners.add(AccountOwner(team.id, team.name, OwnerType.Team, team.role))
|
||||||
}
|
}
|
||||||
return owners
|
return owners
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFreePlan(): Boolean {
|
fun isFreePlan(): Boolean {
|
||||||
return isLocally() || getSubscription().plan == SubscriptionPlan.Free
|
return isLocally() || getSubscription().plan == SubscriptionPlan.Free.name
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSubscription(): Subscription {
|
fun getSubscription(): Subscription {
|
||||||
|
|
||||||
if (isLocally().not()) {
|
if (isLocally().not()) {
|
||||||
val subscriptions = getSubscriptions()
|
val subscriptions = getSubscriptions()
|
||||||
val enterprises = getSubscriptions().filter { it.plan == SubscriptionPlan.Enterprise }
|
val enterprises = getSubscriptions().filter { it.plan == SubscriptionPlan.Enterprise.name }
|
||||||
val teams = subscriptions.filter { it.plan == SubscriptionPlan.Team }
|
val teams = subscriptions.filter { it.plan == SubscriptionPlan.Team.name }
|
||||||
val pros = subscriptions.filter { it.plan == SubscriptionPlan.Pro }
|
val pros = subscriptions.filter { it.plan == SubscriptionPlan.Pro.name }
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
|
||||||
if (enterprises.any { it.endAt > now }) {
|
if (enterprises.any { it.endAt > now }) {
|
||||||
@@ -83,16 +83,9 @@ class AccountManager private constructor() : ApplicationRunnerExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Subscription(id = "0", plan = SubscriptionPlan.Free, startAt = 0, endAt = 0)
|
return Subscription(id = "0", plan = SubscriptionPlan.Free.name, startAt = 0, endAt = 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasTeamFeature(): Boolean {
|
|
||||||
if (accountProperties.signed.not()) return false
|
|
||||||
val plan = getSubscription().plan
|
|
||||||
return SubscriptionPlan.Team == plan || SubscriptionPlan.Enterprise == plan
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新 Token
|
* 刷新 Token
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class AccountOption : JPanel(BorderLayout()), OptionsPane.Option, Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val planBox = Box.createHorizontalBox()
|
val planBox = Box.createHorizontalBox()
|
||||||
planBox.add(JLabel(if (isLocally) "-" else subscription.plan.name))
|
planBox.add(JLabel(if (isLocally) "-" else subscription.plan))
|
||||||
if (isFreePlan && isLocally.not()) {
|
if (isFreePlan && isLocally.not()) {
|
||||||
planBox.add(Box.createHorizontalStrut(16))
|
planBox.add(Box.createHorizontalStrut(16))
|
||||||
val upgrade = JXHyperlink(object : AnAction(I18n.getString("termora.settings.account.upgrade")) {
|
val upgrade = JXHyperlink(object : AnAction(I18n.getString("termora.settings.account.upgrade")) {
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
package app.termora.account
|
package app.termora.account
|
||||||
|
|
||||||
import app.termora.database.OwnerType
|
import app.termora.database.OwnerType
|
||||||
|
import org.apache.commons.lang3.StringUtils
|
||||||
|
|
||||||
data class AccountOwner(val id: String, val name: String, val type: OwnerType)
|
data class AccountOwner(val id: String, val name: String, val type: OwnerType, val role: String) {
|
||||||
|
constructor(id: String, name: String, type: OwnerType) : this(id, name, type, StringUtils.EMPTY)
|
||||||
|
|
||||||
|
fun isVisitorMode(): Boolean {
|
||||||
|
return type == OwnerType.Team && role == TeamRole.Visitor.name
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -159,5 +159,5 @@ class ServerManager private constructor() {
|
|||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MeTeam(val id: String, val name: String, val role: TeamRole, val secretKey: String)
|
data class MeTeam(val id: String, val name: String, val role: String, val secretKey: String)
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class Subscription(
|
data class Subscription(
|
||||||
val id: String,
|
val id: String,
|
||||||
val plan: SubscriptionPlan,
|
val plan: String,
|
||||||
val startAt: Long,
|
val startAt: Long,
|
||||||
val endAt: Long,
|
val endAt: Long,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Team(
|
|||||||
/**
|
/**
|
||||||
* 所属角色
|
* 所属角色
|
||||||
*/
|
*/
|
||||||
val role: TeamRole,
|
val role: String,
|
||||||
) {
|
) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ package app.termora.account
|
|||||||
enum class TeamRole {
|
enum class TeamRole {
|
||||||
Member,
|
Member,
|
||||||
Owner,
|
Owner,
|
||||||
|
Visitor,
|
||||||
}
|
}
|
||||||
@@ -409,7 +409,8 @@ class DatabaseManager private constructor() : Disposable {
|
|||||||
val accountOwner = AccountOwner(
|
val accountOwner = AccountOwner(
|
||||||
id = account.id,
|
id = account.id,
|
||||||
name = account.email,
|
name = account.email,
|
||||||
type = OwnerType.User
|
type = OwnerType.User,
|
||||||
|
role = StringUtils.EMPTY,
|
||||||
)
|
)
|
||||||
|
|
||||||
for (host in hostManager.hosts()) {
|
for (host in hostManager.hosts()) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import app.termora.account.AccountManager
|
|||||||
import app.termora.account.AccountOwner
|
import app.termora.account.AccountOwner
|
||||||
import app.termora.database.OwnerType
|
import app.termora.database.OwnerType
|
||||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||||
|
import org.apache.commons.lang3.StringUtils
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
import javax.swing.BorderFactory
|
import javax.swing.BorderFactory
|
||||||
@@ -45,12 +46,13 @@ class KeywordHighlightDialog(owner: Window) : DialogWrapper(owner) {
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
accountManager.getAccountId(),
|
accountManager.getAccountId(),
|
||||||
accountManager.getEmail(),
|
accountManager.getEmail(),
|
||||||
OwnerType.User
|
OwnerType.User,
|
||||||
|
StringUtils.EMPTY,
|
||||||
)
|
)
|
||||||
).apply { Disposer.register(disposable, this) }
|
).apply { Disposer.register(disposable, this) }
|
||||||
)
|
)
|
||||||
|
|
||||||
if (accountManager.hasTeamFeature()) {
|
// if (accountManager.hasTeamFeature()) {
|
||||||
for (team in accountManager.getTeams()) {
|
for (team in accountManager.getTeams()) {
|
||||||
tabbed.addTab(
|
tabbed.addTab(
|
||||||
team.name,
|
team.name,
|
||||||
@@ -59,11 +61,12 @@ class KeywordHighlightDialog(owner: Window) : DialogWrapper(owner) {
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
team.id,
|
team.id,
|
||||||
team.name,
|
team.name,
|
||||||
OwnerType.Team
|
OwnerType.Team,
|
||||||
|
team.role,
|
||||||
)
|
)
|
||||||
).apply { Disposer.register(disposable, this) })
|
).apply { Disposer.register(disposable, this) })
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
return tabbed
|
return tabbed
|
||||||
|
|||||||
@@ -248,6 +248,9 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
|||||||
|
|
||||||
table.addMouseListener(object : MouseAdapter() {
|
table.addMouseListener(object : MouseAdapter() {
|
||||||
override fun mouseClicked(e: MouseEvent) {
|
override fun mouseClicked(e: MouseEvent) {
|
||||||
|
if (accountOwner.isVisitorMode()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (SwingUtilities.isLeftMouseButton(e)) {
|
if (SwingUtilities.isLeftMouseButton(e)) {
|
||||||
val row = table.rowAtPoint(e.point)
|
val row = table.rowAtPoint(e.point)
|
||||||
val column = table.columnAtPoint(e.point)
|
val column = table.columnAtPoint(e.point)
|
||||||
@@ -299,7 +302,8 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
|||||||
|
|
||||||
if (keywordHighlight.backgroundColor in 0..16) {
|
if (keywordHighlight.backgroundColor in 0..16) {
|
||||||
if (keywordHighlight.backgroundColor == 0) {
|
if (keywordHighlight.backgroundColor == 0) {
|
||||||
dialog.backgroundColor.background = Color(colorPalette.getColor(TerminalColor.Basic.BACKGROUND))
|
dialog.backgroundColor.background =
|
||||||
|
Color(colorPalette.getColor(TerminalColor.Basic.BACKGROUND))
|
||||||
dialog.backgroundColor.colorIndex = -1
|
dialog.backgroundColor.colorIndex = -1
|
||||||
} else {
|
} else {
|
||||||
dialog.backgroundColor.color =
|
dialog.backgroundColor.color =
|
||||||
@@ -402,7 +406,7 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
|||||||
val panel = JPanel(BorderLayout())
|
val panel = JPanel(BorderLayout())
|
||||||
panel.add(JScrollPane(table).apply {
|
panel.add(JScrollPane(table).apply {
|
||||||
border = BorderFactory.createCompoundBorder(
|
border = BorderFactory.createCompoundBorder(
|
||||||
BorderFactory.createEmptyBorder(8, 8, 8, 0),
|
BorderFactory.createEmptyBorder(8, 8, 8, if (accountOwner.isVisitorMode()) 8 else 0),
|
||||||
BorderFactory.createMatteBorder(1, 1, 1, 1, DynamicColor.BorderColor)
|
BorderFactory.createMatteBorder(1, 1, 1, 1, DynamicColor.BorderColor)
|
||||||
)
|
)
|
||||||
}, BorderLayout.CENTER)
|
}, BorderLayout.CENTER)
|
||||||
@@ -414,6 +418,7 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
|||||||
"default:grow",
|
"default:grow",
|
||||||
"pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref"
|
"pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref"
|
||||||
)
|
)
|
||||||
|
if (accountOwner.isVisitorMode().not()) {
|
||||||
panel.add(
|
panel.add(
|
||||||
FormBuilder.create().layout(layout)
|
FormBuilder.create().layout(layout)
|
||||||
.border(BorderFactory.createEmptyBorder(8, 8, 8, 8))
|
.border(BorderFactory.createEmptyBorder(8, 8, 8, 8))
|
||||||
@@ -424,7 +429,7 @@ class KeywordHighlightPanel(private val accountOwner: AccountOwner) : JPanel(Bor
|
|||||||
.add(exportBtn).xy(1, rows).apply { rows += step }
|
.add(exportBtn).xy(1, rows).apply { rows += step }
|
||||||
.build(),
|
.build(),
|
||||||
BorderLayout.EAST)
|
BorderLayout.EAST)
|
||||||
|
}
|
||||||
return panel
|
return panel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import app.termora.account.AccountManager
|
|||||||
import app.termora.account.AccountOwner
|
import app.termora.account.AccountOwner
|
||||||
import app.termora.database.OwnerType
|
import app.termora.database.OwnerType
|
||||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||||
|
import org.apache.commons.lang3.StringUtils
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
import javax.swing.BorderFactory
|
import javax.swing.BorderFactory
|
||||||
@@ -65,13 +66,14 @@ class KeyManagerDialog(
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
accountManager.getAccountId(),
|
accountManager.getAccountId(),
|
||||||
accountManager.getEmail(),
|
accountManager.getEmail(),
|
||||||
OwnerType.User
|
OwnerType.User,
|
||||||
|
StringUtils.EMPTY,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accountOwner != null && accountManager.hasTeamFeature()) {
|
if (accountOwner != null) {
|
||||||
for (team in accountManager.getTeams()) {
|
for (team in accountManager.getTeams()) {
|
||||||
if (team.id == accountOwner.id) {
|
if (team.id == accountOwner.id) {
|
||||||
tabbed.addTab(
|
tabbed.addTab(
|
||||||
@@ -81,7 +83,8 @@ class KeyManagerDialog(
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
team.id,
|
team.id,
|
||||||
team.name,
|
team.name,
|
||||||
OwnerType.Team
|
OwnerType.Team,
|
||||||
|
team.role,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -91,8 +94,7 @@ class KeyManagerDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if (accountManager.hasTeamFeature()) {
|
||||||
if (accountManager.hasTeamFeature()) {
|
|
||||||
for (team in accountManager.getTeams()) {
|
for (team in accountManager.getTeams()) {
|
||||||
tabbed.addTab(
|
tabbed.addTab(
|
||||||
team.name,
|
team.name,
|
||||||
@@ -101,12 +103,13 @@ class KeyManagerDialog(
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
team.id,
|
team.id,
|
||||||
team.name,
|
team.name,
|
||||||
OwnerType.Team
|
OwnerType.Team,
|
||||||
|
team.role,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
return tabbed
|
return tabbed
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package app.termora.keymgr
|
|||||||
|
|
||||||
import app.termora.*
|
import app.termora.*
|
||||||
import app.termora.account.AccountOwner
|
import app.termora.account.AccountOwner
|
||||||
|
import app.termora.account.TeamRole
|
||||||
import app.termora.actions.AnAction
|
import app.termora.actions.AnAction
|
||||||
import app.termora.actions.AnActionEvent
|
import app.termora.actions.AnActionEvent
|
||||||
|
import app.termora.database.OwnerType
|
||||||
import app.termora.plugin.internal.ssh.SSHProtocolProvider
|
import app.termora.plugin.internal.ssh.SSHProtocolProvider
|
||||||
import app.termora.tree.Filter
|
import app.termora.tree.Filter
|
||||||
import app.termora.tree.HostTreeNode
|
import app.termora.tree.HostTreeNode
|
||||||
@@ -56,6 +58,7 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
|||||||
init {
|
init {
|
||||||
initView()
|
initView()
|
||||||
initEvents()
|
initEvents()
|
||||||
|
preventImportantData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -89,6 +92,8 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
|||||||
add(JScrollPane(keyPairTable).apply {
|
add(JScrollPane(keyPairTable).apply {
|
||||||
border = BorderFactory.createMatteBorder(1, 1, 1, 1, DynamicColor.BorderColor)
|
border = BorderFactory.createMatteBorder(1, 1, 1, 1, DynamicColor.BorderColor)
|
||||||
}, BorderLayout.CENTER)
|
}, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
if (accountOwner.type == OwnerType.User || (accountOwner.type == OwnerType.Team && accountOwner.role != TeamRole.Visitor.name)) {
|
||||||
add(
|
add(
|
||||||
FormBuilder.create().layout(layout).padding(EmptyBorder(0, 12, 0, 0))
|
FormBuilder.create().layout(layout).padding(EmptyBorder(0, 12, 0, 0))
|
||||||
.add(generateBtn).xy(1, rows).apply { rows += step }
|
.add(generateBtn).xy(1, rows).apply { rows += step }
|
||||||
@@ -98,6 +103,8 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
|||||||
.add(deleteBtn).xy(1, rows).apply { rows += step }
|
.add(deleteBtn).xy(1, rows).apply { rows += step }
|
||||||
.add(sshCopyIdBtn).xy(1, rows).apply { rows += step }
|
.add(sshCopyIdBtn).xy(1, rows).apply { rows += step }
|
||||||
.build(), BorderLayout.EAST)
|
.build(), BorderLayout.EAST)
|
||||||
|
}
|
||||||
|
|
||||||
border = BorderFactory.createEmptyBorder(12, 12, 12, 12)
|
border = BorderFactory.createEmptyBorder(12, 12, 12, 12)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -199,6 +206,17 @@ class KeyManagerPanel(private val accountOwner: AccountOwner) : JPanel(BorderLay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun preventImportantData() {
|
||||||
|
if (accountOwner.isVisitorMode()) {
|
||||||
|
generateBtn.isVisible = false
|
||||||
|
editBtn.isVisible = false
|
||||||
|
deleteBtn.isVisible = false
|
||||||
|
importBtn.isVisible = false
|
||||||
|
exportBtn.isVisible = false
|
||||||
|
sshCopyIdBtn.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun sshCopyId(evt: AnActionEvent) {
|
private fun sshCopyId(evt: AnActionEvent) {
|
||||||
val keyPairs = keyPairTable.selectedRows.map { keyPairTableModel.getOhKeyPair(it) }
|
val keyPairs = keyPairTable.selectedRows.map { keyPairTableModel.getOhKeyPair(it) }
|
||||||
val publicKeys = mutableListOf<Pair<String, String>>()
|
val publicKeys = mutableListOf<Pair<String, String>>()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package app.termora.plugin.internal.rdp
|
package app.termora.plugin.internal.rdp
|
||||||
|
|
||||||
import app.termora.*
|
import app.termora.*
|
||||||
|
import app.termora.account.AccountOwner
|
||||||
import app.termora.plugin.internal.BasicProxyOption
|
import app.termora.plugin.internal.BasicProxyOption
|
||||||
import com.formdev.flatlaf.FlatClientProperties
|
import com.formdev.flatlaf.FlatClientProperties
|
||||||
import com.formdev.flatlaf.extras.components.FlatComboBox
|
import com.formdev.flatlaf.extras.components.FlatComboBox
|
||||||
@@ -17,7 +18,7 @@ import java.awt.event.ComponentEvent
|
|||||||
import java.awt.event.ItemEvent
|
import java.awt.event.ItemEvent
|
||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
|
|
||||||
internal open class RDPHostOptionsPane : OptionsPane() {
|
internal open class RDPHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPane() {
|
||||||
protected val generalOption = GeneralOption()
|
protected val generalOption = GeneralOption()
|
||||||
protected val proxyOption = BasicProxyOption()
|
protected val proxyOption = BasicProxyOption()
|
||||||
protected val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
protected val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package app.termora.plugin.internal.rdp
|
|||||||
|
|
||||||
import app.termora.Disposer
|
import app.termora.Disposer
|
||||||
import app.termora.Host
|
import app.termora.Host
|
||||||
|
import app.termora.account.AccountOwner
|
||||||
import app.termora.protocol.ProtocolHostPanel
|
import app.termora.protocol.ProtocolHostPanel
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
|
|
||||||
class RDPProtocolHostPanel : ProtocolHostPanel() {
|
class RDPProtocolHostPanel(private val accountOwner: AccountOwner) : ProtocolHostPanel() {
|
||||||
private val pane = RDPHostOptionsPane()
|
private val pane = RDPHostOptionsPane(accountOwner)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initView()
|
initView()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ internal class RDPProtocolHostPanelExtension private constructor() : ProtocolHos
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createProtocolHostPanel(accountOwner: AccountOwner): ProtocolHostPanel {
|
override fun createProtocolHostPanel(accountOwner: AccountOwner): ProtocolHostPanel {
|
||||||
return RDPProtocolHostPanel()
|
return RDPProtocolHostPanel(accountOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ordered(): Long {
|
override fun ordered(): Long {
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils.
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
accountManager.getAccountId(),
|
accountManager.getAccountId(),
|
||||||
accountManager.getEmail(),
|
accountManager.getEmail(),
|
||||||
OwnerType.User
|
OwnerType.User,
|
||||||
|
StringUtils.EMPTY,
|
||||||
)
|
)
|
||||||
).apply { Disposer.register(disposable, this) }
|
).apply { Disposer.register(disposable, this) }
|
||||||
)
|
)
|
||||||
|
|
||||||
if (accountManager.hasTeamFeature()) {
|
|
||||||
for (team in accountManager.getTeams()) {
|
for (team in accountManager.getTeams()) {
|
||||||
tabbed.addTab(
|
tabbed.addTab(
|
||||||
team.name,
|
team.name,
|
||||||
@@ -60,7 +60,8 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils.
|
|||||||
AccountOwner(
|
AccountOwner(
|
||||||
team.id,
|
team.id,
|
||||||
team.name,
|
team.name,
|
||||||
OwnerType.Team
|
OwnerType.Team,
|
||||||
|
team.role,
|
||||||
)
|
)
|
||||||
).apply { Disposer.register(disposable, this) })
|
).apply { Disposer.register(disposable, this) })
|
||||||
|
|
||||||
@@ -68,7 +69,6 @@ class TagDialog(owner: Window, private val accountOwnerId: String = StringUtils.
|
|||||||
tabbed.selectedIndex = tabbed.tabCount - 1
|
tabbed.selectedIndex = tabbed.tabCount - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return tabbed
|
return tabbed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package app.termora.tag
|
|||||||
|
|
||||||
import app.termora.*
|
import app.termora.*
|
||||||
import app.termora.account.AccountOwner
|
import app.termora.account.AccountOwner
|
||||||
|
import app.termora.account.TeamRole
|
||||||
|
import app.termora.database.OwnerType
|
||||||
import com.jgoodies.forms.builder.FormBuilder
|
import com.jgoodies.forms.builder.FormBuilder
|
||||||
import com.jgoodies.forms.layout.FormLayout
|
import com.jgoodies.forms.layout.FormLayout
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
@@ -9,7 +11,7 @@ import java.awt.Component
|
|||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
import javax.swing.border.EmptyBorder
|
import javax.swing.border.EmptyBorder
|
||||||
|
|
||||||
class TagPanel(accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable {
|
class TagPanel(private val accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable {
|
||||||
|
|
||||||
private val owner get() = SwingUtilities.getWindowAncestor(this)
|
private val owner get() = SwingUtilities.getWindowAncestor(this)
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ class TagPanel(accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable
|
|||||||
init {
|
init {
|
||||||
initView()
|
initView()
|
||||||
initEvents()
|
initEvents()
|
||||||
|
preventImportantData()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
@@ -108,6 +111,14 @@ class TagPanel(accountOwner: AccountOwner) : JPanel(BorderLayout()), Disposable
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun preventImportantData() {
|
||||||
|
if (accountOwner.isVisitorMode()) {
|
||||||
|
addBtn.isVisible = false
|
||||||
|
editBtn.isVisible = false
|
||||||
|
deleteBtn.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createCenterPanel(): JComponent {
|
private fun createCenterPanel(): JComponent {
|
||||||
|
|
||||||
val panel = JPanel(BorderLayout())
|
val panel = JPanel(BorderLayout())
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package app.termora.tree
|
|||||||
import app.termora.*
|
import app.termora.*
|
||||||
import app.termora.Application.ohMyJson
|
import app.termora.Application.ohMyJson
|
||||||
import app.termora.account.AccountManager
|
import app.termora.account.AccountManager
|
||||||
|
import app.termora.account.Team
|
||||||
|
import app.termora.account.TeamRole
|
||||||
import app.termora.actions.AnAction
|
import app.termora.actions.AnAction
|
||||||
import app.termora.actions.AnActionEvent
|
import app.termora.actions.AnActionEvent
|
||||||
import app.termora.actions.OpenHostAction
|
import app.termora.actions.OpenHostAction
|
||||||
@@ -455,6 +457,33 @@ class NewHostTree : SimpleTree(), Disposable {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
popupMenu.addPopupMenuListener(object : PopupMenuListener {
|
||||||
|
|
||||||
|
override fun popupMenuWillBecomeVisible(e: PopupMenuEvent?) {
|
||||||
|
for (node in nodes) {
|
||||||
|
val team = TeamTreeNode.parentTeam(node) ?: continue
|
||||||
|
if (team.role == TeamRole.Visitor.name) {
|
||||||
|
copy.isEnabled = false
|
||||||
|
remove.isEnabled = false
|
||||||
|
rename.isEnabled = false
|
||||||
|
importMenu.isEnabled = false
|
||||||
|
newMenu.isEnabled = false
|
||||||
|
tagsMenu.isEnabled = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popupMenuWillBecomeInvisible(e: PopupMenuEvent?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popupMenuCanceled(e: PopupMenuEvent?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
val mnemonics = mapOf(
|
val mnemonics = mapOf(
|
||||||
refresh to KeyEvent.VK_R,
|
refresh to KeyEvent.VK_R,
|
||||||
newMenu to KeyEvent.VK_W,
|
newMenu to KeyEvent.VK_W,
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ class NewHostTreeModel private constructor() : SimpleTreeModel<Host>(
|
|||||||
|
|
||||||
// 如果是根,需要引入团队功能
|
// 如果是根,需要引入团队功能
|
||||||
if (parent == getRoot()) {
|
if (parent == getRoot()) {
|
||||||
if (accountManager.hasTeamFeature()) {
|
// if (accountManager.hasTeamFeature()) {
|
||||||
for (team in accountManager.getTeams()) {
|
for (team in accountManager.getTeams()) {
|
||||||
nodes[team.id] = TeamTreeNode(team)
|
nodes[team.id] = TeamTreeNode(team)
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
|
|
||||||
nodes[accountManager.getAccountId()] = HostTreeNode(
|
nodes[accountManager.getAccountId()] = HostTreeNode(
|
||||||
Host(
|
Host(
|
||||||
@@ -93,11 +93,11 @@ class NewHostTreeModel private constructor() : SimpleTreeModel<Host>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parent == getRoot()) {
|
if (parent == getRoot()) {
|
||||||
if (accountManager.hasTeamFeature()) {
|
// if (accountManager.hasTeamFeature()) {
|
||||||
for (team in accountManager.getTeams()) {
|
for (team in accountManager.getTeams()) {
|
||||||
parent.add(nodes.getValue(team.id))
|
parent.add(nodes.getValue(team.id))
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
parent.add(nodes.getValue(accountManager.getAccountId()))
|
parent.add(nodes.getValue(accountManager.getAccountId()))
|
||||||
} else {
|
} else {
|
||||||
for (node in nodes.values) {
|
for (node in nodes.values) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package app.termora.tree
|
package app.termora.tree
|
||||||
|
|
||||||
import app.termora.OutlineTextField
|
import app.termora.OutlineTextField
|
||||||
|
import app.termora.account.TeamRole
|
||||||
import com.formdev.flatlaf.ui.FlatTreeUI
|
import com.formdev.flatlaf.ui.FlatTreeUI
|
||||||
import org.jdesktop.swingx.JXTree
|
import org.jdesktop.swingx.JXTree
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
@@ -134,6 +135,13 @@ open class SimpleTree : JXTree() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (node in nodes) {
|
||||||
|
val team = TeamTreeNode.parentTeam(node) ?: continue
|
||||||
|
if (team.role == TeamRole.Visitor.name) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MoveNodeTransferable(nodes)
|
return MoveNodeTransferable(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,9 +161,14 @@ open class SimpleTree : JXTree() {
|
|||||||
if (nodes.isEmpty()) return false
|
if (nodes.isEmpty()) return false
|
||||||
if (!node.isFolder) return false
|
if (!node.isFolder) return false
|
||||||
|
|
||||||
|
val team = TeamTreeNode.parentTeam(node)
|
||||||
|
if (team?.role == TeamRole.Visitor.name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for (e in nodes) {
|
for (e in nodes) {
|
||||||
// 禁止拖拽到自己的子下面
|
// 禁止拖拽到自己的子下面
|
||||||
if (path.equals(TreePath(e.path)) || TreePath(e.path).isDescendant(path)) {
|
if (path == TreePath(e.path) || TreePath(e.path).isDescendant(path)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +346,7 @@ open class SimpleTree : JXTree() {
|
|||||||
|
|
||||||
private inner class MyTreeUI : FlatTreeUI() {
|
private inner class MyTreeUI : FlatTreeUI() {
|
||||||
|
|
||||||
override fun createNodeDimensions(): AbstractLayoutCache.NodeDimensions? {
|
override fun createNodeDimensions(): AbstractLayoutCache.NodeDimensions {
|
||||||
return object : NodeDimensionsHandler() {
|
return object : NodeDimensionsHandler() {
|
||||||
override fun getNodeDimensions(
|
override fun getNodeDimensions(
|
||||||
value: Any?, row: Int, depth: Int, expanded: Boolean,
|
value: Any?, row: Int, depth: Int, expanded: Boolean,
|
||||||
|
|||||||
@@ -26,4 +26,16 @@ class TeamTreeNode(val team: Team) : HostTreeNode(
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return team.name
|
return team.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun parentTeam(node: SimpleTreeNode<*>?): Team? {
|
||||||
|
if (node is TeamTreeNode) {
|
||||||
|
return node.team
|
||||||
|
} else if (node == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return parentTeam(node.parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user