ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / internal/modules/opportunities/document_handler.go

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / internal/modules/opportunities/document_handler.go
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberinternal/modules/opportunities/document_handler.go
Original SHA-25640b731cbdc1630292424cc4b51d9c4c4a3d72cbd4023d24dba5ecb855ddf7c2f
Git blob SHAcdb6e2478ee29a877442e25327f187fbb80e9e36
Reading-copy SHA-25640b731cbdc1630292424cc4b51d9c4c4a3d72cbd4023d24dba5ecb855ddf7c2f

Original source ↗

Recovered source transcript

package opportunities import ( "encoding/json" "errors" "io" "net/http" "github.com/go-chi/chi/v5" "github.com/google/uuid" "github.com/missionworkforce/missionmatch/internal/platform/security" "github.com/missionworkforce/missionmatch/internal/platform/tenant" ) // The document intake HTTP surface, directive Section 6 screen 3. // // Gated on opportunity.manage rather than a read capability, because attaching a customer's solicitation // package to an opportunity is a write to tenant data and should state that authority rather than inherit it. // // EVERY FAILURE MODE HERE RETURNS A REASON A HUMAN CAN ACT ON. "Upload failed" is the message that produces // a support ticket; "this file is 81 MB and the cap is 64 MB" is the message that produces a smaller file. type DocumentHandler struct{ svc *DocumentService } func NewDocumentHandler(svc *DocumentService) *DocumentHandler { return &DocumentHandler{svc: svc} } func (h *DocumentHandler) Routes(r chi.Router) { write := security.RequireCapability(security.CapOpportunityManage) read := security.RequireCapability(security.CapCandidateRead) r.With(write).Post("/opportunities/{id}/documents", h.upload) r.With(read).Get("/opportunities/{id}/documents", h.list) } // maxRequestBytes bounds what the server will READ, which is a different control from the size cap on the // document itself. Without it a caller can stream forever and the cap is only reached after the bytes are // already in memory, which is a denial of service with extra steps. const maxRequestBytes = MaxDocumentBytes + (1 << 20) func (h *DocumentHandler) upload(w http.ResponseWriter, r *http.Request) { oppID := chi.URLParam(r, "id") if err := r.ParseMultipartForm(8 << 20); err != nil { writeDocErr(w, http.StatusBadRequest, "this endpoint takes a multipart form with a file field: "+err.Error()) return } file, header, err := r.FormFile("file") if err != nil { writeDocErr(w, http.StatusBadRequest, "no file field in the form") return } defer file.Close() // LimitReader with ONE byte of headroom, so exceeding the cap is DETECTED rather than silently truncated // into a corrupt document that hashes differently every time. body, err := io.ReadAll(io.LimitReader(file, maxRequestBytes+1)) if err != nil { writeDocErr(w, http.StatusBadRequest, "could not read the uploaded file: "+err.Error()) return } if len(body) > maxRequestBytes { writeDocErr(w, http.StatusRequestEntityTooLarge, "the upload exceeds the request cap") return } p, _ := tenant.UserFromContext(r.Context()) uid, uerr := uuid.Parse(p.UserID) if uerr != nil { writeDocErr(w, http.StatusUnauthorized, "no validated user on this request") return } doc, err := h.svc.Upload(r.Context(), uid, UploadInput{ OpportunityID: oppID, DocumentType: r.FormValue("document_type"), FileName: header.Filename, MediaType: header.Header.Get("Content-Type"), Bytes: body, }) if err != nil { writeDocErr(w, statusForDocumentError(err), err.Error()) return } writeDocJSON(w, http.StatusCreated, doc) } func (h *DocumentHandler) list(w http.ResponseWriter, r *http.Request) { docs, err := h.svc.List(r.Context(), chi.URLParam(r, "id")) if err != nil { writeDocErr(w, statusForDocumentError(err), err.Error()) return } writeDocJSON(w, http.StatusOK, map[string]any{"documents": docs}) } // statusForDocumentError maps a sentinel to a status. Mapping on typed values rather than on message text // means renaming an error message never silently changes an HTTP contract. func statusForDocumentError(err error) int { switch { case errors.Is(err, ErrDocumentTooLarge): return http.StatusRequestEntityTooLarge case errors.Is(err, ErrMediaTypeRefused): return http.StatusUnsupportedMediaType case errors.Is(err, ErrDuplicateDocument): return http.StatusConflict case errors.Is(err, ErrDocumentEmpty), errors.Is(err, ErrDocumentTypeInvalid): return http.StatusBadRequest case errors.Is(err, ErrOpportunityUnknown): // 404 rather than 403: an opportunity belonging to another tenant must be indistinguishable from one // that does not exist, or the error code itself becomes a cross tenant existence oracle. return http.StatusNotFound case errors.Is(err, ErrNoDatabase): return http.StatusServiceUnavailable default: return http.StatusInternalServerError } } func writeDocJSON(w http.ResponseWriter, code int, v any) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) _ = json.NewEncoder(w).Encode(v) } func writeDocErr(w http.ResponseWriter, code int, msg string) { writeDocJSON(w, code, map[string]string{"error": msg}) }

Search equations, builds, manuscript text, and recovered sources.