Skip to content

Commit

Permalink
feat: test logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
kehiy committed Jan 30, 2025
1 parent b182bdd commit db35f77
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.60
version: v1.63.4
84 changes: 10 additions & 74 deletions delivery/websocket/event_handler.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package websocket

import (
"context"
"fmt"
"slices"
"strconv"
"strings"
"time"

"github.com/dezh-tech/immortal/infrastructure/redis"
Expand All @@ -14,7 +14,6 @@ import (
"github.com/dezh-tech/immortal/types/filter"
"github.com/dezh-tech/immortal/types/message"
"github.com/gorilla/websocket"
gredis "github.com/redis/go-redis/v9"
)

// handleEvent handles new incoming EVENT messages from client.
Expand Down Expand Up @@ -56,80 +55,18 @@ func (s *Server) handleEvent(conn *websocket.Conn, m message.Message) { //nolint
return
}

qCtx, cancel := context.WithTimeout(context.Background(), s.redis.QueryTimeout)
defer cancel()

pipe := s.redis.Client.Pipeline()

bloomCheckCmd := pipe.BFExists(qCtx, s.redis.BloomFilterName, eID[:])

var whiteListCheckCmd *gredis.BoolCmd

if s.config.Limitation.RestrictedWrites {
whiteListCheckCmd = pipe.CFExists(qCtx, s.redis.WhiteListFilterName, msg.Event.PublicKey)
}

blackListCheckCmd := pipe.CFExists(qCtx, s.redis.BlackListFilterName, msg.Event.PublicKey)

_, err := pipe.Exec(qCtx)
if err != nil {
logger.Error("checking bloom filter", "err", err.Error())
}

exists, err := bloomCheckCmd.Result()
if err != nil {
okm := message.MakeOK(false, msg.Event.ID, "error: internal error")
_ = conn.WriteMessage(1, okm)

status = serverFail

return
}

if exists {
okm := message.MakeOK(false, msg.Event.ID, "duplicate: this event is already received.")
_ = conn.WriteMessage(1, okm)

return
}

isBlackListed, err := blackListCheckCmd.Result()
if err != nil {
okm := message.MakeOK(false, msg.Event.ID, "error: internal error")
_ = conn.WriteMessage(1, okm)

status = serverFail

return
}
if isBlackListed {
okm := message.MakeOK(false, msg.Event.ID, "blocked: pubkey is blocked, contact support for more details.")
if err := s.redis.CheckAcceptability(s.config.Limitation.RestrictedWrites,
eID[:], msg.Event.PublicKey); err != nil {
okm := message.MakeOK(false, msg.Event.ID, err.Error())
_ = conn.WriteMessage(1, okm)

status = limitsFail

return
}

if s.config.Limitation.RestrictedWrites {
isWhiteListed, err := whiteListCheckCmd.Result()
if err != nil {
okm := message.MakeOK(false, msg.Event.ID, "error: internal error")
_ = conn.WriteMessage(1, okm)

if strings.HasPrefix(err.Error(), "internal") {
status = serverFail

return
}

if !isWhiteListed {
okm := message.MakeOK(false, msg.Event.ID, "restricted: not allowed to write.")
_ = conn.WriteMessage(1, okm)

status = limitsFail

return
}
return
}

client, ok := s.conns[conn]
Expand Down Expand Up @@ -192,9 +129,9 @@ func (s *Server) handleEvent(conn *websocket.Conn, m message.Message) { //nolint
}

if msg.Event.Kind == types.KindRightToVanish {
relays := msg.Event.Tags.GetValues("relays")
if !(slices.Contains(relays, "ALL_RELAYS") ||
slices.Contains(relays, s.config.URL.String())) {
relays := msg.Event.Tags.GetValues("relay")
if !slices.Contains(relays, "ALL_RELAYS") &&
!slices.Contains(relays, s.config.URL.String()) {
okm := message.MakeOK(false,
msg.Event.ID,
"error: can't execute vanish request.",
Expand Down Expand Up @@ -254,8 +191,7 @@ func (s *Server) handleEvent(conn *websocket.Conn, m message.Message) { //nolint

_ = conn.WriteMessage(1, message.MakeOK(true, msg.Event.ID, ""))

_, err = s.redis.Client.BFAdd(qCtx, s.redis.BloomFilterName, eID[:]).Result()
if err != nil {
if err := s.redis.AddEventToBloom(eID[:]); err != nil {
logger.Info("adding event to bloom filter", "err", err.Error(), msg.Event.ID)
}

Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ require (
github.com/stretchr/testify v1.10.0
github.com/tidwall/gjson v1.18.0
go.mongodb.org/mongo-driver v1.17.2
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
google.golang.org/grpc v1.69.2
google.golang.org/protobuf v1.36.2
gopkg.in/natefinch/lumberjack.v2 v2.2.1
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
Expand Down
66 changes: 66 additions & 0 deletions infrastructure/redis/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package redis

import (
"context"
"errors"
"fmt"
"time"

Expand Down Expand Up @@ -52,6 +53,71 @@ func (r *Redis) Close() error {
return r.Client.Close()
}

func (r *Redis) AddEventToBloom(id []byte) error {
ctx, cancel := context.WithTimeout(context.Background(), r.QueryTimeout)
defer cancel()

_, err := r.Client.BFAdd(ctx, r.BloomFilterName, id).Result()
if err != nil {
return err
}

return nil
}

func (r *Redis) CheckAcceptability(restrictedWrites bool, eid []byte, pubkey string) error {
ctx, cancel := context.WithTimeout(context.Background(), r.QueryTimeout)
defer cancel()

pipe := r.Client.Pipeline()

bloomCheckCmd := pipe.BFExists(ctx, r.BloomFilterName, eid)

var whiteListCheckCmd *redis.BoolCmd

if restrictedWrites {
whiteListCheckCmd = pipe.CFExists(ctx, r.WhiteListFilterName, pubkey)
}

blackListCheckCmd := pipe.CFExists(ctx, r.BlackListFilterName, pubkey)

_, err := pipe.Exec(ctx)
if err != nil {
return errors.New("internal: error while checking event acceptability")
}

exists, err := bloomCheckCmd.Result()
if err != nil {
return errors.New("internal: cna't lookup bloom filter")
}

if exists {
return errors.New("duplicate: this event is already received")
}

isBlackListed, err := blackListCheckCmd.Result()
if err != nil {
return errors.New("internal: cna't lookup black list")
}

if isBlackListed {
return errors.New("blocked: pubkey is blocked")
}

if restrictedWrites {
isWhiteListed, err := whiteListCheckCmd.Result()
if err != nil {
return errors.New("internal: cna't lookup white list")
}

if !isWhiteListed {
return errors.New("restricted: not allowed to write")
}
}

return nil
}

// ! note: delayed tasks probably are not concurrent safe at the moment.
func (r *Redis) AddDelayedTask(listName string,
data string, delay time.Duration,
Expand Down
31 changes: 15 additions & 16 deletions pkg/utils/random.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package utils

import (
"time"

"golang.org/x/exp/rand"
"crypto/rand"
"math/big"
)

const (
Expand All @@ -14,19 +13,19 @@ const (
)

func GenerateChallenge(n int) string {
src := rand.NewSource(uint64(time.Now().UnixNano()))
b := make([]byte, n)
for i, cache, remain := n-1, src.Uint64(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Uint64(), letterIdxMax
}
if idx := cache & letterIdxMask; idx < uint64(len(chars)) {
b[i] = chars[idx]
i--
}
cache >>= letterIdxBits
remain--
token := ""
for i := 0; i < n; i++ {
token += string(chars[cryptoRandSecure(int64(len(chars)))])
}

return token
}

func cryptoRandSecure(n int64) int64 {
nBig, err := rand.Int(rand.Reader, big.NewInt(n))
if err != nil {
return 0
}

return string(b)
return nBig.Int64()
}
1 change: 1 addition & 0 deletions types/kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,5 @@ var KindToName = map[Kind]string{
KindVideoViewEvent: "video_view_events",
KindCommunityDefinition: "community_definitions",
KindGroupsMetadata: "groups_metadata",
KindRightToVanish: "right_to_vanish",
}

0 comments on commit db35f77

Please sign in to comment.