package api import ( "encoding/json" "fmt" "io" "log" "net/http" ) // GetJobPaperwork retrieves a list of paperwork for a specific job // This is a specialized endpoint to directly access paperwork func (s *Session) GetJobPaperwork(jobID string) ([]map[string]interface{}, error) { log.Printf("GetJobPaperwork: Fetching paperwork for job %s", jobID) url := fmt.Sprintf("%s/job/%s/paperwork", BaseURL, jobID) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, fmt.Errorf("error creating request: %v", err) } // Add authorization header req.Header.Set("Cookie", s.Cookie) // Set headers for better compatibility req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") // Send the request log.Printf("GetJobPaperwork: Sending request to %s", url) resp, err := s.Client.Do(req) if err != nil { return nil, fmt.Errorf("error sending request: %v", err) } defer resp.Body.Close() // Read the full response body body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("error reading response body: %v", err) } // Check for errors if resp.StatusCode != http.StatusOK { // Log detailed error information log.Printf("GetJobPaperwork: API returned error %d for job %s", resp.StatusCode, jobID) log.Printf("GetJobPaperwork: Error response: %s", string(body)) return nil, fmt.Errorf("API returned error: %s - %s", resp.Status, string(body)) } // Log response preview responsePreview := string(body) if len(responsePreview) > 200 { responsePreview = responsePreview[:200] + "... [truncated]" } log.Printf("GetJobPaperwork: Response preview for job %s: %s", jobID, responsePreview) // Parse the response into a generic map var result map[string]interface{} if err := json.Unmarshal(body, &result); err != nil { return nil, fmt.Errorf("error parsing response: %v", err) } // Debug the response structure keys := make([]string, 0) for k := range result { keys = append(keys, k) } log.Printf("GetJobPaperwork: Response root keys for job %s: %v", jobID, keys) // Check for data.attachments format (which is what the logs show) paperworkItems := make([]map[string]interface{}, 0) // Check if data key exists if data, ok := result["data"].(map[string]interface{}); ok { dataKeys := make([]string, 0) for k := range data { dataKeys = append(dataKeys, k) } log.Printf("GetJobPaperwork: Data keys for job %s: %v", jobID, dataKeys) // Look for the attachments array in data if attachments, ok := data["attachments"].([]interface{}); ok && len(attachments) > 0 { log.Printf("GetJobPaperwork: Found %d attachments in data.attachments for job %s", len(attachments), jobID) // Convert each attachment to a map and add to our collection for _, attachment := range attachments { if attachmentMap, ok := attachment.(map[string]interface{}); ok { // Log the structure of the first attachment to better understand format if len(paperworkItems) == 0 { log.Printf("GetJobPaperwork: First attachment structure: %+v", attachmentMap) } paperworkItems = append(paperworkItems, attachmentMap) } } return paperworkItems, nil } // Check for objects in data if objects, ok := data["objects"].([]interface{}); ok && len(objects) > 0 { log.Printf("GetJobPaperwork: Found %d items in data.objects for job %s", len(objects), jobID) for _, obj := range objects { if objMap, ok := obj.(map[string]interface{}); ok { paperworkItems = append(paperworkItems, objMap) } } } // Check for paperwork array in data if paperwork, ok := data["paperwork"].([]interface{}); ok && len(paperwork) > 0 { log.Printf("GetJobPaperwork: Found %d items in data.paperwork for job %s", len(paperwork), jobID) for _, doc := range paperwork { if docMap, ok := doc.(map[string]interface{}); ok { paperworkItems = append(paperworkItems, docMap) } } } } // Also try the old formats // Check for objects at root level if objects, ok := result["objects"].([]interface{}); ok && len(objects) > 0 { log.Printf("GetJobPaperwork: Found %d items at root.objects for job %s", len(objects), jobID) for _, obj := range objects { if objMap, ok := obj.(map[string]interface{}); ok { paperworkItems = append(paperworkItems, objMap) } } } if len(paperworkItems) > 0 { log.Printf("GetJobPaperwork: Extracted %d total paperwork items from response for job %s", len(paperworkItems), jobID) return paperworkItems, nil } log.Printf("GetJobPaperwork: No paperwork items found in any format for job %s", jobID) return nil, nil } // CheckJobPermissions verifies if the current user has permissions to access the specified job func (s *Session) CheckJobPermissions(jobID string) (bool, string, error) { log.Printf("CheckJobPermissions: Checking permissions for job %s", jobID) // First try to get the job details - if this succeeds, the user has basic read access url := fmt.Sprintf("%s/job/%s", BaseURL, jobID) req, err := http.NewRequest("GET", url, nil) if err != nil { return false, "Error creating request", err } req.Header.Set("Cookie", s.Cookie) resp, err := s.Client.Do(req) if err != nil { return false, "Error sending request", err } defer resp.Body.Close() // Read response for detailed error information body, _ := io.ReadAll(resp.Body) // If we can't get the job, check the specific error if resp.StatusCode != http.StatusOK { errorMessage := string(body) // Check for permission-related errors if resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusUnauthorized { log.Printf("CheckJobPermissions: Permission denied for job %s: %s", jobID, errorMessage) return false, fmt.Sprintf("Permission denied: %s", resp.Status), nil } // Check for job not found if resp.StatusCode == http.StatusNotFound { log.Printf("CheckJobPermissions: Job %s not found: %s", jobID, errorMessage) return false, "Job not found", nil } // Other errors log.Printf("CheckJobPermissions: Error accessing job %s: %s - %s", jobID, resp.Status, errorMessage) return false, fmt.Sprintf("Error: %s", resp.Status), nil } // If we get here, the user can at least view the job // Now try to check if they can access paperwork paperworkURL := fmt.Sprintf("%s/job/%s/paperwork", BaseURL, jobID) paperworkReq, err := http.NewRequest("GET", paperworkURL, nil) if err != nil { return true, "Can access job, but error checking paperwork permissions", err } paperworkReq.Header.Set("Cookie", s.Cookie) paperworkResp, err := s.Client.Do(paperworkReq) if err != nil { return true, "Can access job, but error checking paperwork API", err } defer paperworkResp.Body.Close() if paperworkResp.StatusCode != http.StatusOK { log.Printf("CheckJobPermissions: User can access job %s but paperwork API returned %d", jobID, paperworkResp.StatusCode) return true, "Can access job, but paperwork access denied", nil } log.Printf("CheckJobPermissions: User has full access to job %s and its paperwork", jobID) return true, "Full access", nil }