Skip to content

Commit

Permalink
add new auth endpoint /getSignatures
Browse files Browse the repository at this point in the history
  • Loading branch information
Marketen committed May 17, 2024
1 parent aa0185e commit 91412b6
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.env
./listener/tmp/*
./listener/bin/*
./listener/bin/*
jwt
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ services:
BEACON_NODE_URL_HOLESKY: ${BEACON_NODE_URL_HOLESKY}
BEACON_NODE_URL_LUKSO: ${BEACON_NODE_URL_LUKSO}
BEACON_NODE_URL_GNOSIS: ${BEACON_NODE_URL_GNOSIS}
volumes:
- ./jwt:/jwt
depends_on:
- mongo
container_name: listener
Expand Down
65 changes: 65 additions & 0 deletions listener/internal/api/handlers/getSignatures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package handlers

import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"

"github.com/dappnode/validator-monitoring/listener/internal/api/types"
"github.com/dappnode/validator-monitoring/listener/internal/logger"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)

// GetSignatures fetches signatures from MongoDB based on the network, tag, and timestamp criteria.
func GetSignatures(w http.ResponseWriter, r *http.Request, dbCollection *mongo.Collection) {
logger.Debug("Received new POST '/getSignatures' request")

var params types.GetSignatureParams
err := json.NewDecoder(r.Body).Decode(&params)
if err != nil {
logger.Error("Failed to decode request body: " + err.Error())
respondError(w, http.StatusBadRequest, "Invalid request format")
return
}

// Calculate the cutoff time in Unix milliseconds as a string
cutoffTime := time.Now().Add(-time.Duration(params.Hours) * time.Hour).UnixMilli()
cutoffTimeStr := fmt.Sprintf("%d", cutoffTime)

filter := bson.M{
"network": params.Network,
"tag": params.Tag,
"entries.decodedPayload.timestamp": bson.M{
"$gt": cutoffTimeStr,
},
}

var results []bson.M
cursor, err := dbCollection.Find(context.Background(), filter)
if err != nil {
logger.Error("Failed to fetch signatures from MongoDB: " + err.Error())
respondError(w, http.StatusInternalServerError, "Failed to fetch signatures")
return
}
defer cursor.Close(context.Background())

if err = cursor.All(context.Background(), &results); err != nil {
logger.Error("Failed to decode signatures: " + err.Error())
respondError(w, http.StatusInternalServerError, "Failed to decode signatures")
return
}

// Set the content type to application/json
w.Header().Set("Content-Type", "application/json")

// Write the JSON response directly to the ResponseWriter
err = json.NewEncoder(w).Encode(results)
if err != nil {
logger.Error("Failed to encode response: " + err.Error())
respondError(w, http.StatusInternalServerError, "Failed to encode response")
return
}
}
58 changes: 58 additions & 0 deletions listener/internal/api/middleware/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package middleware

import (
"errors"
"net/http"
"os"
"strings"

"github.com/dappnode/validator-monitoring/listener/internal/logger"
)

// AuthMiddleware checks if the provided JWT token is valid.
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
logger.Debug("No token provided")
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}

// We expect the token to be in the format "Bearer <token>"
token = strings.TrimPrefix(token, "Bearer ")

valid, err := isValidToken(token)
if err != nil || !valid {
logger.Debug("Invalid token")
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}

next.ServeHTTP(w, r)
})
}

// isValidToken checks if the provided token exists in the /jwt directory.
func isValidToken(token string) (bool, error) {
files, err := os.ReadDir("/jwt")
if err != nil {
logger.Error("Failed to read /jwt directory: " + err.Error())
return false, err
}

for _, file := range files {
if !file.IsDir() {
content, err := os.ReadFile("/jwt/" + file.Name())
if err != nil {
logger.Error("Failed to read token file: " + err.Error())
continue
}
if strings.TrimSpace(string(content)) == token {
return true, nil
}
}
}

return false, errors.New("token not found")
}
6 changes: 4 additions & 2 deletions listener/internal/api/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"net/http"

"github.com/dappnode/validator-monitoring/listener/internal/api/handlers"
"github.com/dappnode/validator-monitoring/listener/internal/api/middleware"
"github.com/gorilla/mux"
"go.mongodb.org/mongo-driver/mongo"
)
Expand All @@ -18,8 +19,9 @@ func SetupRouter(dbCollection *mongo.Collection, beaconNodeUrls map[string]strin
handlers.PostNewSignature(w, r, dbCollection, beaconNodeUrls)
}).Methods(http.MethodPost)

// Middlewares
// r.Use(corsmiddleware()))
r.Handle("/getSignatures", middleware.AuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handlers.GetSignatures(w, r, dbCollection)
}))).Methods(http.MethodPost)

return r
}
6 changes: 6 additions & 0 deletions listener/internal/api/types/types.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package types

type GetSignatureParams struct {
Network string `json:"network"`
Tag string `json:"tag"`
Hours int `json:"hours"`
}

type SignatureRequest struct {
Payload string `json:"payload"`
Pubkey string `json:"pubkey"`
Expand Down

0 comments on commit 91412b6

Please sign in to comment.