backend.go

 1package backend
 2
 3import (
 4	"context"
 5
 6	"github.com/charmbracelet/log"
 7	"github.com/charmbracelet/soft-serve/server/access"
 8	"github.com/charmbracelet/soft-serve/server/auth"
 9	"github.com/charmbracelet/soft-serve/server/config"
10	"github.com/charmbracelet/soft-serve/server/settings"
11	"github.com/charmbracelet/soft-serve/server/sshutils"
12	"github.com/charmbracelet/soft-serve/server/store"
13	"github.com/charmbracelet/ssh"
14	gossh "golang.org/x/crypto/ssh"
15)
16
17// Backend handles repository management, server settings, authentication, and
18// authorization.
19type Backend struct {
20	settings.Settings
21	store.Store
22	auth.Auth
23	access.Access
24
25	ctx    context.Context
26	logger *log.Logger
27}
28
29// NewBackendStore returns a new BackendStore.
30func NewBackend(ctx context.Context, s settings.Settings, st store.Store, a auth.Auth, ac access.Access) (*Backend, error) {
31	ba := &Backend{
32		Settings: s,
33		Store:    st,
34		Auth:     a,
35		Access:   ac,
36		ctx:      ctx,
37		logger:   log.FromContext(ctx).WithPrefix("backend"),
38	}
39
40	return ba, nil
41}
42
43// AccessLevel returns the access level for the given user and repository.
44// It will also check if the SSH connection is using an admin key.
45func (b *Backend) AccessLevel(ctx context.Context, repo string, user auth.User) (access.AccessLevel, error) {
46	cfg := config.FromContext(ctx)
47	if cfg != nil {
48		log.Printf("found cfg")
49		if pk, ok := ctx.Value(ssh.ContextKeyPublicKey).(gossh.PublicKey); ok {
50			log.Printf("pk: %v", sshutils.MarshalAuthorizedKey(pk))
51			for _, k := range cfg.AdminKeys() {
52				if sshutils.KeysEqual(pk, k) {
53					return access.AdminAccess, nil
54				}
55			}
56		}
57		log.Printf("no pk")
58	}
59
60	log.Printf("no cfg")
61
62	return b.Access.AccessLevel(ctx, repo, user)
63}