Raw
 1package session
 2
 3import (
 4	"context"
 5	"errors"
 6	"fmt"
 7	"strings"
 8
 9	"tug/internal/platform/sshkey"
10	"tug/internal/platform/sshkey/openssh"
11	"tug/internal/storage"
12)
13
14func (s *Service) SSHKeys(ctx context.Context, userID string) ([]storage.SSHKey, error) {
15	keys, err := s.store.SSHKeysOf(ctx, userID)
16	if err != nil {
17		return nil, failure("list ssh keys", err)
18	}
19	return keys, nil
20}
21
22func (s *Service) AddSSHKey(ctx context.Context, p Principal, line, label string) (storage.SSHKey, error) {
23	const operation = "add ssh key"
24	if p.SessionID == "" {
25		return storage.SSHKey{}, fmt.Errorf("session: %s: %w: no current session", operation, ErrNoSession)
26	}
27	key, err := openssh.Parse(line)
28	if err != nil {
29		return storage.SSHKey{}, fmt.Errorf("session: %s: %w", operation, err)
30	}
31	if err := storage.CheckSSHKeyLabel(strings.TrimSpace(label)); err != nil {
32		return storage.SSHKey{}, fmt.Errorf("session: %s: %w", operation, err)
33	}
34	added, err := s.store.AddSSHKeyAudited(ctx, storage.AddSSHKeyInput{UserID: p.UserID, Key: key, Label: label, SessionID: p.SessionID}, p.UserID)
35	switch {
36	case errors.Is(err, sshkey.ErrOwned), errors.Is(err, sshkey.ErrTaken), errors.Is(err, sshkey.ErrLimit):
37		return storage.SSHKey{}, fmt.Errorf("session: %s: %w", operation, err)
38	case errors.Is(err, storage.ErrInvalid), errors.Is(err, storage.ErrSSHKeyDisabled), errors.Is(err, storage.ErrSSHKeyPending):
39		return storage.SSHKey{}, fmt.Errorf("session: %s: %w: %w", operation, ErrNoSession, err)
40	case err != nil:
41		return storage.SSHKey{}, failure(operation, err)
42	}
43	return added, nil
44}
45
46func (s *Service) RemoveSSHKey(ctx context.Context, p Principal, keyID string) (storage.SSHKey, error) {
47	const operation = "remove ssh key"
48	if p.SessionID == "" {
49		return storage.SSHKey{}, fmt.Errorf("session: %s: %w: no current session", operation, ErrNoSession)
50	}
51	removed, err := s.store.RemoveSSHKeyAudited(ctx, p.UserID, keyID, p.SessionID, p.UserID)
52	switch {
53	case errors.Is(err, storage.ErrSSHKeyNotFound):
54		return storage.SSHKey{}, fmt.Errorf("session: %s: %w: %w", operation, ErrNoSuchSSHKey, err)
55	case errors.Is(err, storage.ErrInvalid):
56		return storage.SSHKey{}, fmt.Errorf("session: %s: %w: %w", operation, ErrNoSession, err)
57	case err != nil:
58		return storage.SSHKey{}, failure(operation, err)
59	}
60	return removed, nil
61}