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
package sweepkcp
import (
"context"
"errors"
"fmt"
"github.com/johnandersen777/socialweb-computer-kcp/internal/revocation"
)
type DenyWriter interface {
WriteDeny(ctx context.Context, did string) error
}
type FanOut interface {
FanOut(ctx context.Context, did string) ([]revocation.ClusterView, error)
}
type Plan struct {
DID string
Why string
Entries []revocation.ReplyEntry
Err error
}
type Revoker struct {
Deny DenyWriter
FanOut FanOut
Erase revocation.Eraser
OnPlan func(Plan)
}
func (r *Revoker) Revoke(ctx context.Context, did, why string) error {
if r.Deny == nil {
return errors.New("sweepkcp: no DenyWriter: the deny's write half has no implementation, " +
"and a sweep that cannot write the deny must not report a revocation")
}
if err := r.Deny.WriteDeny(ctx, did); err != nil {
return fmt.Errorf("sweepkcp: write the deny for %s: %w", did, err)
}
plan := Plan{DID: did, Why: why}
switch {
case r.FanOut == nil:
plan.Err = errors.New("no FanOut: whether the identity's ServiceAccount still exists in " +
"each cluster is not observable in this build, so the fan-out is unwritten by anything " +
"this process can see")
default:
views, err := r.FanOut.FanOut(ctx, did)
if err != nil {
plan.Err = fmt.Errorf("the deny IS written; the fan-out could not be observed: %w", err)
break
}
effects, err := revocation.Erase(ctx, r.Erase, did, revocation.Plan(views))
if err != nil {
plan.Err = err
}
plan.Entries = revocation.Reply(effects)
}
if r.OnPlan != nil {
r.OnPlan(plan)
}
return nil
}