Skip to content

Instantly share code, notes, and snippets.

@hbenali
Created December 24, 2025 17:46
Show Gist options
  • Select an option

  • Save hbenali/95fbcc1495e44b67c390ed558e2697a8 to your computer and use it in GitHub Desktop.

Select an option

Save hbenali/95fbcc1495e44b67c390ed558e2697a8 to your computer and use it in GitHub Desktop.
eXo Platform Avatar Update Script
#!/bin/bash
# ============================================================================
# BULK AVATAR UPDATER SCRIPT
# ============================================================================
#
# PURPOSE:
# This script automates the process of updating user avatars in an eXo Platform
# instance by uploading image files from the current directory. Each image file's
# name (without extension) is treated as a username, and the image is set as
# that user's avatar.
#
# KEY FEATURES:
# - Batch processes all jpg/jpeg/png images in current directory
# - Authenticates using admin credentials (requires HTTP 302 redirect response)
# - Preserves dots in filenames for complex usernames (e.g., "john.doe.smith")
# - Tracks and displays failed updates with usernames
# - Provides progress indicator and summary statistics
#
# AUTHENTICATION NOTE:
# This script expects a successful authentication to return HTTP status code 302
# (Found/Redirect), which is the standard behavior for eXo Platform login.
# The 302 response indicates successful authentication and redirect to the
# main portal page.
#
# USAGE:
# ./update_avatars.sh -u https://your-server.com -n admin -p password
# ============================================================================
update_user_avatars() {
# Color codes for terminal output
RED='\e[31m'
GREEN='\e[32m'
YELLOW='\e[33m'
BLUE='\e[34m'
NC='\e[0m' # No Color
# Parse command line arguments
local url="" user="" pass=""
while [[ $# -gt 0 ]]; do
case $1 in
-u|--url) url="$2"; shift 2 ;;
-n|--username) user="$2"; shift 2 ;;
-p|--password) pass="$2"; shift 2 ;;
-h|--help)
echo "Usage: $0 -u URL -n USERNAME -p PASSWORD"
echo ""
echo "Purpose: Upload images from current directory as user avatars"
echo " Image filename (without extension) = Username"
echo ""
echo "Examples:"
echo " john.doe.jpg -> Avatar for user 'john.doe'"
echo " jane.smith.png -> Avatar for user 'jane.smith'"
echo ""
echo "Note: Authentication requires HTTP 302 response"
exit 0
;;
*) shift ;;
esac
done
# Validate required arguments
if [ -z "$url" ] || [ -z "$user" ] || [ -z "$pass" ]; then
echo -e "${RED}Error: Missing required arguments${NC}"
echo "Usage: $0 -u URL -n USERNAME -p PASSWORD"
exit 1
fi
# Remove trailing slash from URL if present
url="${url%/}"
# ------------------------------------------------------------------------
# AUTHENTICATION PHASE
# ------------------------------------------------------------------------
# Note: eXo Platform login typically returns HTTP 302 on successful auth
# This redirect indicates authentication succeeded and user is being
# redirected to the main portal page.
echo -ne "${BLUE}Authenticating...${NC} "
local cookie=$(mktemp)
local auth_code=$(curl -s -w "%{http_code}" -c "$cookie" -X POST \
"$url/portal/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "username=$user&password=$pass")
# Check for HTTP 302 response (required for successful authentication)
if [[ ! "${auth_code: -3}" == "302" ]]; then
echo -e "${RED}FAILED${NC}"
echo -e "${YELLOW}Expected HTTP 302 (redirect) but got: ${auth_code: -3}${NC}"
echo -e "${YELLOW}Possible issues:${NC}"
echo -e "${YELLOW} • Invalid credentials${NC}"
echo -e "${YELLOW} • Server URL incorrect${NC}"
echo -e "${YELLOW} • Server not running/accessible${NC}"
rm -f "$cookie"
exit 1
fi
echo -e "${GREEN}OK (302 redirect received)${NC}"
# ------------------------------------------------------------------------
# IMAGE DISCOVERY PHASE
# ------------------------------------------------------------------------
# Find all image files in current directory
# Supports jpg, jpeg, png (case insensitive)
shopt -s nullglob
local images=(*.{jpg,jpeg,png,JPG,JPEG,PNG})
shopt -u nullglob
if [ ${#images[@]} -eq 0 ]; then
echo "No image files found in current directory"
echo "Supported formats: .jpg, .jpeg, .png"
rm -f "$cookie"
exit 0
fi
echo -e "${BLUE}Found ${#images[@]} image(s) to process${NC}"
echo ""
# ------------------------------------------------------------------------
# PROCESSING PHASE
# ------------------------------------------------------------------------
# Arrays to track results for final summary
local success=() # Users successfully updated
local failed=() # Users where update failed
local skipped=() # Users not found in system
local current=0 # Progress counter
# Process each image file
for img in "${images[@]}"; do
((current++))
# Extract username from filename (preserving all dots)
# Example: "john.doe.smith.jpg" -> "john.doe.smith"
local username="${img%.*}"
# Show progress: [current/total] username...
echo -ne "[$current/${#images[@]}] $username... "
# --------------------------------------------------------------------
# STEP 1: Verify user exists in system
# --------------------------------------------------------------------
local check_code=$(curl -s -w "%{http_code}" -b "$cookie" \
"$url/portal/rest/v1/users/$username")
# If user not found (HTTP 404) or access denied, skip
if [[ ! "${check_code: -3}" == "200" ]]; then
echo -e "${YELLOW}SKIP (user not found/accessible)${NC}"
skipped+=("$username")
continue
fi
# --------------------------------------------------------------------
# STEP 2: Upload image to server
# --------------------------------------------------------------------
# Generate unique upload ID to prevent conflicts
local upload_id="avatar_$(date +%s)_$RANDOM"
local temp_img="/tmp/$upload_id"
# Copy image to temporary location
cp "$img" "$temp_img" 2>/dev/null
# Upload image to server's upload endpoint
local upload_code=$(curl -s -w "%{http_code}" -X POST -b "$cookie" \
"$url/portal/upload?uploadId=$upload_id&action=upload" \
-F "upload=@$temp_img" 2>/dev/null)
# --------------------------------------------------------------------
# STEP 3: Update user's avatar with uploaded image
# --------------------------------------------------------------------
local update_code="000" # Default error code
if [[ "${upload_code: -3}" == "200" ]]; then
# Only proceed with avatar update if upload was successful
update_code=$(curl -s -w "%{http_code}" -XPATCH -b "$cookie" \
"$url/portal/rest/v1/social/users/$username" \
--data-raw "name=avatar&value=$upload_id" 2>/dev/null)
fi
# --------------------------------------------------------------------
# STEP 4: Cleanup and track result
# --------------------------------------------------------------------
rm -f "$temp_img" 2>/dev/null
# Check if update was successful (HTTP 204 or 200)
if [[ "${update_code: -3}" =~ ^(204|200)$ ]]; then
echo -e "${GREEN}OK${NC}"
success+=("$username")
else
echo -e "${RED}FAIL (HTTP ${update_code: -3})${NC}"
failed+=("$username")
fi
done
# ------------------------------------------------------------------------
# CLEANUP PHASE
# ------------------------------------------------------------------------
rm -f "$cookie"
# ------------------------------------------------------------------------
# SUMMARY PHASE
# ------------------------------------------------------------------------
echo ""
echo "=== PROCESSING SUMMARY ==="
echo -e "Total images processed: ${#images[@]}"
echo -e "${GREEN}Successfully updated: ${#success[@]}${NC}"
echo -e "${RED}Failed updates: ${#failed[@]}${NC}"
echo -e "${YELLOW}Skipped (not found): ${#skipped[@]}${NC}"
# ------------------------------------------------------------------------
# DETAILED FAILURE REPORT
# ------------------------------------------------------------------------
if [ ${#failed[@]} -gt 0 ]; then
echo ""
echo -e "${RED}FAILED TO UPDATE THESE USERS:${NC}"
printf ' %s\n' "${failed[@]}"
echo ""
echo -e "${YELLOW}Troubleshooting tips:${NC}"
echo -e "${YELLOW} • Check user permissions${NC}"
echo -e "${YELLOW} • Verify image file format/size${NC}"
echo -e "${YELLOW} • Check server logs for errors${NC}"
fi
# ------------------------------------------------------------------------
# SKIPPED USERS REPORT
# ------------------------------------------------------------------------
if [ ${#skipped[@]} -gt 0 ]; then
echo ""
echo -e "${YELLOW}SKIPPED (USERS NOT FOUND):${NC}"
printf ' %s\n' "${skipped[@]}"
fi
# ------------------------------------------------------------------------
# FINAL STATUS
# ------------------------------------------------------------------------
echo ""
if [ ${#success[@]} -eq ${#images[@]} ]; then
echo -e "${GREEN}✅ SUCCESS: All ${#images[@]} avatars updated successfully${NC}"
elif [ ${#success[@]} -gt 0 ]; then
echo -e "${BLUE}⚠️ PARTIAL SUCCESS: ${#success[@]}/${#images[@]} avatars updated${NC}"
else
echo -e "${RED}❌ FAILURE: No avatars were updated${NC}"
fi
}
# Execute the main function with all provided arguments
update_user_avatars "$@"
@hbenali
Copy link
Author

hbenali commented Dec 24, 2025

🚀 Quick Start Guide

1. Prepare Your Images

bash
# Navigate to your images folder
cd /path/to/avatar/images/

# Rename images to match usernames
# Example: john.doe.jpg, mary.smith.png, user123.jpeg

2. Make Script Executable

bash
chmod +x update_avatars.sh

3. Run the Script

bash
./update_avatars.sh -u https://your-server.com -n admin -p password

⚙️ Command Syntax

bash
./update_avatars.sh -u SERVER_URL -n ADMIN_USERNAME -p ADMIN_PASSWORD

Parameters:

Option Description Example
-u, --url eXo Platform server URL https://exo.company.com
-n, --username Admin username root
-p, --password Admin password @root123456
-h, --help Show help message  

📁 File Naming Convention

Supported Formats:

  • .jpg, .jpeg, .png (case insensitive)

Naming Rules:

  1. Filename = Username (without extension)

  2. Dots are preserved: Useful for complex usernames

  3. Examples:

    • john.doe.jpg → User: john.doe

    • mary.smith@company.png → User: mary.smith@company

    • user123.jpeg → User: user123

What Happens:

text
Image: john.doe.smith.jpg
↓
Username: john.doe.smith
↓
Avatar update for user "john.doe.smith"

🔄 Execution Process

Step 1: Authentication

  • Connects to /portal/login endpoint

  • Requires HTTP 302 response for success

  • Stores session cookies for subsequent requests

Step 2: Image Discovery

  • Scans current directory for image files

  • Supports: .jpg, .jpeg, .png (all cases)

Step 3: Per-User Processing

For each image file:

  1. User Verification: Checks if user exists in system

  2. Image Upload: Uploads to server with unique ID

  3. Avatar Assignment: Links image to user's avatar

  4. Cleanup: Removes temporary files

Step 4: Summary Report

  • Success/failure statistics

  • List of users not found

  • Detailed error information


📊 Example Output

text
Authenticating... OK (302 redirect received)
Found 10 image(s) to process

[1/10] john.doe... OK
[2/10] mary.smith... OK
[3/10] unknown.user... SKIP (user not found)
[4/10] bob.jones... FAIL (HTTP 403)
...

=== PROCESSING SUMMARY ===
Total images processed: 10
Successfully updated: 8
Failed updates: 1
Skipped (not found): 1

FAILED TO UPDATE THESE USERS:
bob.jones

SKIPPED (USERS NOT FOUND):
unknown.user

⚠️ PARTIAL SUCCESS: 8/10 avatars updated


🔍 Troubleshooting

Common Issues:

1. Authentication Failed

text
Authenticating... FAILED
Expected HTTP 302 (redirect) but got: 401

Solutions:

  • Verify credentials are correct

  • Check server URL is accessible

  • Ensure server is running

2. User Not Found

text
unknown.user... SKIP (user not found/accessible)

Check:

  • Username spelling matches exactly

  • User exists in eXo Platform

  • Admin has permission to access user

3. Update Failed

text
bob.jones... FAIL (HTTP 403)

Possible causes:

  • Insufficient permissions

  • Image file too large

  • Server-side restrictions


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment