Skip to content

Commit 8101250

Browse files
committed
Simplify CLI secret registration flow
1 parent 376c6d5 commit 8101250

1 file changed

Lines changed: 51 additions & 32 deletions

File tree

Sources/App/Views/EditorViews.swift

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ struct RegisterCLIView: View {
6969
TextField("CLI name", text: $name, prompt: Text("hcloud"))
7070
.accessibilityLabel("CLI name")
7171
HStack(alignment: .firstTextBaseline, spacing: 8) {
72-
TextField("Executable path", text: $targetPath, prompt: Text("/opt/homebrew/bin/hcloud"))
72+
TextField("Executable path", text: $targetPath)
7373
.accessibilityLabel("Executable path")
7474
Button {
7575
chooseExecutable()
@@ -90,27 +90,36 @@ struct RegisterCLIView: View {
9090
Text("Use the resolved executable path for the CLI you want Agentic Secrets to verify before delivery.")
9191
.foregroundStyle(.secondary)
9292
}
93-
case .bindings:
94-
Section("Environment bindings") {
95-
ForEach($bindings) { $binding in
96-
HStack {
97-
TextField("ENV_NAME", text: $binding.environmentName)
98-
.accessibilityLabel("Environment variable name")
99-
Button {
100-
bindings.removeAll { $0.id == binding.id }
101-
if bindings.isEmpty { bindings.append(SecretDraft()) }
102-
} label: {
103-
Image(systemName: "minus.circle")
104-
}
105-
.buttonStyle(.borderless)
106-
.help("Remove binding")
107-
.accessibilityLabel("Remove environment binding")
93+
case .secrets:
94+
Section("Environment secrets") {
95+
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 8) {
96+
GridRow {
97+
Text("ENV_NAME")
98+
.font(.caption.weight(.semibold))
99+
.foregroundStyle(.secondary)
100+
Text("Value")
101+
.font(.caption.weight(.semibold))
102+
.foregroundStyle(.secondary)
103+
Text("")
104+
.accessibilityHidden(true)
105+
}
106+
Divider()
107+
.gridCellColumns(3)
108+
ForEach($bindings) { $binding in
109+
RegisterCLISecretRow(
110+
binding: $binding,
111+
canRemove: bindings.count > 1,
112+
remove: {
113+
bindings.removeAll { $0.id == binding.id }
114+
if bindings.isEmpty { bindings.append(SecretDraft()) }
115+
}
116+
)
108117
}
109118
}
110119
Button {
111120
bindings.append(SecretDraft())
112121
} label: {
113-
Label("Add Environment Binding", systemImage: "plus")
122+
Label("Add Environment Secret", systemImage: "plus")
114123
}
115124
if RegisterCLIFormValidation.hasDuplicateEnvironmentNames(bindings) {
116125
Text("Environment names must be unique.")
@@ -120,13 +129,6 @@ struct RegisterCLIView: View {
120129
Text("Use shell-style names such as HCLOUD_TOKEN: letters, numbers, and underscores; do not start with a number.")
121130
.foregroundStyle(.red)
122131
}
123-
}
124-
case .secrets:
125-
Section("Write-only secrets") {
126-
ForEach($bindings) { $binding in
127-
SecureField(binding.environmentName.isEmpty ? "Secret value" : binding.environmentName, text: $binding.secretValue)
128-
.accessibilityLabel("Secret value for \(binding.environmentName.isEmpty ? "environment binding" : binding.environmentName)")
129-
}
130132
if bindings.contains(where: { !$0.secretValue.isEmpty && !SecretInputValidation.hasNonWhitespace($0.secretValue) }) {
131133
Text("Secret values cannot be only whitespace.")
132134
.foregroundStyle(.red)
@@ -158,10 +160,6 @@ struct RegisterCLIView: View {
158160
!name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
159161
&& !targetPath.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
160162
&& RegisterCLIFormValidation.isValidExecutablePath(targetPath)
161-
case .bindings:
162-
bindings.contains { !$0.environmentName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
163-
&& !RegisterCLIFormValidation.hasDuplicateEnvironmentNames(bindings)
164-
&& RegisterCLIFormValidation.invalidEnvironmentNames(bindings).isEmpty
165163
case .secrets:
166164
bindings.allSatisfy {
167165
!$0.environmentName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
@@ -279,14 +277,12 @@ enum BitwardenBindingEditorDefaults {
279277

280278
private enum RegisterCLIStep: Int, CaseIterable {
281279
case target
282-
case bindings
283280
case secrets
284281
case review
285282

286283
var title: String {
287284
switch self {
288285
case .target: "Target"
289-
case .bindings: "Bindings"
290286
case .secrets: "Secrets"
291287
case .review: "Review"
292288
}
@@ -295,8 +291,7 @@ private enum RegisterCLIStep: Int, CaseIterable {
295291
var subtitle: String {
296292
switch self {
297293
case .target: "Choose the CLI executable to verify."
298-
case .bindings: "Name the environment variables Agentic Secrets may deliver."
299-
case .secrets: "Enter secret material once; it will not be shown again."
294+
case .secrets: "Add environment names and write-only values in one table."
300295
case .review: "Confirm the target and write-only bindings."
301296
}
302297
}
@@ -310,6 +305,30 @@ private enum RegisterCLIStep: Int, CaseIterable {
310305
}
311306
}
312307

308+
private struct RegisterCLISecretRow: View {
309+
@Binding var binding: SecretDraft
310+
var canRemove: Bool
311+
var remove: () -> Void
312+
313+
var body: some View {
314+
GridRow {
315+
TextField("HCLOUD_TOKEN", text: $binding.environmentName)
316+
.textFieldStyle(.roundedBorder)
317+
.accessibilityLabel("Environment variable name")
318+
SecureField("Secret value", text: $binding.secretValue)
319+
.textFieldStyle(.roundedBorder)
320+
.accessibilityLabel("Secret value for \(binding.environmentName.isEmpty ? "environment variable" : binding.environmentName)")
321+
Button(action: remove) {
322+
Image(systemName: "minus.circle")
323+
}
324+
.buttonStyle(.borderless)
325+
.disabled(!canRemove)
326+
.help(canRemove ? "Remove environment secret" : "At least one environment secret is required")
327+
.accessibilityLabel("Remove environment secret")
328+
}
329+
}
330+
}
331+
313332
private struct RegisterCLIStepHeader: View {
314333
var step: RegisterCLIStep
315334

0 commit comments

Comments
 (0)