service.go raw
1 package server
2
3 import (
4 "context"
5 "encoding/hex"
6 "errors"
7 "time"
8
9 "google.golang.org/grpc/codes"
10 "google.golang.org/grpc/status"
11 "next.orly.dev/pkg/lol/log"
12
13 "next.orly.dev/pkg/acl"
14 "next.orly.dev/pkg/database"
15 orlyaclv1 "next.orly.dev/pkg/proto/orlyacl/v1"
16 orlydbv1 "next.orly.dev/pkg/proto/orlydb/v1"
17 )
18
19 // ACLService implements the orlyaclv1.ACLServiceServer interface.
20 type ACLService struct {
21 orlyaclv1.UnimplementedACLServiceServer
22 cfg *Config
23 db database.Database
24 }
25
26 // NewACLService creates a new ACL service.
27 func NewACLService(cfg *Config, db database.Database) *ACLService {
28 return &ACLService{
29 cfg: cfg,
30 db: db,
31 }
32 }
33
34 // === Core ACL Methods ===
35
36 func (s *ACLService) GetAccessLevel(ctx context.Context, req *orlyaclv1.AccessLevelRequest) (*orlyaclv1.AccessLevelResponse, error) {
37 level := acl.Registry.GetAccessLevel(req.Pubkey, req.Address)
38 return &orlyaclv1.AccessLevelResponse{Level: level}, nil
39 }
40
41 func (s *ACLService) CheckPolicy(ctx context.Context, req *orlyaclv1.PolicyCheckRequest) (*orlyaclv1.PolicyCheckResponse, error) {
42 ev := orlydbv1.ProtoToEvent(req.Event)
43 allowed, err := acl.Registry.CheckPolicy(ev)
44 resp := &orlyaclv1.PolicyCheckResponse{Allowed: allowed}
45 if err != nil {
46 resp.Error = err.Error()
47 }
48 return resp, nil
49 }
50
51 func (s *ACLService) GetACLInfo(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ACLInfoResponse, error) {
52 name, description, documentation := acl.Registry.GetACLInfo()
53 return &orlyaclv1.ACLInfoResponse{
54 Name: name,
55 Description: description,
56 Documentation: documentation,
57 }, nil
58 }
59
60 func (s *ACLService) GetMode(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ModeResponse, error) {
61 return &orlyaclv1.ModeResponse{Mode: acl.Registry.Type()}, nil
62 }
63
64 func (s *ACLService) Ready(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ReadyResponse, error) {
65 // Check if database is ready
66 select {
67 case <-s.db.Ready():
68 return &orlyaclv1.ReadyResponse{Ready: true}, nil
69 default:
70 return &orlyaclv1.ReadyResponse{Ready: false}, nil
71 }
72 }
73
74 // === Follows ACL Methods ===
75
76 func (s *ACLService) GetThrottleDelay(ctx context.Context, req *orlyaclv1.ThrottleDelayRequest) (*orlyaclv1.ThrottleDelayResponse, error) {
77 // Get the active ACL and check if it's Follows
78 for _, i := range acl.Registry.ACLs() {
79 if i.Type() == "follows" {
80 if follows, ok := i.(*acl.Follows); ok {
81 delay := follows.GetThrottleDelay(req.Pubkey, req.Ip)
82 return &orlyaclv1.ThrottleDelayResponse{DelayMs: delay.Milliseconds()}, nil
83 }
84 }
85 }
86 return &orlyaclv1.ThrottleDelayResponse{DelayMs: 0}, nil
87 }
88
89 func (s *ACLService) AddFollow(ctx context.Context, req *orlyaclv1.AddFollowRequest) (*orlyaclv1.Empty, error) {
90 acl.Registry.AddFollow(req.Pubkey)
91 return &orlyaclv1.Empty{}, nil
92 }
93
94 func (s *ACLService) GetFollowedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.FollowedPubkeysResponse, error) {
95 for _, i := range acl.Registry.ACLs() {
96 if i.Type() == "follows" {
97 if follows, ok := i.(*acl.Follows); ok {
98 pubkeys := follows.GetFollowedPubkeys()
99 return &orlyaclv1.FollowedPubkeysResponse{Pubkeys: pubkeys}, nil
100 }
101 }
102 }
103 return &orlyaclv1.FollowedPubkeysResponse{}, nil
104 }
105
106 func (s *ACLService) GetAdminRelays(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.AdminRelaysResponse, error) {
107 for _, i := range acl.Registry.ACLs() {
108 if i.Type() == "follows" {
109 if follows, ok := i.(*acl.Follows); ok {
110 urls := follows.AdminRelays()
111 return &orlyaclv1.AdminRelaysResponse{Urls: urls}, nil
112 }
113 }
114 }
115 return &orlyaclv1.AdminRelaysResponse{}, nil
116 }
117
118 // === Managed ACL Methods ===
119
120 func (s *ACLService) BanPubkey(ctx context.Context, req *orlyaclv1.BanPubkeyRequest) (*orlyaclv1.Empty, error) {
121 managed := s.getManagedACL()
122 if managed == nil {
123 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
124 }
125 managedACL := managed.GetManagedACL()
126 if managedACL == nil {
127 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
128 }
129 if err := managedACL.SaveBannedPubkey(req.Pubkey, req.Reason); err != nil {
130 return nil, status.Errorf(codes.Internal, "failed to ban pubkey: %v", err)
131 }
132 return &orlyaclv1.Empty{}, nil
133 }
134
135 func (s *ACLService) UnbanPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) {
136 managed := s.getManagedACL()
137 if managed == nil {
138 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
139 }
140 managedACL := managed.GetManagedACL()
141 if managedACL == nil {
142 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
143 }
144 if err := managedACL.RemoveBannedPubkey(req.Pubkey); err != nil {
145 return nil, status.Errorf(codes.Internal, "failed to unban pubkey: %v", err)
146 }
147 return &orlyaclv1.Empty{}, nil
148 }
149
150 func (s *ACLService) ListBannedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBannedPubkeysResponse, error) {
151 managed := s.getManagedACL()
152 if managed == nil {
153 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
154 }
155 managedACL := managed.GetManagedACL()
156 if managedACL == nil {
157 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
158 }
159 banned, err := managedACL.ListBannedPubkeys()
160 if err != nil {
161 return nil, status.Errorf(codes.Internal, "failed to list banned pubkeys: %v", err)
162 }
163 resp := &orlyaclv1.ListBannedPubkeysResponse{}
164 for _, b := range banned {
165 resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.BannedPubkey{
166 Pubkey: b.Pubkey,
167 Reason: b.Reason,
168 Added: b.Added.Unix(),
169 })
170 }
171 return resp, nil
172 }
173
174 func (s *ACLService) AllowPubkey(ctx context.Context, req *orlyaclv1.AllowPubkeyRequest) (*orlyaclv1.Empty, error) {
175 managed := s.getManagedACL()
176 if managed == nil {
177 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
178 }
179 managedACL := managed.GetManagedACL()
180 if managedACL == nil {
181 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
182 }
183 if err := managedACL.SaveAllowedPubkey(req.Pubkey, req.Reason); err != nil {
184 return nil, status.Errorf(codes.Internal, "failed to allow pubkey: %v", err)
185 }
186 return &orlyaclv1.Empty{}, nil
187 }
188
189 func (s *ACLService) DisallowPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) {
190 managed := s.getManagedACL()
191 if managed == nil {
192 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
193 }
194 managedACL := managed.GetManagedACL()
195 if managedACL == nil {
196 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
197 }
198 if err := managedACL.RemoveAllowedPubkey(req.Pubkey); err != nil {
199 return nil, status.Errorf(codes.Internal, "failed to disallow pubkey: %v", err)
200 }
201 return &orlyaclv1.Empty{}, nil
202 }
203
204 func (s *ACLService) ListAllowedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedPubkeysResponse, error) {
205 managed := s.getManagedACL()
206 if managed == nil {
207 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
208 }
209 managedACL := managed.GetManagedACL()
210 if managedACL == nil {
211 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
212 }
213 allowed, err := managedACL.ListAllowedPubkeys()
214 if err != nil {
215 return nil, status.Errorf(codes.Internal, "failed to list allowed pubkeys: %v", err)
216 }
217 resp := &orlyaclv1.ListAllowedPubkeysResponse{}
218 for _, a := range allowed {
219 resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.AllowedPubkey{
220 Pubkey: a.Pubkey,
221 Reason: a.Reason,
222 Added: a.Added.Unix(),
223 })
224 }
225 return resp, nil
226 }
227
228 func (s *ACLService) BanEvent(ctx context.Context, req *orlyaclv1.BanEventRequest) (*orlyaclv1.Empty, error) {
229 managed := s.getManagedACL()
230 if managed == nil {
231 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
232 }
233 managedACL := managed.GetManagedACL()
234 if managedACL == nil {
235 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
236 }
237 if err := managedACL.SaveBannedEvent(req.EventId, req.Reason); err != nil {
238 return nil, status.Errorf(codes.Internal, "failed to ban event: %v", err)
239 }
240 return &orlyaclv1.Empty{}, nil
241 }
242
243 func (s *ACLService) UnbanEvent(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) {
244 managed := s.getManagedACL()
245 if managed == nil {
246 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
247 }
248 managedACL := managed.GetManagedACL()
249 if managedACL == nil {
250 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
251 }
252 if err := managedACL.RemoveBannedEvent(req.EventId); err != nil {
253 return nil, status.Errorf(codes.Internal, "failed to unban event: %v", err)
254 }
255 return &orlyaclv1.Empty{}, nil
256 }
257
258 func (s *ACLService) ListBannedEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBannedEventsResponse, error) {
259 managed := s.getManagedACL()
260 if managed == nil {
261 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
262 }
263 managedACL := managed.GetManagedACL()
264 if managedACL == nil {
265 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
266 }
267 banned, err := managedACL.ListBannedEvents()
268 if err != nil {
269 return nil, status.Errorf(codes.Internal, "failed to list banned events: %v", err)
270 }
271 resp := &orlyaclv1.ListBannedEventsResponse{}
272 for _, b := range banned {
273 resp.Events = append(resp.Events, &orlyaclv1.BannedEvent{
274 EventId: b.ID,
275 Reason: b.Reason,
276 Added: b.Added.Unix(),
277 })
278 }
279 return resp, nil
280 }
281
282 func (s *ACLService) AllowEvent(ctx context.Context, req *orlyaclv1.BanEventRequest) (*orlyaclv1.Empty, error) {
283 managed := s.getManagedACL()
284 if managed == nil {
285 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
286 }
287 managedACL := managed.GetManagedACL()
288 if managedACL == nil {
289 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
290 }
291 if err := managedACL.SaveAllowedEvent(req.EventId, req.Reason); err != nil {
292 return nil, status.Errorf(codes.Internal, "failed to allow event: %v", err)
293 }
294 return &orlyaclv1.Empty{}, nil
295 }
296
297 func (s *ACLService) DisallowEvent(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) {
298 managed := s.getManagedACL()
299 if managed == nil {
300 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
301 }
302 managedACL := managed.GetManagedACL()
303 if managedACL == nil {
304 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
305 }
306 if err := managedACL.RemoveAllowedEvent(req.EventId); err != nil {
307 return nil, status.Errorf(codes.Internal, "failed to disallow event: %v", err)
308 }
309 return &orlyaclv1.Empty{}, nil
310 }
311
312 func (s *ACLService) ListAllowedEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedEventsResponse, error) {
313 managed := s.getManagedACL()
314 if managed == nil {
315 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
316 }
317 managedACL := managed.GetManagedACL()
318 if managedACL == nil {
319 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
320 }
321 allowed, err := managedACL.ListAllowedEvents()
322 if err != nil {
323 return nil, status.Errorf(codes.Internal, "failed to list allowed events: %v", err)
324 }
325 resp := &orlyaclv1.ListAllowedEventsResponse{}
326 for _, a := range allowed {
327 resp.Events = append(resp.Events, &orlyaclv1.AllowedEvent{
328 EventId: a.ID,
329 Reason: a.Reason,
330 Added: a.Added.Unix(),
331 })
332 }
333 return resp, nil
334 }
335
336 func (s *ACLService) BlockIP(ctx context.Context, req *orlyaclv1.BlockIPRequest) (*orlyaclv1.Empty, error) {
337 managed := s.getManagedACL()
338 if managed == nil {
339 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
340 }
341 managedACL := managed.GetManagedACL()
342 if managedACL == nil {
343 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
344 }
345 if err := managedACL.SaveBlockedIP(req.Ip, req.Reason); err != nil {
346 return nil, status.Errorf(codes.Internal, "failed to block IP: %v", err)
347 }
348 return &orlyaclv1.Empty{}, nil
349 }
350
351 func (s *ACLService) UnblockIP(ctx context.Context, req *orlyaclv1.IPRequest) (*orlyaclv1.Empty, error) {
352 managed := s.getManagedACL()
353 if managed == nil {
354 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
355 }
356 managedACL := managed.GetManagedACL()
357 if managedACL == nil {
358 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
359 }
360 if err := managedACL.RemoveBlockedIP(req.Ip); err != nil {
361 return nil, status.Errorf(codes.Internal, "failed to unblock IP: %v", err)
362 }
363 return &orlyaclv1.Empty{}, nil
364 }
365
366 func (s *ACLService) ListBlockedIPs(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBlockedIPsResponse, error) {
367 managed := s.getManagedACL()
368 if managed == nil {
369 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
370 }
371 managedACL := managed.GetManagedACL()
372 if managedACL == nil {
373 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
374 }
375 blocked, err := managedACL.ListBlockedIPs()
376 if err != nil {
377 return nil, status.Errorf(codes.Internal, "failed to list blocked IPs: %v", err)
378 }
379 resp := &orlyaclv1.ListBlockedIPsResponse{}
380 for _, b := range blocked {
381 resp.Ips = append(resp.Ips, &orlyaclv1.BlockedIP{
382 Ip: b.IP,
383 Reason: b.Reason,
384 Added: b.Added.Unix(),
385 })
386 }
387 return resp, nil
388 }
389
390 func (s *ACLService) AllowKind(ctx context.Context, req *orlyaclv1.AllowKindRequest) (*orlyaclv1.Empty, error) {
391 managed := s.getManagedACL()
392 if managed == nil {
393 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
394 }
395 managedACL := managed.GetManagedACL()
396 if managedACL == nil {
397 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
398 }
399 if err := managedACL.SaveAllowedKind(int(req.Kind)); err != nil {
400 return nil, status.Errorf(codes.Internal, "failed to allow kind: %v", err)
401 }
402 return &orlyaclv1.Empty{}, nil
403 }
404
405 func (s *ACLService) DisallowKind(ctx context.Context, req *orlyaclv1.KindRequest) (*orlyaclv1.Empty, error) {
406 managed := s.getManagedACL()
407 if managed == nil {
408 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
409 }
410 managedACL := managed.GetManagedACL()
411 if managedACL == nil {
412 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
413 }
414 if err := managedACL.RemoveAllowedKind(int(req.Kind)); err != nil {
415 return nil, status.Errorf(codes.Internal, "failed to disallow kind: %v", err)
416 }
417 return &orlyaclv1.Empty{}, nil
418 }
419
420 func (s *ACLService) ListAllowedKinds(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedKindsResponse, error) {
421 managed := s.getManagedACL()
422 if managed == nil {
423 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
424 }
425 managedACL := managed.GetManagedACL()
426 if managedACL == nil {
427 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available")
428 }
429 kinds, err := managedACL.ListAllowedKinds()
430 if err != nil {
431 return nil, status.Errorf(codes.Internal, "failed to list allowed kinds: %v", err)
432 }
433 resp := &orlyaclv1.ListAllowedKindsResponse{}
434 for _, k := range kinds {
435 resp.Kinds = append(resp.Kinds, int32(k))
436 }
437 return resp, nil
438 }
439
440 func (s *ACLService) UpdatePeerAdmins(ctx context.Context, req *orlyaclv1.UpdatePeerAdminsRequest) (*orlyaclv1.Empty, error) {
441 managed := s.getManagedACL()
442 if managed == nil {
443 return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available")
444 }
445 managed.UpdatePeerAdmins(req.PeerPubkeys)
446 return &orlyaclv1.Empty{}, nil
447 }
448
449 // === Curating ACL Methods ===
450
451 func (s *ACLService) TrustPubkey(ctx context.Context, req *orlyaclv1.TrustPubkeyRequest) (*orlyaclv1.Empty, error) {
452 curating := s.getCuratingACL()
453 if curating == nil {
454 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
455 }
456 if err := curating.TrustPubkey(req.Pubkey, req.Note); err != nil {
457 return nil, status.Errorf(codes.Internal, "failed to trust pubkey: %v", err)
458 }
459 return &orlyaclv1.Empty{}, nil
460 }
461
462 func (s *ACLService) UntrustPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) {
463 curating := s.getCuratingACL()
464 if curating == nil {
465 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
466 }
467 if err := curating.UntrustPubkey(req.Pubkey); err != nil {
468 return nil, status.Errorf(codes.Internal, "failed to untrust pubkey: %v", err)
469 }
470 return &orlyaclv1.Empty{}, nil
471 }
472
473 func (s *ACLService) ListTrustedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListTrustedPubkeysResponse, error) {
474 curating := s.getCuratingACL()
475 if curating == nil {
476 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
477 }
478 curatingACL := curating.GetCuratingACL()
479 if curatingACL == nil {
480 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
481 }
482 trusted, err := curatingACL.ListTrustedPubkeys()
483 if err != nil {
484 return nil, status.Errorf(codes.Internal, "failed to list trusted pubkeys: %v", err)
485 }
486 resp := &orlyaclv1.ListTrustedPubkeysResponse{}
487 for _, t := range trusted {
488 resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.TrustedPubkey{
489 Pubkey: t.Pubkey,
490 Note: t.Note,
491 Added: t.Added.Unix(),
492 })
493 }
494 return resp, nil
495 }
496
497 func (s *ACLService) BlacklistPubkey(ctx context.Context, req *orlyaclv1.BlacklistPubkeyRequest) (*orlyaclv1.Empty, error) {
498 curating := s.getCuratingACL()
499 if curating == nil {
500 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
501 }
502 if err := curating.BlacklistPubkey(req.Pubkey, req.Reason); err != nil {
503 return nil, status.Errorf(codes.Internal, "failed to blacklist pubkey: %v", err)
504 }
505 return &orlyaclv1.Empty{}, nil
506 }
507
508 func (s *ACLService) UnblacklistPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) {
509 curating := s.getCuratingACL()
510 if curating == nil {
511 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
512 }
513 if err := curating.UnblacklistPubkey(req.Pubkey); err != nil {
514 return nil, status.Errorf(codes.Internal, "failed to unblacklist pubkey: %v", err)
515 }
516 return &orlyaclv1.Empty{}, nil
517 }
518
519 func (s *ACLService) ListBlacklistedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBlacklistedPubkeysResponse, error) {
520 curating := s.getCuratingACL()
521 if curating == nil {
522 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
523 }
524 curatingACL := curating.GetCuratingACL()
525 if curatingACL == nil {
526 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
527 }
528 blacklisted, err := curatingACL.ListBlacklistedPubkeys()
529 if err != nil {
530 return nil, status.Errorf(codes.Internal, "failed to list blacklisted pubkeys: %v", err)
531 }
532 resp := &orlyaclv1.ListBlacklistedPubkeysResponse{}
533 for _, b := range blacklisted {
534 resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.BlacklistedPubkey{
535 Pubkey: b.Pubkey,
536 Reason: b.Reason,
537 Added: b.Added.Unix(),
538 })
539 }
540 return resp, nil
541 }
542
543 func (s *ACLService) MarkSpam(ctx context.Context, req *orlyaclv1.MarkSpamRequest) (*orlyaclv1.Empty, error) {
544 curating := s.getCuratingACL()
545 if curating == nil {
546 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
547 }
548 curatingACL := curating.GetCuratingACL()
549 if curatingACL == nil {
550 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
551 }
552 if err := curatingACL.MarkEventAsSpam(req.EventId, req.Pubkey, req.Reason); err != nil {
553 return nil, status.Errorf(codes.Internal, "failed to mark spam: %v", err)
554 }
555 return &orlyaclv1.Empty{}, nil
556 }
557
558 func (s *ACLService) UnmarkSpam(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) {
559 curating := s.getCuratingACL()
560 if curating == nil {
561 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
562 }
563 curatingACL := curating.GetCuratingACL()
564 if curatingACL == nil {
565 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
566 }
567 if err := curatingACL.UnmarkEventAsSpam(req.EventId); err != nil {
568 return nil, status.Errorf(codes.Internal, "failed to unmark spam: %v", err)
569 }
570 return &orlyaclv1.Empty{}, nil
571 }
572
573 func (s *ACLService) ListSpamEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListSpamEventsResponse, error) {
574 curating := s.getCuratingACL()
575 if curating == nil {
576 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
577 }
578 curatingACL := curating.GetCuratingACL()
579 if curatingACL == nil {
580 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
581 }
582 spam, err := curatingACL.ListSpamEvents()
583 if err != nil {
584 return nil, status.Errorf(codes.Internal, "failed to list spam events: %v", err)
585 }
586 resp := &orlyaclv1.ListSpamEventsResponse{}
587 for _, se := range spam {
588 resp.Events = append(resp.Events, &orlyaclv1.SpamEvent{
589 EventId: se.EventID,
590 Pubkey: se.Pubkey,
591 Reason: se.Reason,
592 Added: se.Added.Unix(),
593 })
594 }
595 return resp, nil
596 }
597
598 func (s *ACLService) RateLimitCheck(ctx context.Context, req *orlyaclv1.RateLimitCheckRequest) (*orlyaclv1.RateLimitCheckResponse, error) {
599 curating := s.getCuratingACL()
600 if curating == nil {
601 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
602 }
603 allowed, message, err := curating.RateLimitCheck(req.Pubkey, req.Ip)
604 if err != nil {
605 return nil, status.Errorf(codes.Internal, "failed to check rate limit: %v", err)
606 }
607 return &orlyaclv1.RateLimitCheckResponse{
608 Allowed: allowed,
609 Message: message,
610 }, nil
611 }
612
613 func (s *ACLService) ProcessConfigEvent(ctx context.Context, req *orlyaclv1.ConfigEventRequest) (*orlyaclv1.Empty, error) {
614 curating := s.getCuratingACL()
615 if curating == nil {
616 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
617 }
618 ev := orlydbv1.ProtoToEvent(req.Event)
619 if err := curating.ProcessConfigEvent(ev); err != nil {
620 return nil, status.Errorf(codes.Internal, "failed to process config event: %v", err)
621 }
622 return &orlyaclv1.Empty{}, nil
623 }
624
625 func (s *ACLService) GetCuratingConfig(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.CuratingConfig, error) {
626 curating := s.getCuratingACL()
627 if curating == nil {
628 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
629 }
630 config, err := curating.GetConfig()
631 if err != nil {
632 return nil, status.Errorf(codes.Internal, "failed to get config: %v", err)
633 }
634 resp := &orlyaclv1.CuratingConfig{
635 ConfigEventId: config.ConfigEventID,
636 ConfigPubkey: config.ConfigPubkey,
637 ConfiguredAt: config.ConfiguredAt,
638 DailyLimit: int32(config.DailyLimit),
639 IpDailyLimit: int32(config.IPDailyLimit),
640 FirstBanHours: int32(config.FirstBanHours),
641 SecondBanHours: int32(config.SecondBanHours),
642 KindCategories: config.KindCategories,
643 AllowedRanges: config.AllowedRanges,
644 }
645 for _, k := range config.AllowedKinds {
646 resp.AllowedKinds = append(resp.AllowedKinds, int32(k))
647 }
648 return resp, nil
649 }
650
651 func (s *ACLService) IsCuratingConfigured(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.BoolResponse, error) {
652 curating := s.getCuratingACL()
653 if curating == nil {
654 return &orlyaclv1.BoolResponse{Value: false}, nil
655 }
656 configured, err := curating.IsConfigured()
657 if err != nil {
658 return nil, status.Errorf(codes.Internal, "failed to check if configured: %v", err)
659 }
660 return &orlyaclv1.BoolResponse{Value: configured}, nil
661 }
662
663 func (s *ACLService) ListUnclassifiedUsers(ctx context.Context, req *orlyaclv1.PaginationRequest) (*orlyaclv1.ListUnclassifiedUsersResponse, error) {
664 curating := s.getCuratingACL()
665 if curating == nil {
666 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
667 }
668 curatingACL := curating.GetCuratingACL()
669 if curatingACL == nil {
670 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
671 }
672 // The underlying ListUnclassifiedUsers only takes limit, not offset
673 // We'll request limit+offset and skip the first offset items
674 limit := int(req.Limit)
675 offset := int(req.Offset)
676 if limit == 0 {
677 limit = 100 // Default limit
678 }
679 users, err := curatingACL.ListUnclassifiedUsers(limit + offset)
680 if err != nil {
681 return nil, status.Errorf(codes.Internal, "failed to list unclassified users: %v", err)
682 }
683 // Apply offset
684 if offset > 0 && len(users) > offset {
685 users = users[offset:]
686 } else if offset > 0 {
687 users = nil
688 }
689 // Apply limit
690 if limit > 0 && len(users) > limit {
691 users = users[:limit]
692 }
693 resp := &orlyaclv1.ListUnclassifiedUsersResponse{Total: int32(len(users))}
694 for _, u := range users {
695 resp.Users = append(resp.Users, &orlyaclv1.UnclassifiedUser{
696 Pubkey: u.Pubkey,
697 EventCount: int32(u.EventCount),
698 FirstSeen: u.LastEvent.Format("2006-01-02T15:04:05Z"),
699 })
700 }
701 return resp, nil
702 }
703
704 func (s *ACLService) GetEventsForPubkey(ctx context.Context, req *orlyaclv1.GetEventsForPubkeyRequest) (*orlyaclv1.EventsForPubkeyResponse, error) {
705 curating := s.getCuratingACL()
706 if curating == nil {
707 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
708 }
709 curatingACL := curating.GetCuratingACL()
710 if curatingACL == nil {
711 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
712 }
713 events, total, err := curatingACL.GetEventsForPubkey(req.Pubkey, int(req.Limit), int(req.Offset))
714 if err != nil {
715 return nil, status.Errorf(codes.Internal, "failed to get events for pubkey: %v", err)
716 }
717 resp := &orlyaclv1.EventsForPubkeyResponse{Total: int32(total)}
718 for _, ev := range events {
719 resp.Events = append(resp.Events, &orlyaclv1.EventSummary{
720 Id: ev.ID,
721 Kind: uint32(ev.Kind),
722 Content: []byte(ev.Content),
723 CreatedAt: ev.CreatedAt,
724 })
725 }
726 return resp, nil
727 }
728
729 func (s *ACLService) DeleteEventsForPubkey(ctx context.Context, req *orlyaclv1.DeleteEventsForPubkeyRequest) (*orlyaclv1.DeleteCountResponse, error) {
730 curating := s.getCuratingACL()
731 if curating == nil {
732 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
733 }
734 curatingACL := curating.GetCuratingACL()
735 if curatingACL == nil {
736 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
737 }
738 count, err := curatingACL.DeleteEventsForPubkey(req.Pubkey)
739 if err != nil {
740 return nil, status.Errorf(codes.Internal, "failed to delete events for pubkey: %v", err)
741 }
742 return &orlyaclv1.DeleteCountResponse{Count: int32(count)}, nil
743 }
744
745 func (s *ACLService) ScanAllPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ScanResultResponse, error) {
746 curating := s.getCuratingACL()
747 if curating == nil {
748 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available")
749 }
750 curatingACL := curating.GetCuratingACL()
751 if curatingACL == nil {
752 return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available")
753 }
754 result, err := curatingACL.ScanAllPubkeys()
755 if err != nil {
756 return nil, status.Errorf(codes.Internal, "failed to scan all pubkeys: %v", err)
757 }
758 return &orlyaclv1.ScanResultResponse{
759 TotalPubkeys: int32(result.TotalPubkeys),
760 TotalEvents: int32(result.TotalEvents),
761 }, nil
762 }
763
764 // === Helper Methods ===
765
766 func (s *ACLService) getManagedACL() *acl.Managed {
767 for _, i := range acl.Registry.ACLs() {
768 if i.Type() == "managed" {
769 if managed, ok := i.(*acl.Managed); ok {
770 return managed
771 }
772 }
773 }
774 return nil
775 }
776
777 func (s *ACLService) getCuratingACL() *acl.Curating {
778 for _, i := range acl.Registry.ACLs() {
779 if i.Type() == "curating" {
780 if curating, ok := i.(*acl.Curating); ok {
781 return curating
782 }
783 }
784 }
785 return nil
786 }
787
788 // === Paid ACL Methods ===
789
790 func (s *ACLService) getPaidACL() *acl.Paid {
791 for _, i := range acl.Registry.ACLs() {
792 if i.Type() == "paid" {
793 if paid, ok := i.(*acl.Paid); ok {
794 return paid
795 }
796 }
797 }
798 return nil
799 }
800
801 func (s *ACLService) SubscribePubkey(ctx context.Context, req *orlyaclv1.SubscribeRequest) (*orlyaclv1.Empty, error) {
802 paid := s.getPaidACL()
803 if paid == nil {
804 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
805 }
806 expiresAt := time.Unix(req.ExpiresAt, 0)
807 if err := paid.Subscribe(req.Pubkey, expiresAt, req.InvoiceHash, req.Alias); err != nil {
808 return nil, status.Errorf(codes.Internal, "failed to subscribe: %v", err)
809 }
810 return &orlyaclv1.Empty{}, nil
811 }
812
813 func (s *ACLService) UnsubscribePubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) {
814 paid := s.getPaidACL()
815 if paid == nil {
816 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
817 }
818 if err := paid.Unsubscribe(req.Pubkey); err != nil {
819 return nil, status.Errorf(codes.Internal, "failed to unsubscribe: %v", err)
820 }
821 return &orlyaclv1.Empty{}, nil
822 }
823
824 func (s *ACLService) IsSubscribed(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.BoolResponse, error) {
825 paid := s.getPaidACL()
826 if paid == nil {
827 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
828 }
829 return &orlyaclv1.BoolResponse{Value: paid.IsSubscribed(req.Pubkey)}, nil
830 }
831
832 func (s *ACLService) GetSubscription(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.SubscriptionResponse, error) {
833 paid := s.getPaidACL()
834 if paid == nil {
835 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
836 }
837 sub, err := paid.GetSubscription(req.Pubkey)
838 if err != nil {
839 return nil, status.Errorf(codes.NotFound, "subscription not found: %v", err)
840 }
841 alias, _ := paid.GetAliasByPubkey(req.Pubkey)
842 return &orlyaclv1.SubscriptionResponse{
843 Pubkey: sub.PubkeyHex,
844 Alias: alias,
845 ExpiresAt: sub.ExpiresAt.Unix(),
846 CreatedAt: sub.CreatedAt.Unix(),
847 HasAlias: alias != "",
848 }, nil
849 }
850
851 func (s *ACLService) ClaimAlias(ctx context.Context, req *orlyaclv1.ClaimAliasRequest) (*orlyaclv1.Empty, error) {
852 paid := s.getPaidACL()
853 if paid == nil {
854 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
855 }
856 if err := paid.ClaimAlias(req.Alias, req.Pubkey); err != nil {
857 if errors.Is(err, database.ErrAliasTaken) {
858 return nil, status.Errorf(codes.AlreadyExists, "alias already taken")
859 }
860 return nil, status.Errorf(codes.Internal, "failed to claim alias: %v", err)
861 }
862 return &orlyaclv1.Empty{}, nil
863 }
864
865 func (s *ACLService) GetAliasByPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.AliasResponse, error) {
866 paid := s.getPaidACL()
867 if paid == nil {
868 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
869 }
870 alias, err := paid.GetAliasByPubkey(req.Pubkey)
871 if err != nil {
872 return nil, status.Errorf(codes.Internal, "failed to get alias: %v", err)
873 }
874 return &orlyaclv1.AliasResponse{Alias: alias}, nil
875 }
876
877 func (s *ACLService) GetPubkeyByAlias(ctx context.Context, req *orlyaclv1.AliasRequest) (*orlyaclv1.PubkeyResponse, error) {
878 paid := s.getPaidACL()
879 if paid == nil {
880 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
881 }
882 pubkey, err := paid.GetPubkeyByAlias(req.Alias)
883 if err != nil {
884 return nil, status.Errorf(codes.NotFound, "alias not found: %v", err)
885 }
886 return &orlyaclv1.PubkeyResponse{Pubkey: pubkey}, nil
887 }
888
889 func (s *ACLService) IsAliasTaken(ctx context.Context, req *orlyaclv1.AliasRequest) (*orlyaclv1.BoolResponse, error) {
890 paid := s.getPaidACL()
891 if paid == nil {
892 return nil, status.Errorf(codes.FailedPrecondition, "paid ACL not available")
893 }
894 taken, err := paid.IsAliasTaken(req.Alias)
895 if err != nil {
896 return nil, status.Errorf(codes.Internal, "failed to check alias: %v", err)
897 }
898 return &orlyaclv1.BoolResponse{Value: taken}, nil
899 }
900
901 // Unused but may be needed for debugging
902 var _ = log.T
903 var _ = hex.EncodeToString
904