From 5ff41c0e6f71e5aaac3a3edbe7373baebb226ad9 Mon Sep 17 00:00:00 2001 From: Toby Padilla Date: Tue, 5 Oct 2021 18:02:45 -0500 Subject: [PATCH] Allow repos to be private / admin only --- config/config.go | 16 +++++++++++++--- config/defaults.go | 3 ++- config/git.go | 8 ++++++-- tui/bubble.go | 4 ++++ tui/commands.go | 27 +++++++++++++++------------ tui/session.go | 2 +- 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/config/config.go b/config/config.go index 8eafe2810..168ba4c56 100644 --- a/config/config.go +++ b/config/config.go @@ -31,9 +31,10 @@ type User struct { } type Repo struct { - Name string `yaml:"name"` - Repo string `yaml:"repo"` - Note string `yaml:"note"` + Name string `yaml:"name"` + Repo string `yaml:"repo"` + Note string `yaml:"note"` + Private bool `yaml:"private"` } func NewConfig(host string, port int, pk string, rs *git.RepoSource) (*Config, error) { @@ -155,3 +156,12 @@ func (cfg *Config) createDefaultConfigRepo(yaml string) error { } return cfg.reload() } + +func (cfg *Config) isPrivate(repo string) bool { + for _, r := range cfg.Repos { + if r.Repo == repo { + return r.Private + } + } + return false +} diff --git a/config/defaults.go b/config/defaults.go index 261784419..0eaceb131 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -1,6 +1,6 @@ package config -const defaultReadme = "# Soft Serve\n\n Welcome! You can configure your Soft Serve server by cloning this repo and pushing changes.\n\n## Repos\n\n{{ range .Repos }}* {{ .Name }}{{ if .Note }} - {{ .Note }} {{ end }}\n - `git clone ssh://{{$.Host}}:{{$.Port}}/{{.Repo}}`\n{{ end }}" +const defaultReadme = "# Soft Serve\n\n Welcome! You can configure your Soft Serve server by cloning this repo and pushing changes.\n\n```\ngit clone ssh://{{.Host}}:{{.Port}}/config\n```" const defaultConfig = `name: Soft Serve host: %s @@ -16,6 +16,7 @@ allow-no-keys: false repos: - name: Home repo: config + private: true note: "Configuration and content repo for this server"` const hasKeyUserConfig = ` diff --git a/config/git.go b/config/git.go index 0e559508f..bd7372a8b 100644 --- a/config/git.go +++ b/config/git.go @@ -35,6 +35,10 @@ func (cfg *Config) PublicKeyHandler(ctx ssh.Context, pk ssh.PublicKey) bool { } func (cfg *Config) accessForKey(repo string, pk ssh.PublicKey) gm.AccessLevel { + private := cfg.isPrivate(repo) + if repo == "config" { + private = true + } for _, u := range cfg.Users { apk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(u.PublicKey)) if err != nil { @@ -50,12 +54,12 @@ func (cfg *Config) accessForKey(repo string, pk ssh.PublicKey) gm.AccessLevel { return gm.ReadWriteAccess } } - if repo != "config" { + if !private { return gm.ReadOnlyAccess } } } - if repo == "config" && (cfg.AnonAccess != "read-write") { + if private && (cfg.AnonAccess != "read-write") { return gm.NoAccess } switch cfg.AnonAccess { diff --git a/tui/bubble.go b/tui/bubble.go index 6ae9047c1..11c238b04 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -11,6 +11,7 @@ import ( "github.com/charmbracelet/soft/tui/bubbles/repo" "github.com/charmbracelet/soft/tui/bubbles/selection" "github.com/charmbracelet/soft/tui/style" + "github.com/gliderlabs/ssh" ) type sessionState int @@ -27,6 +28,7 @@ type SessionConfig struct { Width int Height int InitialRepo string + Session ssh.Session } type MenuEntry struct { @@ -49,6 +51,7 @@ type Bubble struct { boxes []tea.Model activeBox int repoSelect *selection.Bubble + session ssh.Session } func NewBubble(cfg *config.Config, sCfg *SessionConfig) *Bubble { @@ -60,6 +63,7 @@ func NewBubble(cfg *config.Config, sCfg *SessionConfig) *Bubble { repoMenu: make([]MenuEntry, 0), boxes: make([]tea.Model, 2), initialRepo: sCfg.InitialRepo, + session: sCfg.Session, } b.state = startState return b diff --git a/tui/commands.go b/tui/commands.go index 083a2f4da..072d83b2e 100644 --- a/tui/commands.go +++ b/tui/commands.go @@ -8,6 +8,7 @@ import ( "github.com/charmbracelet/soft/config" br "github.com/charmbracelet/soft/tui/bubbles/repo" "github.com/charmbracelet/soft/tui/bubbles/selection" + gm "github.com/charmbracelet/wish/git" "github.com/muesli/termenv" ) @@ -61,18 +62,20 @@ func (b *Bubble) setupCmd() tea.Msg { func (b *Bubble) menuEntriesFromSource() ([]MenuEntry, error) { mes := make([]MenuEntry, 0) - for _, r := range b.config.Repos { - me, err := b.newMenuEntry(r.Name, r.Repo) - if err != nil { - return nil, err - } - mes = append(mes, me) - } rs := b.config.Source.AllRepos() OUTER: for _, r := range rs { - for _, me := range mes { - if r.Name == me.Repo { + acc := b.config.AuthRepo(r.Name, b.session.PublicKey()) + if acc == gm.NoAccess && r.Name != "config" { + continue + } + for _, cr := range b.config.Repos { + if r.Name == cr.Repo { + me, err := b.newMenuEntry(cr.Name, cr.Repo) + if err != nil { + return nil, err + } + mes = append(mes, me) continue OUTER } } @@ -87,6 +90,9 @@ OUTER: func (b *Bubble) newMenuEntry(name string, repo string) (MenuEntry, error) { var tmplConfig *config.Config + if repo == "config" { + tmplConfig = b.config + } me := MenuEntry{Name: name, Repo: repo} width := b.width boxLeftWidth := b.styles.Menu.GetWidth() + b.styles.Menu.GetHorizontalFrameSize() @@ -95,9 +101,6 @@ func (b *Bubble) newMenuEntry(name string, repo string) (MenuEntry, error) { lipgloss.Height(b.footerView()) + b.styles.RepoBody.GetVerticalFrameSize() + b.styles.App.GetVerticalMargins() - if repo == "config" { - tmplConfig = b.config - } rb := br.NewBubble( b.config.Source, me.Repo, diff --git a/tui/session.go b/tui/session.go index c91e5a31d..540ced515 100644 --- a/tui/session.go +++ b/tui/session.go @@ -11,7 +11,7 @@ import ( func SessionHandler(cfg *config.Config) func(ssh.Session) (tea.Model, []tea.ProgramOption) { return func(s ssh.Session) (tea.Model, []tea.ProgramOption) { cmd := s.Command() - scfg := &SessionConfig{} + scfg := &SessionConfig{Session: s} switch len(cmd) { case 0: scfg.InitialRepo = ""