1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package revocation
import (
"context"
"errors"
"fmt"
)
type DenyState string
const (
DenyFirstLogin DenyState = "FirstLogin"
DenyGranted DenyState = "Granted"
DenyRevoked DenyState = "Revoked"
DenyRecordMissing DenyState = "RecordMissing"
)
type Deny interface {
Lookup(ctx context.Context, did string) (DenyState, error)
}
var (
ErrRevoked = errors.New("revocation: identity is revoked")
ErrDenyRecordMissing = errors.New("revocation: account identity record is missing")
ErrDenyUnreadable = errors.New("revocation: deny record unreadable")
ErrNoDID = errors.New("revocation: no did")
)
type Permit interface {
Admitted() string
}
type permit struct{ did string }
func (p *permit) Admitted() string { return p.did }
func Admit(ctx context.Context, d Deny, did string) (Permit, error) {
if did == "" {
return nil, ErrNoDID
}
st, err := d.Lookup(ctx, did)
switch {
case err != nil:
return nil, fmt.Errorf("%w: %s: %w", ErrDenyUnreadable, did, err)
case st == DenyRevoked:
return nil, fmt.Errorf("%w: %s", ErrRevoked, did)
case st == DenyRecordMissing:
return nil, fmt.Errorf("%w: %s", ErrDenyRecordMissing, did)
case st == DenyGranted, st == DenyFirstLogin:
return &permit{did: did}, nil
default:
return nil, fmt.Errorf("%w: %s: unknown deny state %q", ErrDenyUnreadable, did, st)
}
}
func CreateOnRead(ctx context.Context, d Deny, did string, create func(context.Context) error) (Permit, error) {
p, err := Admit(ctx, d, did)
if err != nil {
return nil, err
}
if err := create(ctx); err != nil {
return nil, err
}
return p, nil
}