tinyrelayfile
tinyrelay/internal/records/management.go/

internal/records/management.go raw
1package records
2
3import (
4 "context"
5 "encoding/json"
6 "errors"
7 "fmt"
8 "time"
9
10 "github.com/FelineStateMachine/tinyrelay/internal/policy"
11 "github.com/FelineStateMachine/tinyrelay/internal/storage"
12)
13
14// Execute covers record-owned management operations.
15func (s *Service) Execute(ctx context.Context, actor, method string, params []json.RawMessage) (any, error) {
16 p := s.policy()
17 if actor != "" && actor != p.Owner {
18 return nil, errors.New("restricted: owner record operation")
19 }
20 now := time.Now().Unix()
21 _ = s.audit(ctx, actor, method, "", "", now)
22 switch method {
23 case "successionstatus":
24 var seen, warning, last int64
25 _ = s.store.GetSetting(ctx, "records.owner_seen", &seen)
26 _ = s.store.GetSetting(ctx, "records.succession_warning", &warning)
27 _ = s.store.GetSetting(ctx, "records.succession_notify", &last)
28 var log []successionLog
29 _ = s.store.GetSetting(ctx, "records.succession_log", &log)
30 var warningState any
31 if warning > 0 {
32 warningState = map[string]any{"since": warning, "lastNotified": last}
33 }
34 return map[string]any{"ownerSeenAt": seen, "warning": warningState, "handoverAt": func() int64 {
35 if warning > 0 {
36 return warning + 30*86400
37 }
38 if p.Succession != nil {
39 return seen + int64(p.Succession.AfterDays)*86400 + 30*86400
40 }
41 return 0
42 }(), "log": log, "succession": p.Succession}, nil
43 case "setsuccession":
44 if len(params) == 0 {
45 return nil, errors.New("invalid: missing succession")
46 }
47 var v policy.Succession
48 if err := json.Unmarshal(params[0], &v); err != nil {
49 return nil, err
50 }
51 if v.AfterDays != 90 && v.AfterDays != 180 && v.AfterDays != 365 {
52 return nil, errors.New("invalid: succession delay")
53 }
54 if s.setPolicy != nil {
55 next := p
56 next.Succession = &v
57 next.Notify.Succession = true
58 if err := s.setPolicy(next); err != nil {
59 return nil, err
60 }
61 }
62 return v, s.store.PutSetting(ctx, "records.succession", v)
63 case "clearsuccession":
64 if s.setPolicy != nil {
65 next := p
66 next.Succession = nil
67 next.Notify.Succession = false
68 if err := s.setPolicy(next); err != nil {
69 return nil, err
70 }
71 }
72 return true, s.store.PutSetting(ctx, "records.succession", nil)
73 case "listpins":
74 return s.store.DB().QueryContext(ctx, `SELECT ref FROM records_pins ORDER BY position`)
75 case "pinevent", "unpinevent":
76 if len(params) == 0 {
77 return nil, errors.New("invalid: missing pin")
78 }
79 var ref string
80 if err := json.Unmarshal(params[0], &ref); err != nil {
81 return nil, err
82 }
83 var refs []string
84 rows, _ := s.store.DB().QueryContext(ctx, `SELECT ref FROM records_pins ORDER BY position`)
85 for rows.Next() {
86 var x string
87 _ = rows.Scan(&x)
88 if x != ref {
89 refs = append(refs, x)
90 }
91 }
92 _ = rows.Close()
93 if method == "pinevent" {
94 refs = append(refs, ref)
95 }
96 return s.SetPins(ctx, refs, now)
97 case "listviews":
98 return s.ViewSummaries(ctx)
99 case "notifytest":
100 return true, s.notify(ctx, "test", p.Owner, p.Owner, now)
101 case "notifystatus":
102 return map[string]any{"reports": p.Notify.Reports, "jobs": p.Notify.Jobs, "succession": p.Notify.Succession, "digest": p.Notify.Digest}, nil
103 default:
104 return nil, fmt.Errorf("unsupported: records method %q", method)
105 }
106}
107
108func (s *Service) Clock(ctx context.Context) (int64, error) {
109 var v int64
110 err := s.store.GetSetting(ctx, "records.clock", &v)
111 return v, err
112}
113
114func parseIntSetting(ctx context.Context, s *storage.Store, key string) int64 {
115 var v int64
116 _ = s.GetSetting(ctx, key, &v)
117 return v
118}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs