sshkeys.go
⎇
Raw
1package db
2
3import (
4 "context"
5 "database/sql"
6 "errors"
7)
8
9type SSHKey struct {
10 ID int64
11 UserID int64
12 Name string
13 PublicKey string
14 Fingerprint string
15 CreatedAt string
16}
17
18func (d *DB) ListSSHKeys(ctx context.Context, userID int64) ([]SSHKey, error) {
19 rows, err := d.QueryContext(ctx,
20 `SELECT id, user_id, name, public_key, fingerprint, created_at
21 FROM ssh_keys WHERE user_id = ?`, userID)
22 if err != nil {
23 return nil, err
24 }
25 defer rows.Close()
26 var out []SSHKey
27 for rows.Next() {
28 var k SSHKey
29 if err := rows.Scan(&k.ID, &k.UserID, &k.Name, &k.PublicKey, &k.Fingerprint, &k.CreatedAt); err != nil {
30 return nil, err
31 }
32 out = append(out, k)
33 }
34 return out, rows.Err()
35}
36
37func (d *DB) CreateSSHKey(ctx context.Context, userID int64, name, publicKey, fingerprint, createdAt string) error {
38 _, err := d.ExecContext(ctx,
39 `INSERT INTO ssh_keys (user_id, name, public_key, fingerprint, created_at)
40 VALUES (?, ?, ?, ?, ?)`,
41 userID, name, publicKey, fingerprint, createdAt)
42 return err
43}
44
45// SSHKeyOwner returns the id and user of one key, used to check ownership
46// before a delete.
47func (d *DB) SSHKeyOwner(ctx context.Context, id int64) (int64, bool, error) {
48 var userID int64
49 err := d.QueryRowContext(ctx, `SELECT user_id FROM ssh_keys WHERE id = ?`, id).Scan(&userID)
50 if errors.Is(err, sql.ErrNoRows) {
51 return 0, false, nil
52 }
53 if err != nil {
54 return 0, false, err
55 }
56 return userID, true, nil
57}
58
59func (d *DB) DeleteSSHKey(ctx context.Context, id int64) error {
60 _, err := d.ExecContext(ctx, `DELETE FROM ssh_keys WHERE id = ?`, id)
61 return err
62}
63
64// SSHKeyUser is the identity behind an SSH public key offered at login.
65type SSHKeyUser struct {
66 UserID int64
67 Username string
68 PublicKey string
69}
70
71// SSHKeyByFingerprint resolves an SSH key to its (non-pending) owner.
72func (d *DB) SSHKeyByFingerprint(ctx context.Context, fingerprint string) (*SSHKeyUser, error) {
73 var k SSHKeyUser
74 err := d.QueryRowContext(ctx,
75 `SELECT users.id, users.username, ssh_keys.public_key
76 FROM ssh_keys
77 JOIN users ON users.id = ssh_keys.user_id
78 WHERE ssh_keys.fingerprint = ? AND users.is_pending = 0`,
79 fingerprint).Scan(&k.UserID, &k.Username, &k.PublicKey)
80 if errors.Is(err, sql.ErrNoRows) {
81 return nil, nil
82 }
83 if err != nil {
84 return nil, err
85 }
86 return &k, nil
87}
88