Skip to content

Commit b26a1df

Browse files
committed
fix assigning keys (regression)
1 parent 1b538ef commit b26a1df

File tree

3 files changed

+71
-21
lines changed

3 files changed

+71
-21
lines changed

internal/db/mysql.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,25 @@ func (s *MySQLStore) HasSystemKeys() (bool, error) {
437437
return count > 0, nil
438438
}
439439
func (s *MySQLStore) AssignKeyToAccount(keyID, accountID int) error {
440-
_, err := s.db.Exec("INSERT INTO account_keys(key_id, account_id) VALUES(?, ?)", keyID, accountID)
440+
// First verify the key and account exist
441+
var keyExists, accountExists bool
442+
err := s.db.QueryRow("SELECT EXISTS(SELECT 1 FROM public_keys WHERE id = ?)", keyID).Scan(&keyExists)
443+
if err != nil {
444+
return fmt.Errorf("error checking key existence: %w", err)
445+
}
446+
if !keyExists {
447+
return fmt.Errorf("key ID %d does not exist in public_keys table", keyID)
448+
}
449+
450+
err = s.db.QueryRow("SELECT EXISTS(SELECT 1 FROM accounts WHERE id = ?)", accountID).Scan(&accountExists)
451+
if err != nil {
452+
return fmt.Errorf("error checking account existence: %w", err)
453+
}
454+
if !accountExists {
455+
return fmt.Errorf("account ID %d does not exist in accounts table", accountID)
456+
}
457+
458+
_, err = s.db.Exec("INSERT INTO account_keys(key_id, account_id) VALUES(?, ?)", keyID, accountID)
441459
if err == nil {
442460
// Get details for logging, ignoring errors as this is best-effort.
443461
var keyComment, accUser, accHost string

internal/tui/assign_keys.go

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ type assignKeysModel struct {
5252
}
5353

5454
// newAssignKeysModel creates a new model for the key assignment view, pre-loading accounts and keys.
55-
func newAssignKeysModel() assignKeysModel {
56-
m := assignKeysModel{
55+
func newAssignKeysModel() *assignKeysModel {
56+
m := &assignKeysModel{
5757
state: assignStateSelectAccount,
5858
assignedKeys: make(map[int]struct{}),
5959
}
@@ -74,12 +74,12 @@ func newAssignKeysModel() assignKeysModel {
7474
}
7575

7676
// Init initializes the model.
77-
func (m assignKeysModel) Init() tea.Cmd {
77+
func (m *assignKeysModel) Init() tea.Cmd {
7878
return nil
7979
}
8080

8181
// Update handles messages and updates the model's state.
82-
func (m assignKeysModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
82+
func (m *assignKeysModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
8383
switch m.state {
8484
case assignStateSelectAccount:
8585
return m.updateAccountSelection(msg)
@@ -90,7 +90,7 @@ func (m assignKeysModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
9090
}
9191

9292
// updateAccountSelection handles input when the user is selecting an account.
93-
func (m assignKeysModel) updateAccountSelection(msg tea.Msg) (tea.Model, tea.Cmd) {
93+
func (m *assignKeysModel) updateAccountSelection(msg tea.Msg) (tea.Model, tea.Cmd) {
9494
switch msg := msg.(type) {
9595
case tea.KeyMsg:
9696
// Filtering mode for accounts
@@ -141,6 +141,16 @@ func (m assignKeysModel) updateAccountSelection(msg tea.Msg) (tea.Model, tea.Cmd
141141
m.state = assignStateSelectKeys
142142
m.keyCursor = 0
143143
m.status = ""
144+
145+
// Refresh the key list to ensure we have the latest data
146+
keys, err := db.GetAllPublicKeys()
147+
if err != nil {
148+
m.err = fmt.Errorf("error refreshing key list: %v", err)
149+
return m, nil
150+
}
151+
m.keys = keys
152+
153+
// Get currently assigned keys
144154
assigned, err := db.GetKeysForAccount(m.selectedAccount.ID)
145155
if err != nil {
146156
m.err = err
@@ -150,14 +160,15 @@ func (m assignKeysModel) updateAccountSelection(msg tea.Msg) (tea.Model, tea.Cmd
150160
for _, key := range assigned {
151161
m.assignedKeys[key.ID] = struct{}{}
152162
}
163+
m.status = fmt.Sprintf("Selected account %s (ID: %d) with %d keys assigned", m.selectedAccount.String(), m.selectedAccount.ID, len(assigned))
153164
return m, nil
154165
}
155166
}
156167
return m, nil
157168
}
158169

159170
// filteredAccounts returns a slice of accounts that match the current filter text.
160-
func (m assignKeysModel) filteredAccounts() []model.Account {
171+
func (m *assignKeysModel) filteredAccounts() []model.Account {
161172
if m.accountFilter == "" {
162173
return m.accounts
163174
}
@@ -171,7 +182,7 @@ func (m assignKeysModel) filteredAccounts() []model.Account {
171182
}
172183

173184
// filteredKeys returns a slice of public keys that match the current filter text.
174-
func (m assignKeysModel) filteredKeys() []model.PublicKey {
185+
func (m *assignKeysModel) filteredKeys() []model.PublicKey {
175186
if m.keyFilter == "" {
176187
return m.keys
177188
}
@@ -193,7 +204,7 @@ func containsIgnoreCase(s, substr string) bool {
193204
}
194205

195206
// updateKeySelection handles input when the user is selecting keys to assign.
196-
func (m assignKeysModel) updateKeySelection(msg tea.Msg) (tea.Model, tea.Cmd) {
207+
func (m *assignKeysModel) updateKeySelection(msg tea.Msg) (tea.Model, tea.Cmd) {
197208
switch msg := msg.(type) {
198209
case tea.KeyMsg:
199210
// Filtering mode for keys
@@ -234,27 +245,44 @@ func (m assignKeysModel) updateKeySelection(msg tea.Msg) (tea.Model, tea.Cmd) {
234245
if m.keyCursor < len(m.filteredKeys())-1 {
235246
m.keyCursor++
236247
}
237-
case " ", "enter":
248+
case " ": // Only use space for toggling assignment
238249
filteredKeys := m.filteredKeys()
239250
if len(filteredKeys) == 0 || m.keyCursor >= len(filteredKeys) {
240251
return m, nil
241252
}
242253
selectedKey := filteredKeys[m.keyCursor]
243254
if _, assigned := m.assignedKeys[selectedKey.ID]; assigned {
244255
// Unassign
245-
if err := db.UnassignKeyFromAccount(m.selectedAccount.ID, selectedKey.ID); err != nil {
256+
m.status = fmt.Sprintf("Attempting to unassign key: %s (ID: %d) from account ID: %d", selectedKey.Comment, selectedKey.ID, m.selectedAccount.ID)
257+
if err := db.UnassignKeyFromAccount(selectedKey.ID, m.selectedAccount.ID); err != nil {
246258
m.err = err
259+
m.status = fmt.Sprintf("Error unassigning key: %v", err)
247260
} else {
248261
delete(m.assignedKeys, selectedKey.ID)
249262
m.status = fmt.Sprintf("Unassigned key: %s", selectedKey.Comment)
250263
}
251264
} else {
252265
// Assign
253-
if err := db.AssignKeyToAccount(m.selectedAccount.ID, selectedKey.ID); err != nil {
266+
m.status = fmt.Sprintf("Attempting to assign key: %s (ID: %d) to account ID: %d", selectedKey.Comment, selectedKey.ID, m.selectedAccount.ID)
267+
// Verify key still exists
268+
exists := false
269+
for _, k := range m.keys {
270+
if k.ID == selectedKey.ID {
271+
exists = true
272+
break
273+
}
274+
}
275+
if !exists {
276+
m.err = fmt.Errorf("key ID %d no longer exists in memory", selectedKey.ID)
277+
m.status = fmt.Sprintf("Error: key may have been deleted: %v", m.err)
278+
return m, nil
279+
}
280+
if err := db.AssignKeyToAccount(selectedKey.ID, m.selectedAccount.ID); err != nil {
254281
m.err = err
282+
m.status = fmt.Sprintf("Error assigning key: %v", err)
255283
} else {
256284
m.assignedKeys[selectedKey.ID] = struct{}{}
257-
m.status = fmt.Sprintf("Assigned key: %s", selectedKey.Comment)
285+
m.status = fmt.Sprintf("Assigned key: %s (ID: %d)", selectedKey.Comment, selectedKey.ID)
258286
}
259287
}
260288
return m, nil
@@ -264,7 +292,7 @@ func (m assignKeysModel) updateKeySelection(msg tea.Msg) (tea.Model, tea.Cmd) {
264292
}
265293

266294
// viewAccountList renders the left pane containing the list of accounts.
267-
func (m assignKeysModel) viewAccountList() string {
295+
func (m *assignKeysModel) viewAccountList() string {
268296
var listItems []string
269297
accounts := m.filteredAccounts()
270298
if len(accounts) == 0 {
@@ -293,7 +321,7 @@ func (m assignKeysModel) viewAccountList() string {
293321
}
294322

295323
// viewKeySelection renders the right pane containing the list of keys for assignment.
296-
func (m assignKeysModel) viewKeySelection() string {
324+
func (m *assignKeysModel) viewKeySelection() string {
297325
var listItems []string
298326
keys := m.filteredKeys()
299327
if len(keys) == 0 {
@@ -339,7 +367,7 @@ func (m assignKeysModel) viewKeySelection() string {
339367
}
340368

341369
// View renders the entire key assignment UI.
342-
func (m assignKeysModel) View() string {
370+
func (m *assignKeysModel) View() string {
343371
left := m.viewAccountList()
344372
right := ""
345373
if m.state == assignStateSelectKeys {

internal/tui/tui.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ type mainModel struct {
5757
menu menuModel
5858
deployer deployModel
5959
rotator *rotateKeyModel
60-
assignment assignKeysModel
60+
assignment *assignKeysModel
6161
keys publicKeysModel
6262
accounts accountsModel
6363
auditLog *auditLogModel
@@ -149,9 +149,13 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
149149
m.state = menuView
150150
return m, refreshDashboardCmd()
151151
}
152-
var newAssignmentModel tea.Model
153-
newAssignmentModel, cmd = m.assignment.Update(msg)
154-
m.assignment = newAssignmentModel.(assignKeysModel)
152+
var newModel tea.Model
153+
newModel, cmd = m.assignment.Update(msg)
154+
// Since assignment is a pointer receiver, we don't need to reassign
155+
// the model unless it's changed
156+
if newModel != m.assignment {
157+
m.assignment = newModel.(*assignKeysModel)
158+
}
155159

156160
case rotateKeyView:
157161
// If we received a "back" message, switch the state.
@@ -216,7 +220,7 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
216220
return m, nil
217221
case 2: // Assign Keys to Accounts
218222
m.state = assignKeysView
219-
m.assignment = newAssignKeysModel()
223+
m.assignment = newAssignKeysModel() // Already returns *assignKeysModel
220224
return m, nil
221225
case 3: // Rotate System Keys
222226
m.state = rotateKeyView

0 commit comments

Comments
 (0)