687 lines
17 KiB
Go
687 lines
17 KiB
Go
package openapi
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/danielgtaylor/huma/v2"
|
|
"github.com/davecgh/go-spew/spew"
|
|
"github.com/dgraph-io/badger/v4"
|
|
"math"
|
|
"net/http"
|
|
"orly.dev/pkg/app/relay/helpers"
|
|
"orly.dev/pkg/encoders/event"
|
|
"orly.dev/pkg/encoders/filter"
|
|
"orly.dev/pkg/encoders/filters"
|
|
"orly.dev/pkg/encoders/kind"
|
|
"orly.dev/pkg/encoders/tag"
|
|
"orly.dev/pkg/encoders/timestamp"
|
|
"orly.dev/pkg/protocol/auth"
|
|
"orly.dev/pkg/utils/context"
|
|
"orly.dev/pkg/utils/log"
|
|
"orly.dev/pkg/utils/pointers"
|
|
)
|
|
|
|
type Filter struct {
|
|
Ids []string `json:"ids,omitempty"`
|
|
Kinds []int `json:"kinds,omitempty"`
|
|
Authors []string `json:"authors,omitempty"`
|
|
Tag_a []string `json:"#a,omitempty"`
|
|
Tag_b []string `json:"#b,omitempty"`
|
|
Tag_c []string `json:"#c,omitempty"`
|
|
Tag_d []string `json:"#d,omitempty"`
|
|
Tag_e []string `json:"#e,omitempty"`
|
|
Tag_f []string `json:"#f,omitempty"`
|
|
Tag_g []string `json:"#g,omitempty"`
|
|
Tag_h []string `json:"#h,omitempty"`
|
|
Tag_i []string `json:"#i,omitempty"`
|
|
Tag_j []string `json:"#j,omitempty"`
|
|
Tag_k []string `json:"#k,omitempty"`
|
|
Tag_l []string `json:"#l,omitempty"`
|
|
Tag_m []string `json:"#m,omitempty"`
|
|
Tag_n []string `json:"#n,omitempty"`
|
|
Tag_o []string `json:"#o,omitempty"`
|
|
Tag_p []string `json:"#p,omitempty"`
|
|
Tag_q []string `json:"#q,omitempty"`
|
|
Tag_r []string `json:"#r,omitempty"`
|
|
Tag_s []string `json:"#s,omitempty"`
|
|
Tag_t []string `json:"#t,omitempty"`
|
|
Tag_u []string `json:"#u,omitempty"`
|
|
Tag_v []string `json:"#v,omitempty"`
|
|
Tag_w []string `json:"#w,omitempty"`
|
|
Tag_x []string `json:"#x,omitempty"`
|
|
Tag_y []string `json:"#y,omitempty"`
|
|
Tag_z []string `json:"#z,omitempty"`
|
|
Tag_A []string `json:"#A,omitempty"`
|
|
Tag_B []string `json:"#B,omitempty"`
|
|
Tag_C []string `json:"#C,omitempty"`
|
|
Tag_D []string `json:"#D,omitempty"`
|
|
Tag_E []string `json:"#E,omitempty"`
|
|
Tag_F []string `json:"#F,omitempty"`
|
|
Tag_G []string `json:"#G,omitempty"`
|
|
Tag_H []string `json:"#H,omitempty"`
|
|
Tag_I []string `json:"#I,omitempty"`
|
|
Tag_J []string `json:"#J,omitempty"`
|
|
Tag_K []string `json:"#K,omitempty"`
|
|
Tag_L []string `json:"#L,omitempty"`
|
|
Tag_M []string `json:"#M,omitempty"`
|
|
Tag_N []string `json:"#N,omitempty"`
|
|
Tag_O []string `json:"#O,omitempty"`
|
|
Tag_P []string `json:"#P,omitempty"`
|
|
Tag_Q []string `json:"#Q,omitempty"`
|
|
Tag_R []string `json:"#R,omitempty"`
|
|
Tag_S []string `json:"#S,omitempty"`
|
|
Tag_T []string `json:"#T,omitempty"`
|
|
Tag_U []string `json:"#U,omitempty"`
|
|
Tag_V []string `json:"#V,omitempty"`
|
|
Tag_W []string `json:"#W,omitempty"`
|
|
Tag_X []string `json:"#X,omitempty"`
|
|
Tag_Y []string `json:"#Y,omitempty"`
|
|
Tag_Z []string `json:"#Z,omitempty"`
|
|
Since *int64 `json:"since,omitempty"`
|
|
Until *int64 `json:"until,omitempty"`
|
|
Search *string `json:"search,omitempty"`
|
|
Limit *int `json:"limit,omitempty"`
|
|
}
|
|
|
|
func (f *Filter) ToFilter() (ff *filter.F) {
|
|
ff = filter.New()
|
|
|
|
// Convert Ids
|
|
if f.Ids != nil && len(f.Ids) > 0 {
|
|
for _, id := range f.Ids {
|
|
ff.Ids.Append([]byte(id))
|
|
}
|
|
}
|
|
if f.Kinds != nil && len(f.Kinds) > 0 {
|
|
for _, k := range f.Kinds {
|
|
ff.Kinds.K = append(ff.Kinds.K, kind.New(uint16(k)))
|
|
}
|
|
}
|
|
if f.Authors != nil && len(f.Authors) > 0 {
|
|
for _, author := range f.Authors {
|
|
ff.Authors.Append([]byte(author))
|
|
}
|
|
}
|
|
if f.Since != nil {
|
|
ts := timestamp.New(*f.Since)
|
|
ff.Since = ts
|
|
}
|
|
if f.Until != nil {
|
|
ts := timestamp.New(*f.Until)
|
|
ff.Until = ts
|
|
}
|
|
if f.Search != nil {
|
|
ff.Search = []byte(*f.Search)
|
|
}
|
|
if f.Limit != nil {
|
|
u := uint(*f.Limit)
|
|
ff.Limit = &u
|
|
}
|
|
if f.Tag_a != nil && len(f.Tag_a) > 0 {
|
|
t := tag.New("#a")
|
|
for _, v := range f.Tag_a {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_b != nil && len(f.Tag_b) > 0 {
|
|
t := tag.New("#b")
|
|
for _, v := range f.Tag_b {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_c != nil && len(f.Tag_c) > 0 {
|
|
t := tag.New("#c")
|
|
for _, v := range f.Tag_c {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_d != nil && len(f.Tag_d) > 0 {
|
|
t := tag.New("#d")
|
|
for _, v := range f.Tag_d {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_e != nil && len(f.Tag_e) > 0 {
|
|
t := tag.New("#e")
|
|
for _, v := range f.Tag_e {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_f != nil && len(f.Tag_f) > 0 {
|
|
t := tag.New("#f")
|
|
for _, v := range f.Tag_f {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_g != nil && len(f.Tag_g) > 0 {
|
|
t := tag.New("#g")
|
|
for _, v := range f.Tag_g {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_h != nil && len(f.Tag_h) > 0 {
|
|
t := tag.New("#h")
|
|
for _, v := range f.Tag_h {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_i != nil && len(f.Tag_i) > 0 {
|
|
t := tag.New("#i")
|
|
for _, v := range f.Tag_i {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_j != nil && len(f.Tag_j) > 0 {
|
|
t := tag.New("#j")
|
|
for _, v := range f.Tag_j {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_k != nil && len(f.Tag_k) > 0 {
|
|
t := tag.New("#k")
|
|
for _, v := range f.Tag_k {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_l != nil && len(f.Tag_l) > 0 {
|
|
t := tag.New("#l")
|
|
for _, v := range f.Tag_l {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_m != nil && len(f.Tag_m) > 0 {
|
|
t := tag.New("#m")
|
|
for _, v := range f.Tag_m {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_n != nil && len(f.Tag_n) > 0 {
|
|
t := tag.New("#n")
|
|
for _, v := range f.Tag_n {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_o != nil && len(f.Tag_o) > 0 {
|
|
t := tag.New("#o")
|
|
for _, v := range f.Tag_o {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_p != nil && len(f.Tag_p) > 0 {
|
|
t := tag.New("#p")
|
|
for _, v := range f.Tag_p {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_q != nil && len(f.Tag_q) > 0 {
|
|
t := tag.New("#q")
|
|
for _, v := range f.Tag_q {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_r != nil && len(f.Tag_r) > 0 {
|
|
t := tag.New("#r")
|
|
for _, v := range f.Tag_r {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_s != nil && len(f.Tag_s) > 0 {
|
|
t := tag.New("#s")
|
|
for _, v := range f.Tag_s {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_t != nil && len(f.Tag_t) > 0 {
|
|
t := tag.New("#t")
|
|
for _, v := range f.Tag_t {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_u != nil && len(f.Tag_u) > 0 {
|
|
t := tag.New("#u")
|
|
for _, v := range f.Tag_u {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_v != nil && len(f.Tag_v) > 0 {
|
|
t := tag.New("#v")
|
|
for _, v := range f.Tag_v {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_w != nil && len(f.Tag_w) > 0 {
|
|
t := tag.New("#w")
|
|
for _, v := range f.Tag_w {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_x != nil && len(f.Tag_x) > 0 {
|
|
t := tag.New("#x")
|
|
for _, v := range f.Tag_x {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_y != nil && len(f.Tag_y) > 0 {
|
|
t := tag.New("#y")
|
|
for _, v := range f.Tag_y {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_z != nil && len(f.Tag_z) > 0 {
|
|
t := tag.New("#z")
|
|
for _, v := range f.Tag_z {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_A != nil && len(f.Tag_A) > 0 {
|
|
t := tag.New("#A")
|
|
for _, v := range f.Tag_A {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_B != nil && len(f.Tag_B) > 0 {
|
|
t := tag.New("#B")
|
|
for _, v := range f.Tag_B {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_C != nil && len(f.Tag_C) > 0 {
|
|
t := tag.New("#C")
|
|
for _, v := range f.Tag_C {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_D != nil && len(f.Tag_D) > 0 {
|
|
t := tag.New("#D")
|
|
for _, v := range f.Tag_D {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_E != nil && len(f.Tag_E) > 0 {
|
|
t := tag.New("#E")
|
|
for _, v := range f.Tag_E {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_F != nil && len(f.Tag_F) > 0 {
|
|
t := tag.New("#F")
|
|
for _, v := range f.Tag_F {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_G != nil && len(f.Tag_G) > 0 {
|
|
t := tag.New("#G")
|
|
for _, v := range f.Tag_G {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_H != nil && len(f.Tag_H) > 0 {
|
|
t := tag.New("#H")
|
|
for _, v := range f.Tag_H {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_I != nil && len(f.Tag_I) > 0 {
|
|
t := tag.New("#I")
|
|
for _, v := range f.Tag_I {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_J != nil && len(f.Tag_J) > 0 {
|
|
t := tag.New("#J")
|
|
for _, v := range f.Tag_J {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_K != nil && len(f.Tag_K) > 0 {
|
|
t := tag.New("#K")
|
|
for _, v := range f.Tag_K {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_L != nil && len(f.Tag_L) > 0 {
|
|
t := tag.New("#L")
|
|
for _, v := range f.Tag_L {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_M != nil && len(f.Tag_M) > 0 {
|
|
t := tag.New("#M")
|
|
for _, v := range f.Tag_M {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_N != nil && len(f.Tag_N) > 0 {
|
|
t := tag.New("#N")
|
|
for _, v := range f.Tag_N {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_O != nil && len(f.Tag_O) > 0 {
|
|
t := tag.New("#O")
|
|
for _, v := range f.Tag_O {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_P != nil && len(f.Tag_P) > 0 {
|
|
t := tag.New("#P")
|
|
for _, v := range f.Tag_P {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_Q != nil && len(f.Tag_Q) > 0 {
|
|
t := tag.New("#Q")
|
|
for _, v := range f.Tag_Q {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_R != nil && len(f.Tag_R) > 0 {
|
|
t := tag.New("#R")
|
|
for _, v := range f.Tag_R {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_S != nil && len(f.Tag_S) > 0 {
|
|
t := tag.New("#S")
|
|
for _, v := range f.Tag_S {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_T != nil && len(f.Tag_T) > 0 {
|
|
t := tag.New("#T")
|
|
for _, v := range f.Tag_T {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_U != nil && len(f.Tag_U) > 0 {
|
|
t := tag.New("#U")
|
|
for _, v := range f.Tag_U {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_V != nil && len(f.Tag_V) > 0 {
|
|
t := tag.New("#V")
|
|
for _, v := range f.Tag_V {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_W != nil && len(f.Tag_W) > 0 {
|
|
t := tag.New("#W")
|
|
for _, v := range f.Tag_W {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_X != nil && len(f.Tag_X) > 0 {
|
|
t := tag.New("#X")
|
|
for _, v := range f.Tag_X {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_Y != nil && len(f.Tag_Y) > 0 {
|
|
t := tag.New("#Y")
|
|
for _, v := range f.Tag_Y {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
if f.Tag_Z != nil && len(f.Tag_Z) > 0 {
|
|
t := tag.New("#Z")
|
|
for _, v := range f.Tag_Z {
|
|
t.Append([]byte(v))
|
|
}
|
|
ff.Tags.AppendTags(t)
|
|
}
|
|
return
|
|
}
|
|
|
|
var exampleSince int64 = 1753432853
|
|
var exampleUntil int64 = 1753462853
|
|
var exampleLimit int = 20
|
|
var created_atMinimum float64 = 0
|
|
var created_atMaximum float64 = float64(math.MaxInt64)
|
|
var limitMinimum float64 = 0
|
|
var limitMaximum float64 = float64(math.MaxUint64)
|
|
|
|
var EventsBody = &huma.RequestBody{
|
|
Description: "array of nostr events",
|
|
Content: map[string]*huma.MediaType{
|
|
"application/json": {
|
|
Schema: &huma.Schema{
|
|
Type: huma.TypeObject,
|
|
Examples: []any{
|
|
Filter{
|
|
Kinds: []int{0, 1},
|
|
Authors: []string{
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
},
|
|
Tag_e: []string{
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
},
|
|
Since: &exampleSince,
|
|
Until: &exampleUntil,
|
|
Limit: &exampleLimit,
|
|
},
|
|
Filter{
|
|
Ids: []string{
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
"deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008deadbeefcafe8008",
|
|
},
|
|
},
|
|
},
|
|
Properties: map[string]*huma.Schema{
|
|
"ids": {
|
|
Type: huma.TypeArray,
|
|
Description: "list of event IDs to search for (if present, all other fields are excluded)",
|
|
Items: &huma.Schema{
|
|
Type: huma.TypeString,
|
|
},
|
|
},
|
|
"kinds": {
|
|
Type: huma.TypeArray,
|
|
Description: "list of event kinds to search for",
|
|
Items: &huma.Schema{
|
|
Type: huma.TypeInteger,
|
|
},
|
|
},
|
|
"authors": {
|
|
Type: huma.TypeArray,
|
|
Description: "list of pubkeys to search for",
|
|
Items: &huma.Schema{
|
|
Type: huma.TypeString,
|
|
},
|
|
},
|
|
"^#[a-zA-Z]$": {
|
|
Type: huma.TypeArray,
|
|
Description: "list of tag values to search for",
|
|
Items: &huma.Schema{
|
|
Type: huma.TypeString,
|
|
},
|
|
},
|
|
"since": {
|
|
Type: huma.TypeInteger,
|
|
Description: "earliest (smallest, inclusive) created_at value for events",
|
|
Minimum: &created_atMinimum,
|
|
Maximum: &created_atMaximum,
|
|
},
|
|
"until": {
|
|
Type: huma.TypeInteger,
|
|
Description: "latest (largest, inclusive) created_at value for events",
|
|
Minimum: &created_atMinimum,
|
|
Maximum: &created_atMaximum,
|
|
},
|
|
"limit": {
|
|
Type: huma.TypeInteger,
|
|
Description: "maximum number of events to return (newest first, reverse chronological order)",
|
|
Minimum: &limitMinimum,
|
|
Maximum: &limitMaximum,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type EventsInput struct {
|
|
Auth string `header:"Authorization" doc:"nostr nip-98 (and expiring variant)" required:"false"`
|
|
Accept string `header:"Accept" default:"application/nostr+json"`
|
|
Body *Filter `doc:"filter JSON (standard NIP-01 filter syntax)"`
|
|
}
|
|
|
|
type EventsOutput struct {
|
|
Body []*event.J
|
|
}
|
|
|
|
// RegisterEvents is the implementation of the HTTP API Events method.
|
|
//
|
|
// This method returns the results of a single filter query, filtered by
|
|
// privilege.
|
|
func (x *Operations) RegisterEvents(api huma.API) {
|
|
name := "Events"
|
|
description := `Query for events using a standard NIP-01 filter (only allows one filter)
|
|
|
|
Returns events as a JSON array of event objects.`
|
|
path := x.path + "/events"
|
|
scopes := []string{"user", "read"}
|
|
method := http.MethodPost
|
|
huma.Register(
|
|
api, huma.Operation{
|
|
OperationID: name,
|
|
Summary: name,
|
|
Path: path,
|
|
Method: method,
|
|
Tags: []string{"events"},
|
|
RequestBody: EventsBody,
|
|
Description: helpers.GenerateDescription(description, scopes),
|
|
Security: []map[string][]string{{"auth": scopes}},
|
|
}, func(ctx context.T, input *EventsInput) (
|
|
output *EventsOutput, err error,
|
|
) {
|
|
r := ctx.Value("http-request").(*http.Request)
|
|
remote := helpers.GetRemoteFromReq(r)
|
|
var authed, super bool
|
|
var pubkey []byte
|
|
// if auth is required and not public readable, the request is not
|
|
// authorized.
|
|
if x.I.AuthRequired() && !x.I.PublicReadable() {
|
|
authed, pubkey, super = x.UserAuth(r, remote)
|
|
if !authed {
|
|
err = huma.Error401Unauthorized("Not Authorized")
|
|
return
|
|
}
|
|
}
|
|
f := filter.New()
|
|
var rem []byte
|
|
log.T.C(func() string { return spew.Sdump(input) })
|
|
if len(rem) > 0 {
|
|
log.I.F("extra '%s'", rem)
|
|
}
|
|
var accept bool
|
|
allowed, accept, _ := x.AcceptReq(
|
|
x.Context(), r, filters.New(f), pubkey, remote,
|
|
)
|
|
if !accept {
|
|
err = huma.Error401Unauthorized("Not Authorized for query")
|
|
return
|
|
}
|
|
var events event.S
|
|
for _, ff := range allowed.F {
|
|
// var i uint
|
|
if pointers.Present(ff.Limit) {
|
|
if *ff.Limit == 0 {
|
|
continue
|
|
}
|
|
}
|
|
if events, err = x.Storage().QueryEvents(
|
|
x.Context(), ff,
|
|
); err != nil {
|
|
if errors.Is(err, badger.ErrDBClosed) {
|
|
return
|
|
}
|
|
continue
|
|
}
|
|
// filter events the authed pubkey is not privileged to fetch.
|
|
// relay replicas don't have this limitation.
|
|
if x.AuthRequired() && len(pubkey) > 0 && !super {
|
|
var tmp event.S
|
|
for _, ev := range events {
|
|
if !auth.CheckPrivilege(pubkey, ev) {
|
|
log.W.F(
|
|
"not privileged: client pubkey '%0x' event pubkey '%0x' kind %s privileged: %v",
|
|
pubkey, ev.Pubkey,
|
|
ev.Kind.Name(),
|
|
ev.Kind.IsPrivileged(),
|
|
)
|
|
continue
|
|
}
|
|
tmp = append(tmp, ev)
|
|
}
|
|
// cap the number of events to 512 to stop excessively large
|
|
// response.
|
|
if len(events) > 512 {
|
|
break
|
|
}
|
|
events = tmp
|
|
}
|
|
}
|
|
output = &EventsOutput{}
|
|
for _, ev := range events {
|
|
output.Body = append(output.Body, ev.ToEventJ())
|
|
}
|
|
return
|
|
},
|
|
)
|
|
}
|