Skip to content

Commit b041a1e

Browse files
committed
Merge branch 'main' of github.com:ToeiRei/Keymaster
2 parents b36f433 + 176393f commit b041a1e

5 files changed

Lines changed: 242 additions & 32 deletions

File tree

client/client.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (c) 2026 Keymaster Team
2+
// Keymaster - SSH key management system
3+
// This source code is licensed under the MIT license found in the LICENSE file.
4+
package client
5+
6+
import (
7+
"context"
8+
"log"
9+
"time"
10+
11+
"github.com/toeirei/keymaster/internal/core"
12+
)
13+
14+
type Client struct {
15+
config Config
16+
store core.Store
17+
// NOTE:
18+
// log != audit_log
19+
// log is not meant for cli out
20+
log *log.Logger
21+
}
22+
23+
// --- Mock types that will later be imported or defined seperately ---
24+
type ID int
25+
type PublicKey struct{}
26+
type Target struct{}
27+
type Account struct{}
28+
type DeployProgress struct {
29+
Done bool
30+
// ...
31+
}
32+
type OnboardHostProgress struct {
33+
Done bool
34+
// ...
35+
}
36+
type DecommisionTargetProgress struct {
37+
Done bool
38+
// ...
39+
}
40+
type DecommisionAccountProgress struct {
41+
Done bool
42+
// ...
43+
}
44+
45+
// --- Lifecycle & Initialization ---
46+
47+
// connect to db,
48+
// auto migrate db to current version,
49+
// initialize store,
50+
// maybe run some offline chores
51+
func New(config Config, logger *log.Logger) (*Client, error)
52+
53+
// cleans up and closes all open connections,
54+
// maybe be an ******* and set c to nil
55+
func (c *Client) Close(ctx context.Context) error
56+
57+
// --- PublicKey Management ---
58+
59+
func (c *Client) CreatePublicKey(ctx context.Context, identity string, tags []string) (ID, error)
60+
func (c *Client) GetPublicKey(ctx context.Context, id ID) (PublicKey, error)
61+
func (c *Client) GetPublicKeys(ctx context.Context, id ...ID) ([]PublicKey, error)
62+
func (c *Client) ListPublicKeys(ctx context.Context, tagFilter string) ([]PublicKey, error)
63+
func (c *Client) UpdatePublicKeyTags(ctx context.Context, id ID, tags []string) error
64+
func (c *Client) DeletePublicKeys(ctx context.Context, id ...ID) error
65+
66+
// --- Target Management ---
67+
68+
func (c *Client) CreateTarget(ctx context.Context, host string, port int /* , gateway string, plugin string */) (ID, error)
69+
func (c *Client) GetTarget(ctx context.Context, id ID) (Target, error)
70+
func (c *Client) GetTargets(ctx context.Context, id ...ID) ([]Target, error)
71+
func (c *Client) ListTargets(ctx context.Context) ([]Target, error)
72+
func (c *Client) UpdateTarget(ctx context.Context, id ID, target Target) error
73+
func (c *Client) DeleteTargets(ctx context.Context, id ...ID) error
74+
75+
// --- Account Management ---
76+
77+
func (c *Client) CreateAccount(ctx context.Context, targetID ID, name string, deploymentKey string) (ID, error)
78+
func (c *Client) GetAccount(ctx context.Context, id ID) (Account, error)
79+
func (c *Client) ListAccountsByTarget(ctx context.Context, targetID ID) ([]Account, error)
80+
func (c *Client) GetDirtyAccounts(ctx context.Context) ([]Account, error)
81+
82+
// --- Tag to Account Management ---
83+
84+
// LinkTagToAccount maps a tag filter (e.g. "device:mobile&company:telekom") to an account
85+
func (c *Client) LinkTagAccount(ctx context.Context, accountID ID, filter string, expiresAt time.Time) (ID, error)
86+
func (c *Client) UnLinkTagAccount(ctx context.Context, linkIDs ...ID) error
87+
func (c *Client) ResolvePublicKeysForAccount(ctx context.Context, accountID ID) ([]PublicKey, error)
88+
func (c *Client) ResolveAccountsForPublicKey(ctx context.Context, publicKeyID ID) ([]Account, error)
89+
90+
// --- Onboarding & Decommision ---
91+
92+
func (c *Client) OnboardHost(ctx context.Context, host string, port int /* , gateway string, plugin string */, accountName string, deploymentKey string) (chan OnboardHostProgress, error)
93+
func (c *Client) DecommisionTarget(ctx context.Context, id ID) (chan DecommisionTargetProgress, error)
94+
func (c *Client) DecommisionAccount(ctx context.Context, id ID) (chan DecommisionAccountProgress, error)
95+
96+
// --- Deploy stuff ---
97+
98+
// Deploy handles the plugin-based deployment to the target
99+
func (c *Client) DeployPublicKeys(ctx context.Context, publicKeyID ...ID) (chan DeployProgress, error)
100+
func (c *Client) DeployTargets(ctx context.Context, targetID ...ID) (chan DeployProgress, error)
101+
func (c *Client) DeployAccounts(ctx context.Context, accountID ...ID) (chan DeployProgress, error)
102+
func (c *Client) DeployAll(ctx context.Context) (chan DeployProgress, error)

client/config.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2026 Keymaster Team
2+
// Keymaster - SSH key management system
3+
// This source code is licensed under the MIT license found in the LICENSE file.
4+
package client
5+
6+
type LogLevel int
7+
8+
type Config struct {
9+
// add all options needed to initialize the client and its db connection here
10+
LogLevel LogLevel
11+
DatabaseUri string
12+
// ...
13+
}

internal/core/dashboard.go

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@ package core
77
import (
88
"sort"
99

10+
"github.com/toeirei/keymaster/internal/core/db"
1011
"github.com/toeirei/keymaster/internal/model"
1112
)
1213

1314
// DashboardData holds aggregated values for the main dashboard.
1415
type DashboardData struct {
1516
AccountCount int
1617
ActiveAccountCount int
17-
PublicKeyCount int
18-
GlobalKeyCount int
19-
HostsUpToDate int
20-
HostsOutdated int
21-
AlgoCounts map[string]int
22-
SystemKeySerial int
23-
RecentLogs []model.AuditLogEntry
18+
// PublicKeyCount int
19+
// GlobalKeyCount int
20+
// AlgoCounts map[string]int
21+
HostsUpToDate int
22+
HostsOutdated int
23+
SystemKeySerial int
24+
RecentLogs []model.AuditLogEntry
2425
}
2526

2627
// BuildDashboardData collects accounts, keys, system key and recent audit logs,
@@ -30,39 +31,43 @@ type AccountReader interface {
3031
GetAllAccounts() ([]model.Account, error)
3132
}
3233

33-
// KeyReader exposes key reads required by the dashboard.
34-
type KeyReader interface {
35-
GetAllPublicKeys() ([]model.PublicKey, error)
36-
GetActiveSystemKey() (*model.SystemKey, error)
37-
GetSystemKeyBySerial(serial int) (*model.SystemKey, error)
38-
}
34+
// // KeyReader exposes key reads required by the dashboard.
35+
// type KeyReader interface {
36+
// GetAllPublicKeys() ([]model.PublicKey, error)
37+
// GetActiveSystemKey() (*model.SystemKey, error)
38+
// GetSystemKeyBySerial(serial int) (*model.SystemKey, error)
39+
// }
3940

4041
// AuditReader exposes audit log reads required by the dashboard.
4142
type AuditReader interface {
4243
GetAllAuditLogEntries() ([]model.AuditLogEntry, error)
4344
}
4445

