Re-enable master asset fetching + Upload troubleshooting document
Master Asset Fetching: - Re-enabled with better error handling - Stores only lightweight data: asset_id, name, mime_type, model_id, security_policies - Avoids storing massive metadata structure that causes crashes - Graceful error handling if fetch fails Upload Troubleshooting Document (UPLOAD_TROUBLESHOOTING.md): - Comprehensive summary of upload blocking issue - Details of all 5 upload approaches tested - Technical specifications of API requests - Error messages and HTTP codes - Questions for Ferrero DAM support team - Comparison of working downloads vs blocked uploads - Recommended next steps Ready for client to share with Ferrero support team to resolve API upload permissions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0ebdf5c755
commit
289d34bf2b
2 changed files with 410 additions and 3 deletions
364
UPLOAD_TROUBLESHOOTING.md
Normal file
364
UPLOAD_TROUBLESHOOTING.md
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
# Ferrero OpenText DAM - Upload Troubleshooting Document
|
||||
|
||||
**Date:** October 24, 2025
|
||||
**Environment:** Production (https://ppr.dam.ferrero.com)
|
||||
**Application:** Content Scaling Workflow V3
|
||||
**Issue:** File uploads blocked with "restricted file extension" error
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The Content Scaling workflow application successfully performs campaign management, asset downloads, and status updates. However, **all file upload attempts via the OpenText Media Management API are being rejected** with file extension restriction errors, regardless of file type.
|
||||
|
||||
This document provides detailed technical information for Ferrero's OpenText DAM support team to diagnose and resolve the upload restriction.
|
||||
|
||||
---
|
||||
|
||||
## Current Status
|
||||
|
||||
### ✅ Working Features
|
||||
|
||||
1. **Campaign Discovery**
|
||||
- Search campaigns by Content Scaling Status (A1, A2, A5, etc.)
|
||||
- Filter by status using `CONTENT.SCALING.STATUS` metadata field
|
||||
- Display campaign details, brands, markets
|
||||
|
||||
2. **Asset Downloads**
|
||||
- Download master assets from campaigns
|
||||
- Bulk download functionality
|
||||
- Multiple file format support (.tif, .jpg, .png, etc.)
|
||||
|
||||
3. **Status Management**
|
||||
- Update campaign status: A1→A2, A2→A3, A5→A6
|
||||
- Uses PATCH `/v6/folders/{id}?lock_strategy=optimistic`
|
||||
- All status transitions working correctly
|
||||
|
||||
4. **OAuth2 Authentication**
|
||||
- Client credentials flow working
|
||||
- Token refresh functioning
|
||||
- Authorization headers properly included in all requests
|
||||
|
||||
### ❌ Blocked Feature
|
||||
|
||||
**File Uploads to DAM**
|
||||
- ALL file uploads rejected
|
||||
- Multiple file types tested
|
||||
- Various API approaches attempted
|
||||
- Consistent error across all attempts
|
||||
|
||||
---
|
||||
|
||||
## Upload Error Details
|
||||
|
||||
### Error Message
|
||||
```json
|
||||
{
|
||||
"exception_body": {
|
||||
"http_response_code": 500,
|
||||
"message": "Cannot import asset having restricted file extension.",
|
||||
"debug_message": "Asset creation failed due to restricted file extension",
|
||||
"error_code": 1000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Endpoint Used
|
||||
```
|
||||
POST https://ppr.dam.ferrero.com/otmmapi/v6/assets
|
||||
```
|
||||
|
||||
### Authentication
|
||||
- **Method:** OAuth2 Bearer Token
|
||||
- **Token Status:** Valid and active
|
||||
- **User:** scpi.user1 (from Creds.txt)
|
||||
- **Permissions:** Claimed to have "full access"
|
||||
|
||||
---
|
||||
|
||||
## File Types Tested
|
||||
|
||||
All of the following file extensions were rejected with the same error:
|
||||
|
||||
| File Extension | MIME Type | Test Result |
|
||||
|----------------|-----------|-------------|
|
||||
| `.tif` | image/tiff | ❌ Rejected |
|
||||
| `.jpg` | image/jpeg | ❌ Rejected |
|
||||
| `.png` | image/png | ❌ Rejected |
|
||||
| `.pdf` | application/pdf | ❌ Rejected |
|
||||
|
||||
**Conclusion:** The restriction appears to be **account-level or API-level**, not file-type-specific.
|
||||
|
||||
---
|
||||
|
||||
## Upload Approaches Tested
|
||||
|
||||
### Attempt 1: Full Metadata from Master Asset
|
||||
**Payload:**
|
||||
- `asset_representation` with complete metadata structure from existing master asset
|
||||
- `metadata_model_id`: ECOMMERCE (from master asset)
|
||||
- `security_policy_list`: From master asset
|
||||
- `manifest`: Upload manifest with filename and MIME type
|
||||
- `parent_folder_id`: Final Assets folder ID
|
||||
- `files`: File uploaded via CURLFile
|
||||
|
||||
**Result:** HTTP 500 - "restricted file extension"
|
||||
|
||||
---
|
||||
|
||||
### Attempt 2: Minimal Metadata with Model ID
|
||||
**Payload:**
|
||||
- `asset_representation` with only:
|
||||
- `name`: Filename
|
||||
- `metadata_model_id`: ECOMMERCE
|
||||
- `security_policy_list`: [{"id": 1594}]
|
||||
- `manifest`: Upload manifest
|
||||
- `parent_folder_id`: Final Assets folder ID
|
||||
- `files`: File
|
||||
|
||||
**Result:** HTTP 500 - "restricted file extension"
|
||||
|
||||
---
|
||||
|
||||
### Attempt 3: Import Template Approach
|
||||
**Payload:**
|
||||
- `import_template_id`: MARKETING.ASSET
|
||||
- `manifest`: Upload manifest
|
||||
- `parent_folder_id`: Final Assets folder ID
|
||||
- `files`: File
|
||||
|
||||
**Result:** HTTP 400 - "No permissable import template found"
|
||||
|
||||
---
|
||||
|
||||
### Attempt 4: Absolute Minimum (No Metadata)
|
||||
**Payload:**
|
||||
- `manifest`: Upload manifest only
|
||||
- `parent_folder_id`: Final Assets folder ID
|
||||
- `files`: File
|
||||
|
||||
**Result:** HTTP 500 - "restricted file extension"
|
||||
|
||||
---
|
||||
|
||||
### Attempt 5: Without Metadata Model ID
|
||||
**Payload:**
|
||||
- `asset_representation`:
|
||||
- `name`: Filename
|
||||
- `security_policy_list`: [{"id": 1594}]
|
||||
- `manifest`: Upload manifest
|
||||
- `parent_folder_id`: Final Assets folder ID
|
||||
- `files`: File
|
||||
|
||||
**Result:** HTTP 500 - "restricted file extension"
|
||||
|
||||
---
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Request Structure (Current Implementation)
|
||||
|
||||
**Endpoint:**
|
||||
```
|
||||
POST /v6/assets
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Accept: application/json
|
||||
Authorization: Bearer {oauth_token}
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
**Form Data Fields:**
|
||||
```
|
||||
asset_representation: {
|
||||
"asset_resource": {
|
||||
"asset": {
|
||||
"name": "filename.jpg",
|
||||
"metadata_model_id": "ECOMMERCE",
|
||||
"security_policy_list": [{"id": 1594}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manifest: {
|
||||
"upload_manifest": {
|
||||
"master_files": [{
|
||||
"file": {
|
||||
"file_name": "filename.jpg",
|
||||
"file_type": "image/jpeg"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parent_folder_id: "ea0dbf86e13e3634895746d3a986558ec2eb8be1"
|
||||
|
||||
files: [binary file data via CURLFile]
|
||||
```
|
||||
|
||||
### Upload Target Details
|
||||
|
||||
**Campaign:** Local adaptation test 2 (C000000078)
|
||||
**Campaign Asset ID:** 7e2f7c97b003f91f8b2a162b9f62ccab51586fa9
|
||||
**Target Folder:** Final Assets (ID: ea0dbf86e13e3634895746d3a986558ec2eb8be1)
|
||||
**Content Scaling Status:** A2 (Assets Sent to Agency)
|
||||
|
||||
**Master Assets Available:**
|
||||
- 8000500247167_8.tif (image/tiff, ECOMMERCE model)
|
||||
- [Additional assets in Master Assets folder]
|
||||
|
||||
---
|
||||
|
||||
## Comparison: Downloads vs Uploads
|
||||
|
||||
### Downloads (Working ✅)
|
||||
- **Endpoint:** `GET /v6/assets/{id}/contents`
|
||||
- **Authentication:** Same OAuth token
|
||||
- **File Types:** .tif, .jpg, .png all download successfully
|
||||
- **Permissions:** Read access confirmed working
|
||||
|
||||
### Uploads (Blocked ❌)
|
||||
- **Endpoint:** `POST /v6/assets`
|
||||
- **Authentication:** Same OAuth token
|
||||
- **File Types:** ALL rejected
|
||||
- **Permissions:** Upload/write access appears restricted
|
||||
|
||||
**Analysis:** The same OAuth credentials work for downloads but not uploads, suggesting **write permissions may not be enabled** for the API user account.
|
||||
|
||||
---
|
||||
|
||||
## Questions for Ferrero DAM Support
|
||||
|
||||
### 1. API Upload Permissions
|
||||
- Is the user account `scpi.user1` authorized to upload files via API?
|
||||
- Are there separate permissions for read vs. write operations?
|
||||
- Is there a different user account or API key required for uploads?
|
||||
|
||||
### 2. File Extension Whitelist
|
||||
- What file extensions are permitted for uploads via `/v6/assets` endpoint?
|
||||
- Is there a server-side whitelist configuration?
|
||||
- Can this be configured per user or globally?
|
||||
|
||||
### 3. Alternative Upload Methods
|
||||
- Is there a different API endpoint for uploads? (e.g., `/assets` without `/v6/`?)
|
||||
- Are there import templates we should be using instead of direct uploads?
|
||||
- What method does the web interface use for uploads?
|
||||
|
||||
### 4. Metadata Requirements
|
||||
- What is the minimum required metadata structure for uploads?
|
||||
- Are specific metadata fields mandatory for the ECOMMERCE model?
|
||||
- Can uploads inherit metadata from the parent folder?
|
||||
|
||||
### 5. Environment Configuration
|
||||
- Are API uploads enabled in the production environment?
|
||||
- Are there rate limits or quota restrictions?
|
||||
- Are uploads restricted to certain folders or campaigns?
|
||||
|
||||
---
|
||||
|
||||
## Additional Context
|
||||
|
||||
### Master Asset Metadata Size Issue
|
||||
|
||||
Master assets contain extensive metadata structures (brands, markets, campaigns, compliance data, etc.) that are **too large to transmit** in upload requests:
|
||||
- Causes PHP memory issues when stored in session
|
||||
- JSON payload becomes several MB in size
|
||||
- Server returns HTTP 502 (Bad Gateway) when full metadata sent
|
||||
|
||||
**Current Approach:** Only transmit essential fields (model ID, security policies) and rely on folder inheritance for other metadata.
|
||||
|
||||
---
|
||||
|
||||
## Working Example from Postman Collection
|
||||
|
||||
The V3 Postman collection includes a "Create Assets and Set Metadata" request with example payload. However:
|
||||
|
||||
1. The example uses `import_template_id: 'MARKETING.ASSET'` which returns "No permissable import template found"
|
||||
2. The example includes extensive metadata fields
|
||||
3. We cannot test this request in Postman as we don't have the Postman environment
|
||||
|
||||
---
|
||||
|
||||
## Recommended Next Steps
|
||||
|
||||
### For Ferrero Support Team:
|
||||
|
||||
1. **Verify API upload permissions** for user `scpi.user1` in production environment
|
||||
2. **Check file extension whitelist** configuration for `/v6/assets` endpoint
|
||||
3. **Provide list of allowed file extensions** for API uploads
|
||||
4. **Confirm correct upload endpoint** and required parameters
|
||||
5. **Share working example** of successful upload via API (if available)
|
||||
|
||||
### For Development Team (Once Resolved):
|
||||
|
||||
1. Update AssetUploader with correct endpoint and parameters
|
||||
2. Implement proper metadata copying from master assets
|
||||
3. Add support for metadata field updates (language, market, etc.)
|
||||
4. Test upload workflow end-to-end (A2→A3)
|
||||
5. Implement rework upload workflow (A5→A6)
|
||||
|
||||
---
|
||||
|
||||
## Code Repository
|
||||
|
||||
**Bitbucket:** bitbucket.org:zlalani/ferrero-opentext.git
|
||||
**Branch:** main
|
||||
**Latest Commit:** 0ebdf5c - "Disable master assets fetching in upload"
|
||||
|
||||
**Key Files:**
|
||||
- `workflow_v3.php` - Main workflow interface
|
||||
- `src/AssetUploader.php` - Upload implementation
|
||||
- `src/StatusManager.php` - Status updates (working)
|
||||
- `config_v3.php` - Configuration
|
||||
|
||||
---
|
||||
|
||||
## Contact Information
|
||||
|
||||
**Developer:** Working through Claude Code
|
||||
**Client:** [Your contact information]
|
||||
**Issue Tracker:** GitHub Issues (if applicable)
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Full Error Log
|
||||
|
||||
### Sample Upload Request (Simplified)
|
||||
|
||||
**URL:**
|
||||
```
|
||||
POST https://ppr.dam.ferrero.com/otmmapi/v6/assets
|
||||
```
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Accept: application/json
|
||||
Authorization: Bearer [valid_oauth_token]
|
||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
|
||||
```
|
||||
|
||||
**Form Fields:**
|
||||
```
|
||||
asset_representation: {"asset_resource":{"asset":{"name":"test.jpg","security_policy_list":[{"id":1594}]}}}
|
||||
manifest: {"upload_manifest":{"master_files":[{"file":{"file_name":"test.jpg","file_type":"image/jpeg"}}]}}
|
||||
parent_folder_id: ea0dbf86e13e3634895746d3a986558ec2eb8be1
|
||||
files: [binary file data]
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"exception_body": {
|
||||
"http_response_code": 500,
|
||||
"message": "Cannot import asset having restricted file extension.",
|
||||
"debug_message": "Asset creation failed due to restricted file extension",
|
||||
"error_code": 1000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**End of Document**
|
||||
|
|
@ -263,10 +263,53 @@ if ($_POST && $testRunner) {
|
|||
|
||||
if ($uploadFolderId) {
|
||||
$results['upload_folder_id'] = $uploadFolderId;
|
||||
$success = "Found upload target folder";
|
||||
|
||||
// TODO: Master assets fetching disabled - causes PHP crashes due to metadata size
|
||||
// Will re-enable once upload file extension issue is resolved
|
||||
// Get Master Assets to copy their metadata
|
||||
try {
|
||||
$masterFolderId = findMasterAssetsFolder($testRunner, $campaignId, $configV3);
|
||||
if ($masterFolderId) {
|
||||
$fullMasterAssets = getAssetsFromFolder($testRunner, $masterFolderId);
|
||||
|
||||
// Store lightweight version - only IDs and basic info
|
||||
$results['master_assets_for_upload'] = [];
|
||||
if (!empty($fullMasterAssets)) {
|
||||
foreach ($fullMasterAssets as $asset) {
|
||||
// Only store minimal fields - no huge metadata structure
|
||||
$lightAsset = [
|
||||
'asset_id' => $asset['asset_id'] ?? null,
|
||||
'name' => $asset['name'] ?? 'Unknown',
|
||||
'mime_type' => $asset['mime_type'] ?? null
|
||||
];
|
||||
|
||||
// Safely extract metadata_model_id if it exists
|
||||
if (isset($asset['metadata_model_id'])) {
|
||||
$lightAsset['metadata_model_id'] = $asset['metadata_model_id'];
|
||||
}
|
||||
|
||||
// Safely extract security policy IDs only
|
||||
if (isset($asset['security_policy_list']) && is_array($asset['security_policy_list'])) {
|
||||
$policyIds = [];
|
||||
foreach ($asset['security_policy_list'] as $policy) {
|
||||
if (isset($policy['id'])) {
|
||||
$policyIds[] = ['id' => $policy['id']];
|
||||
}
|
||||
}
|
||||
if (!empty($policyIds)) {
|
||||
$lightAsset['security_policy_list'] = $policyIds;
|
||||
}
|
||||
}
|
||||
|
||||
$results['master_assets_for_upload'][] = $lightAsset;
|
||||
}
|
||||
}
|
||||
|
||||
$success = "Found upload folder and " . count($results['master_assets_for_upload']) . " master assets for reference";
|
||||
} else {
|
||||
$success = "Found upload target folder (no master assets folder found)";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$success = "Found upload target folder (master assets error: " . $e->getMessage() . ")";
|
||||
}
|
||||
} else {
|
||||
$error = "Upload folder not found in campaign";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue