A community based topic aggregation platform built on atproto

fix(handlers): strengthen input validation with regex patterns

Improve validation robustness in block/unblock handlers:

1. DID validation with regex:
- Pattern: ^did:(plc|web):[a-zA-Z0-9._:%-]+$
- Rejects invalid formats like "did:x" or "did:"
- Ensures only supported DID methods (plc, web)

2. Handle validation:
- Verify handle contains @ symbol for domain
- Rejects incomplete handles like "!" or "!name"
- Ensures proper format: !name@domain.tld

Previous validation only checked prefix, allowing invalid values
to pass through to service layer. New validation catches format
errors early with clear error messages.

Addresses: Important review comment #4

Changed files
+32 -4
internal
api
handlers
community
+32 -4
internal/api/handlers/community/block.go
···
"encoding/json"
"log"
"net/http"
+
"regexp"
"strings"
)
···
return
}
-
// Validate format (DID or handle)
-
if !strings.HasPrefix(req.Community, "did:") && !strings.HasPrefix(req.Community, "!") {
+
// Validate format (DID or handle) with proper regex patterns
+
if strings.HasPrefix(req.Community, "did:") {
+
// Validate DID format: did:method:identifier
+
// atProto supports did:plc and did:web
+
didRegex := regexp.MustCompile(`^did:(plc|web):[a-zA-Z0-9._:%-]+$`)
+
if !didRegex.MatchString(req.Community) {
+
writeError(w, http.StatusBadRequest, "InvalidRequest", "invalid DID format")
+
return
+
}
+
} else if strings.HasPrefix(req.Community, "!") {
+
// Validate handle format: !name@domain.tld
+
if !strings.Contains(req.Community, "@") {
+
writeError(w, http.StatusBadRequest, "InvalidRequest", "handle must contain @domain")
+
return
+
}
+
} else {
writeError(w, http.StatusBadRequest, "InvalidRequest",
"community must be a DID (did:plc:...) or handle (!name@instance.com)")
return
···
return
}
-
// Validate format (DID or handle)
-
if !strings.HasPrefix(req.Community, "did:") && !strings.HasPrefix(req.Community, "!") {
+
// Validate format (DID or handle) with proper regex patterns
+
if strings.HasPrefix(req.Community, "did:") {
+
// Validate DID format: did:method:identifier
+
didRegex := regexp.MustCompile(`^did:(plc|web):[a-zA-Z0-9._:%-]+$`)
+
if !didRegex.MatchString(req.Community) {
+
writeError(w, http.StatusBadRequest, "InvalidRequest", "invalid DID format")
+
return
+
}
+
} else if strings.HasPrefix(req.Community, "!") {
+
// Validate handle format: !name@domain.tld
+
if !strings.Contains(req.Community, "@") {
+
writeError(w, http.StatusBadRequest, "InvalidRequest", "handle must contain @domain")
+
return
+
}
+
} else {
writeError(w, http.StatusBadRequest, "InvalidRequest",
"community must be a DID (did:plc:...) or handle (!name@instance.com)")
return