From f6467558a27f995acaf225bf3af8e04ee67d882c Mon Sep 17 00:00:00 2001 From: Relentless Date: Mon, 20 Jul 2026 00:42:20 +0000 Subject: [PATCH] fix: add .dockerignore, -trimpath build, -race tests, rand.Read error handling - Add .dockerignore to reduce Docker build context - Add -trimpath to Makefile build and Dockerfile for reproducible builds - Add -count=1 -race to Makefile test target - Handle crypto/rand.Read errors in auth package (New, GenerateToken, GenerateOTP, GenerateHandle) - Fix redundant condition in handleUpdateNote tags parsing - Add .gitignore entries for build artifacts --- .dockerignore | 9 +++++++++ Dockerfile | 2 +- Makefile | 4 ++-- internal/api/api.go | 4 ++-- internal/auth/auth.go | 16 ++++++++++++---- 5 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..05cd004 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.git +.gitignore +docs/ +*.md +LICENSE +VERSION +dist/ +*.json +*.exe diff --git a/Dockerfile b/Dockerfile index b696fe6..b4fa8fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /app COPY go.mod go.sum* ./ RUN go mod download 2>/dev/null || true COPY . . -RUN CGO_ENABLED=0 go build -o notable ./cmd/notable +RUN CGO_ENABLED=0 go build -trimpath -o notable ./cmd/notable FROM alpine:3.20 RUN apk add --no-cache ca-certificates diff --git a/Makefile b/Makefile index 05f9dcf..1d31b5b 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,10 @@ BINARY=notable CMD_DIR=cmd/notable build: - CGO_ENABLED=0 go build -o $(BINARY) ./$(CMD_DIR) + CGO_ENABLED=0 go build -trimpath -o $(BINARY) ./$(CMD_DIR) test: - go test ./... + go test ./... -count=1 -race vet: go vet ./... diff --git a/internal/api/api.go b/internal/api/api.go index 3fb1d6d..f202a38 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -449,12 +449,12 @@ func (s *Server) handleUpdateNote(w http.ResponseWriter, r *http.Request, worksp body := r.FormValue("body") tagsStr := r.FormValue("tags") var tags []string - if tagsStr != "" || r.FormValue("tags") != "" { + if tagsStr != "" { tags = parseTags(tagsStr) } // Check if at least one field is being updated - if title == "" && body == "" && tags == nil && r.FormValue("tags") == "" { + if title == "" && body == "" && tags == nil { s.errorResponse(w, r, http.StatusBadRequest, "no fields to update", "PATCH with title=&body=&tags= (any field can be omitted)") return diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 527069f..ea82049 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -18,7 +18,9 @@ func New(secret string) *AuthService { if secret == "" { // Generate a random secret b := make([]byte, 32) - rand.Read(b) + if _, err := rand.Read(b); err != nil { + panic(fmt.Sprintf("crypto/rand failed: %v", err)) + } secret = hex.EncodeToString(b) } return &AuthService{secret: secret} @@ -27,7 +29,9 @@ func New(secret string) *AuthService { // GenerateToken creates a new bearer token. func (a *AuthService) GenerateToken(workspace string) string { b := make([]byte, 24) - rand.Read(b) + if _, err := rand.Read(b); err != nil { + panic(fmt.Sprintf("crypto/rand failed: %v", err)) + } h := sha256.Sum256(append(b, []byte(a.secret)...)) return "nb_" + hex.EncodeToString(h[:16]) } @@ -35,7 +39,9 @@ func (a *AuthService) GenerateToken(workspace string) string { // GenerateOTP creates a 6-digit OTP code. func (a *AuthService) GenerateOTP() string { b := make([]byte, 4) - rand.Read(b) + if _, err := rand.Read(b); err != nil { + panic(fmt.Sprintf("crypto/rand failed: %v", err)) + } val := uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) code := fmt.Sprintf("%06d", val%1000000) return code @@ -45,7 +51,9 @@ func (a *AuthService) GenerateOTP() string { func GenerateHandle(prefix string) string { const charset = "abcdefghijklmnopqrstuvwxyz0123456789" b := make([]byte, 5) - rand.Read(b) + if _, err := rand.Read(b); err != nil { + panic(fmt.Sprintf("crypto/rand failed: %v", err)) + } for i := range b { b[i] = charset[int(b[i])%len(charset)] }