Skip to content

Commit

Permalink
Use new Wish auth WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Toby Padilla committed Oct 2, 2021
1 parent 0e4d562 commit 074eada
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 106 deletions.
20 changes: 20 additions & 0 deletions config/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package config

import (
gm "github.com/charmbracelet/wish/git"
"github.com/gliderlabs/ssh"
)

func (cfg *Config) AuthRepo(repo string, pk ssh.PublicKey) gm.AccessLevel {
// TODO: check yaml for access rules
return gm.ReadWriteAccess
}

func (cfg *Config) PasswordHandler(ctx ssh.Context, password string) bool {
return cfg.AnonReadOnly && cfg.AllowNoKeys
}

func (cfg *Config) PublicKeyHandler(ctx ssh.Context, pk ssh.PublicKey) bool {
// TODO: check yaml for access rules
return true
}
164 changes: 164 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package config

import (
"log"

"gopkg.in/yaml.v2"

"fmt"
"os"
"path/filepath"
"soft-serve/git"

"github.com/gliderlabs/ssh"
gg "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
)

type Config struct {
Name string `yaml:"name"`
Host string `yaml:"host"`
Port int `yaml:"port"`
AnonReadOnly bool `yaml:"anon-access"`
AllowNoKeys bool `yaml:"allow-no-keys"`
Users []User `yaml:"users"`
Repos []Repo `yaml:"repos"`
Source *git.RepoSource
}

type User struct {
Name string `yaml:"name"`
Admin bool `yaml:"admin"`
PublicKey string `yaml:"pk"`
CollabRepos []string `yaml:"collab_repos"`
}

type Repo struct {
Name string `yaml:"name"`
Repo string `yaml:"repo"`
Note string `yaml:"note"`
}

func NewConfig(host string, port int, anon bool, pk string, rs *git.RepoSource) (*Config, error) {
cfg := &Config{}
cfg.Host = host
cfg.Port = port
cfg.AnonReadOnly = anon
cfg.Source = rs

var yamlUsers string
var h string
if host == "" {
h = "localhost"
} else {
h = host
}
yamlConfig := fmt.Sprintf(defaultConfig, h, port, anon)
if pk != "" {
yamlUsers = fmt.Sprintf(hasKeyUserConfig, pk)
} else {
yamlUsers = defaultUserConfig
}
yaml := fmt.Sprintf("%s%s%s", yamlConfig, yamlUsers, exampleUserConfig)
err := cfg.createDefaultConfigRepo(yaml)
if err != nil {
return nil, err
}
return cfg, nil
}

func (cfg *Config) Pushed(repo string, pk ssh.PublicKey) {
err := cfg.Reload()
if err != nil {
log.Printf("error reloading after push: %s", err)
}
}

func (cfg *Config) Reload() error {
err := cfg.Source.LoadRepos()
if err != nil {
return err
}
cr, err := cfg.Source.GetRepo("config")
if err != nil {
return err
}
cs, err := cr.LatestFile("config.yaml")
if err != nil {
return err
}
err = yaml.Unmarshal([]byte(cs), cfg)
if err != nil {
return fmt.Errorf("bad yaml in config.yaml: %s", err)
}
return nil
}

func createFile(path string, content string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(content)
if err != nil {
return err
}
return f.Sync()
}

func (cfg *Config) createDefaultConfigRepo(yaml string) error {
cn := "config"
rs := cfg.Source
err := rs.LoadRepos()
if err != nil {
return err
}
_, err = rs.GetRepo(cn)
if err == git.ErrMissingRepo {
cr, err := rs.InitRepo(cn, false)
if err != nil {
return err
}

rp := filepath.Join(rs.Path, cn, "README.md")
err = createFile(rp, defaultReadme)
if err != nil {
return err
}
cp := filepath.Join(rs.Path, cn, "config.yaml")
err = createFile(cp, yaml)
if err != nil {
return err
}
wt, err := cr.Repository.Worktree()
if err != nil {
return err
}
_, err = wt.Add("README.md")
if err != nil {
return err
}
_, err = wt.Add("config.yaml")
if err != nil {
return err
}
_, err = wt.Commit("Default init", &gg.CommitOptions{
All: true,
Author: &object.Signature{
Name: "Soft Serve Server",
Email: "vt100@charm.sh",
},
})
if err != nil {
return err
}
err = rs.LoadRepos()
if err != nil {
return err
}
} else if err != nil {
return err
}
return nil
}
42 changes: 42 additions & 0 deletions config/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
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 defaultConfig = `
name: Soft Serve
host: %s
port: %d
# Set the access level for anonymous users. Options are: read-write, read-only and no-access
anon-access: %v
# Allow read only even if they don't have private keys, any password will work
allow-no-keys: false
# Customize repo display in menu
repos:
- name: Home
repo: config
note: "Configuration and content repo for this server"`

const hasKeyUserConfig = `
# Users can read all repos, and push to collab-repos, admin can push to all repos
users:
- name: admin
admin: true
public-key: |
%s`

const defaultUserConfig = `
# users:
# - name: admin
# admin: true
# public-key: |
# KEY TEXT`

const exampleUserConfig = `
# - name: little-buddy
# collab-repos:
# - soft-serve
# public-key: |
# KEY TEXT`
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/muesli/reflow v0.3.0
github.com/muesli/termenv v0.9.0
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
gopkg.in/yaml.v2 v2.3.0
)

require (
Expand Down
47 changes: 32 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,62 @@ package main
import (
"fmt"
"log"
"soft-serve/config"
"soft-serve/git"
"soft-serve/tui"
"time"

"github.com/charmbracelet/wish"
bm "github.com/charmbracelet/wish/bubbletea"
gm "github.com/charmbracelet/wish/git"
lm "github.com/charmbracelet/wish/logging"
"github.com/gliderlabs/ssh"

"github.com/meowgorithm/babyenv"
)

type Config struct {
Port int `env:"SOFT_SERVE_PORT" default:"23231"`
Host string `env:"SOFT_SERVE_HOST" default:""`
KeyPath string `env:"SOFT_SERVE_KEY_PATH" default:".ssh/soft_serve_server_ed25519"`
RepoAuth string `env:"SOFT_SERVE_REPO_KEYS" default:""`
RepoAuthFile string `env:"SOFT_SERVE_REPO_KEYS_PATH" default:".ssh/soft_serve_git_authorized_keys"`
RepoPath string `env:"SOFT_SERVE_REPO_PATH" default:".repos"`
type serverConfig struct {
Port int `env:"SOFT_SERVE_PORT" default:"23231"`
Host string `env:"SOFT_SERVE_HOST" default:""`
InitKey string `env:"SOFT_SERVE_REPO_KEY" default:""`
KeyPath string `env:"SOFT_SERVE_KEY_PATH" default:".ssh/soft_serve_server_ed25519"`
RepoPath string `env:"SOFT_SERVE_REPO_PATH" default:".repos"`
}

func main() {
var cfg Config
err := babyenv.Parse(&cfg)
var scfg serverConfig
var cfg *config.Config
var err error
err = babyenv.Parse(&scfg)
if err != nil {
log.Fatalln(err)
}
rs := git.NewRepoSource(scfg.RepoPath)
if scfg.InitKey == "" {
cfg, err = config.NewConfig(scfg.Host, scfg.Port, true, "", rs)
if err != nil {
log.Fatalln(err)
}
} else {
cfg, err = config.NewConfig(scfg.Host, scfg.Port, false, scfg.InitKey, rs)
if err != nil {
log.Fatalln(err)
}
}
s, err := wish.NewServer(
wish.WithAddress(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)),
wish.WithHostKeyPath(cfg.KeyPath),
ssh.PublicKeyAuth(cfg.PublicKeyHandler),
ssh.PasswordAuth(cfg.PasswordHandler),
wish.WithAddress(fmt.Sprintf("%s:%d", scfg.Host, scfg.Port)),
wish.WithHostKeyPath(scfg.KeyPath),
wish.WithMiddlewares(
bm.Middleware(tui.SessionHandler(cfg.RepoPath, time.Second*5)),
gm.Middleware(cfg.RepoPath, cfg.RepoAuth, cfg.RepoAuthFile),
bm.Middleware(tui.SessionHandler(cfg)),
gm.MiddlewareWithPushCallback(scfg.RepoPath, cfg, cfg.Pushed),
lm.Middleware(),
),
)
if err != nil {
log.Fatalln(err)
}
log.Printf("Starting SSH server on %s:%d\n", cfg.Host, cfg.Port)
log.Printf("Starting SSH server on %s:%d\n", scfg.Host, scfg.Port)
err = s.ListenAndServe()
if err != nil {
log.Fatalln(err)
Expand Down
28 changes: 7 additions & 21 deletions tui/bubble.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tui

import (
"fmt"
"soft-serve/config"
"soft-serve/git"
"soft-serve/tui/bubbles/repo"
"soft-serve/tui/bubbles/selection"
Expand All @@ -22,13 +23,10 @@ const (
quitState
)

type Config struct {
Name string `json:"name"`
Host string `json:"host"`
Port int64 `json:"port"`
ShowAllRepos bool `json:"show_all_repos"`
Menu []MenuEntry `json:"menu"`
RepoSource *git.RepoSource
type SessionConfig struct {
Width int
Height int
InitialRepo string
}

type MenuEntry struct {
Expand All @@ -38,20 +36,13 @@ type MenuEntry struct {
bubble *repo.Bubble
}

type SessionConfig struct {
Width int
Height int
InitialRepo string
}

type Bubble struct {
config *Config
config *config.Config
styles *style.Styles
state sessionState
error string
width int
height int
repoSource *git.RepoSource
initialRepo string
repoMenu []MenuEntry
repos []*git.Repo
Expand All @@ -60,17 +51,12 @@ type Bubble struct {
repoSelect *selection.Bubble
}

func NewBubble(cfg *Config, sCfg *SessionConfig) *Bubble {
var repoSource *git.RepoSource = nil
if cfg != nil {
repoSource = cfg.RepoSource
}
func NewBubble(cfg *config.Config, sCfg *SessionConfig) *Bubble {
b := &Bubble{
config: cfg,
styles: style.DefaultStyles(),
width: sCfg.Width,
height: sCfg.Height,
repoSource: repoSource,
repoMenu: make([]MenuEntry, 0),
boxes: make([]tea.Model, 2),
initialRepo: sCfg.InitialRepo,
Expand Down
2 changes: 1 addition & 1 deletion tui/bubbles/repo/bubble.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type Bubble struct {
// solution would be to (rename and) move this Bubble into the parent
// package.
Host string
Port int64
Port int
}

func NewBubble(rs *git.RepoSource, name string, styles *style.Styles, width, wm, height, hm int, tmp interface{}) *Bubble {
Expand Down
Loading

0 comments on commit 074eada

Please sign in to comment.