46+
var _ AccountReader = (db.Store)(nil) // db.Store implements AccountReader
47+
// var _ KeyReader = (db.Store)(nil) // db.Store implements KeyReader
48+
var _ AuditReader = (db.Store)(nil) // db.Store implements AuditReader
49+
4550
// BuildDashboardData computes metrics using provided readers. Core no longer
4651
// depends on DB packages directly; callers must supply implementations.
47-
func BuildDashboardData(accounts AccountReader, keys KeyReader, audits AuditReader) (DashboardData, error) {
52+
func BuildDashboardData(store db.Store) (DashboardData, error) {
4853
var out DashboardData
4954

50-
accs, err := accounts.GetAllAccounts()
55+
accs, err := store.GetAllAccounts()
5156
if err != nil {
5257
return out, err
5358
}
5459

55-
klist, err := keys.GetAllPublicKeys()
56-
if err != nil {
57-
return out, err
58-
}
60+
// klist, err := store. GetAllPublicKeys()
61+
// if err != nil {
62+
// return out, err
63+
// }
5964

60-
sysKey, err := keys.GetActiveSystemKey()
65+
sysKey, err := store.GetActiveSystemKey()
6166
if err != nil {
6267
return out, err
6368
}
6469

65-
logs, err := audits.GetAllAuditLogEntries()
70+
logs, err := store.GetAllAuditLogEntries()
6671
if err != nil {
6772
return out, err
6873
}
@@ -81,14 +86,14 @@ func BuildDashboardData(accounts AccountReader, keys KeyReader, audits AuditRead
8186
}
8287
}
8388

84-
out.PublicKeyCount = len(klist)
85-
out.AlgoCounts = make(map[string]int)
86-
for _, k := range klist {
87-
if k.IsGlobal {
88-
out.GlobalKeyCount++
89-
}
90-
out.AlgoCounts[k.Algorithm]++
91-
}
89+
// out.PublicKeyCount = len(klist)
90+
// out.AlgoCounts = make(map[string]int)
91+
// for _, k := range klist {
92+
// if k.IsGlobal {
93+
// out.GlobalKeyCount++
94+
// }
95+
// out.AlgoCounts[k.Algorithm]++
96+
// }
9297

9398
if sysKey != nil {
9499
out.SystemKeySerial = sysKey.Serial

ui/tui/models/views/content/content.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/toeirei/keymaster/ui/tui/models/components/popup"
1111
"github.com/toeirei/keymaster/ui/tui/models/components/router"
1212
"github.com/toeirei/keymaster/ui/tui/models/components/stack"
13-
"github.com/toeirei/keymaster/ui/tui/models/views/debug"
13+
"github.com/toeirei/keymaster/ui/tui/models/views/dashboard"
1414
"github.com/toeirei/keymaster/ui/tui/models/views/testpopup1"
1515
"github.com/toeirei/keymaster/ui/tui/util"
1616
)
@@ -102,8 +102,8 @@ func New() *Model {
102102
),
103103
menu.WithItem("feedback", "User Feedback"),
104104
))
105-
_debug := util.ModelPointer(debug.New())
106-
_router, routerControll := router.New(_debug)
105+
_dashboard := util.ModelPointer(dashboard.New())
106+
_router, routerControll := router.New(_dashboard)
107107
_stack := stack.New(
108108
stack.WithOrientation(stack.Horizontal),
109109
stack.WithFocusNext(),
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright (c) 2026 Keymaster Team
2+
// Keymaster - SSH key management system
3+
// This source code is licensed under the MIT license found in the LICENSE file.
4+
package dashboard
5+
6+
import (
7+
"fmt"
8+
9+
"github.com/charmbracelet/bubbles/help"
10+
tea "github.com/charmbracelet/bubbletea"
11+
"github.com/charmbracelet/lipgloss"
12+
"github.com/toeirei/keymaster/internal/core"
13+
"github.com/toeirei/keymaster/internal/core/db"
14+
"github.com/toeirei/keymaster/internal/model"
15+
"github.com/toeirei/keymaster/ui/tui/util"
16+
"github.com/toeirei/keymaster/util/slicest"
17+
)
18+
19+
type Model struct {
20+
db db.Store
21+
data core.DashboardData
22+
err error
23+
size util.Size
24+
}
25+
26+
func New() *Model {
27+
return &Model{}
28+
}
29+
30+
func (m Model) Init() tea.Cmd {
31+
return nil
32+
}
33+
34+
func (m *Model) Update(msg tea.Msg) tea.Cmd {
35+
if m.size.Update(msg) {
36+
return nil
37+
}
38+
// wont work until db can be constructed... mock for now
39+
// m.data, m.err = core.BuildDashboardData(m.db)
40+
m.data = core.DashboardData{
41+
AccountCount: 69,
42+
ActiveAccountCount: 420,
43+
HostsUpToDate: 67,
44+
HostsOutdated: 0,
45+
SystemKeySerial: 9001,
46+
RecentLogs: []model.AuditLogEntry{
47+
{
48+
ID: 1,
49+
Timestamp: "2026.01.01",
50+
Username: "rei",
51+
Action: "eat",
52+
Details: "nothing",
53+
},
54+
},
55+
}
56+
m.err = nil
57+
return nil
58+
}
59+
60+
func (m Model) View() string {
61+
if m.err != nil {
62+
return fmt.Sprintf(
63+
"Error Loading Dashboard data:\n%s",
64+
lipgloss.NewStyle().Italic(true).Render(m.err.Error()),
65+
)
66+
} else {
67+
return fmt.Sprintf(
68+
"AccountCount: %v\nActiveAccountCount: %v\nHostsUpToDate: %v\nHostsOutdated: %v\nSystemKeySerial: %v\nRecentLogs:\n%s\n",
69+
m.data.AccountCount,
70+
m.data.ActiveAccountCount,
71+
m.data.HostsUpToDate,
72+
m.data.HostsOutdated,
73+
m.data.SystemKeySerial,
74+
lipgloss.JoinVertical(
75+
lipgloss.Left,
76+
slicest.Map(
77+
m.data.RecentLogs,
78+
func(al model.AuditLogEntry) string { return fmt.Sprintf("- %+#v", al) },
79+
)...,
80+
),
81+
)
82+
}
83+
}
84+
85+
// no focus needed, as it will only be used as a basic background for the apps content
86+
func (m *Model) Focus(baseKeyMap help.KeyMap) tea.Cmd { return nil }
87+
func (m *Model) Blur() {}
88+
89+
// *Model implements util.Model
90+
var _ util.Model = (*Model)(nil)

0 commit comments

Comments
 (0)