133728e barerepo 1mo
1
package store
133728e barerepo 1mo
3
import (
133728e barerepo 1mo
4
"context"
133728e barerepo 1mo
5
"errors"
133728e barerepo 1mo
6
"time"
133728e barerepo 1mo
9
// GPGKey is one signing key an account has published, so a signature on a commit can be checked.
133728e barerepo 1mo
10
type GPGKey struct {
133728e barerepo 1mo
11
ID int64
133728e barerepo 1mo
12
Account string
133728e barerepo 1mo
13
Fingerprint string
133728e barerepo 1mo
14
UID string
133728e barerepo 1mo
15
Armor string
133728e barerepo 1mo
16
Created time.Time
133728e barerepo 1mo
19
// AddGPGKey stores a key already parsed, since parsing needs gpg and this package needs none.
133728e barerepo 1mo
20
func (db *DB) AddGPGKey(ctx context.Context, account, fingerprint, uid, armor string) error {
133728e barerepo 1mo
21
_, err := db.ExecContext(ctx,
133728e barerepo 1mo
22
`INSERT INTO gpgkeys (account, fingerprint, uid, armor, created_at) VALUES (?, ?, ?, ?, ?)`,
133728e barerepo 1mo
23
account, fingerprint, uid, armor, now().Unix())
133728e barerepo 1mo
24
return err
133728e barerepo 1mo
27
// GPGKeys lists one account's keys, newest last, the way the keys page draws them.
133728e barerepo 1mo
28
func (db *DB) GPGKeys(ctx context.Context, account string) ([]GPGKey, error) {
133728e barerepo 1mo
29
rows, err := db.QueryContext(ctx,
133728e barerepo 1mo
30
`SELECT id, account, fingerprint, uid, armor, created_at
133728e barerepo 1mo
31
FROM gpgkeys WHERE account = ? ORDER BY id`, account)
133728e barerepo 1mo
32
if err != nil {
133728e barerepo 1mo
33
return nil, err
133728e barerepo 1mo
35
defer rows.Close()
133728e barerepo 1mo
36
var out []GPGKey
133728e barerepo 1mo
37
for rows.Next() {
133728e barerepo 1mo
38
var k GPGKey
133728e barerepo 1mo
39
var created int64
133728e barerepo 1mo
40
if err := rows.Scan(&k.ID, &k.Account, &k.Fingerprint, &k.UID, &k.Armor, &created); err != nil {
133728e barerepo 1mo
41
return nil, err
133728e barerepo 1mo
43
k.Created = time.Unix(created, 0)
133728e barerepo 1mo
44
out = append(out, k)
133728e barerepo 1mo
46
return out, rows.Err()
133728e barerepo 1mo
49
// AllGPGKeys is every key on the server, because one keyring verifies every commit.
133728e barerepo 1mo
50
func (db *DB) AllGPGKeys(ctx context.Context) ([]GPGKey, error) {
133728e barerepo 1mo
51
rows, err := db.QueryContext(ctx,
133728e barerepo 1mo
52
`SELECT id, account, fingerprint, uid, armor, created_at FROM gpgkeys ORDER BY id`)
133728e barerepo 1mo
53
if err != nil {
133728e barerepo 1mo
54
return nil, err
133728e barerepo 1mo
56
defer rows.Close()
133728e barerepo 1mo
57
var out []GPGKey
133728e barerepo 1mo
58
for rows.Next() {
133728e barerepo 1mo
59
var k GPGKey
133728e barerepo 1mo
60
var created int64
133728e barerepo 1mo
61
if err := rows.Scan(&k.ID, &k.Account, &k.Fingerprint, &k.UID, &k.Armor, &created); err != nil {
133728e barerepo 1mo
62
return nil, err
133728e barerepo 1mo
64
k.Created = time.Unix(created, 0)
133728e barerepo 1mo
65
out = append(out, k)
133728e barerepo 1mo
67
return out, rows.Err()
133728e barerepo 1mo
70
// DeleteGPGKey revokes one key, and only its own account may.
133728e barerepo 1mo
71
func (db *DB) DeleteGPGKey(ctx context.Context, account string, id int64) error {
133728e barerepo 1mo
72
res, err := db.ExecContext(ctx, `DELETE FROM gpgkeys WHERE id = ? AND account = ?`, id, account)
133728e barerepo 1mo
73
if err != nil {
133728e barerepo 1mo
74
return err
133728e barerepo 1mo
76
if n, _ := res.RowsAffected(); n == 0 {
133728e barerepo 1mo
77
return errors.New("no such key")
133728e barerepo 1mo
79
return nil
133728e barerepo 1mo
82
// AccountForGPGKey names who published a key, which is the only claim about a signature barerepo owns.
133728e barerepo 1mo
83
func (db *DB) AccountForGPGKey(ctx context.Context, fingerprint string) (string, error) {
133728e barerepo 1mo
84
var account string
133728e barerepo 1mo
85
err := db.QueryRowContext(ctx,
133728e barerepo 1mo
86
`SELECT account FROM gpgkeys WHERE fingerprint = ?`, fingerprint).Scan(&account)
133728e barerepo 1mo
87
return account, err