277 lines
9.8 KiB
Python
277 lines
9.8 KiB
Python
"""
|
|
Box.com setup & diagnostic script
|
|
|
|
Run this once to:
|
|
1. Verify JWT credentials in oliver_box_config.json
|
|
2. Authenticate as the service account
|
|
3. List enterprise users (to identify BOX_AS_USER_ID)
|
|
4. Access the VIDEO_OPTIMIZER root folder
|
|
5. Discover IN / OUT_SUCCESS / OUT_FAILED sub-folders
|
|
6. Print a summary of what is configured and what is missing
|
|
|
|
Usage:
|
|
cd backend
|
|
python box_setup.py
|
|
|
|
Optional: test with a specific Box user ID
|
|
BOX_AS_USER_ID=12345678 python box_setup.py
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
from dotenv import load_dotenv
|
|
|
|
# Load .env from the parent directory
|
|
load_dotenv(os.path.join(os.path.dirname(__file__), '..', '.env'))
|
|
|
|
BOX_CONFIG_PATH = os.getenv(
|
|
'BOX_CONFIG_PATH',
|
|
os.path.join(os.path.dirname(__file__), '..', 'oliver_box_config.json')
|
|
)
|
|
BOX_VIDEO_OPTIMIZER_FOLDER_ID = os.getenv('BOX_VIDEO_OPTIMIZER_FOLDER_ID', '')
|
|
BOX_AS_USER_ID = os.getenv('BOX_AS_USER_ID', '')
|
|
|
|
|
|
def print_section(title: str):
|
|
print(f"\n{'=' * 70}")
|
|
print(f" {title}")
|
|
print('=' * 70)
|
|
|
|
|
|
def check_config_file():
|
|
print_section("1. Checking oliver_box_config.json")
|
|
resolved = os.path.abspath(BOX_CONFIG_PATH)
|
|
print(f" Path: {resolved}")
|
|
|
|
if not os.path.exists(resolved):
|
|
print(f" ✗ File not found: {resolved}")
|
|
print(" Make sure oliver_box_config.json is in the project root.")
|
|
return False
|
|
|
|
try:
|
|
with open(resolved) as f:
|
|
config = json.load(f)
|
|
|
|
app_settings = config.get('boxAppSettings', {})
|
|
client_id = app_settings.get('clientID', '')
|
|
enterprise_id = config.get('enterpriseID', '')
|
|
key_id = app_settings.get('appAuth', {}).get('publicKeyID', '')
|
|
|
|
print(f" ✓ File found and valid JSON")
|
|
print(f" Client ID: {client_id[:8]}{'*' * (len(client_id) - 8) if len(client_id) > 8 else ''}")
|
|
print(f" Enterprise ID: {enterprise_id}")
|
|
print(f" Public Key ID: {key_id}")
|
|
return True
|
|
|
|
except json.JSONDecodeError as e:
|
|
print(f" ✗ Invalid JSON: {e}")
|
|
return False
|
|
except Exception as e:
|
|
print(f" ✗ Error reading config: {e}")
|
|
return False
|
|
|
|
|
|
def check_env_vars():
|
|
print_section("2. Checking Environment Variables (.env)")
|
|
|
|
vars_to_check = {
|
|
'BOX_CONFIG_PATH': BOX_CONFIG_PATH,
|
|
'BOX_VIDEO_OPTIMIZER_FOLDER_ID': BOX_VIDEO_OPTIMIZER_FOLDER_ID,
|
|
'BOX_AS_USER_ID': BOX_AS_USER_ID or '(not set — will use service account)',
|
|
'BOX_WEBHOOK_SECRET': os.getenv('BOX_WEBHOOK_SECRET', '(not set)'),
|
|
'BOX_PROCESSOR_PORT': os.getenv('BOX_PROCESSOR_PORT', '5001 (default)'),
|
|
'BOX_USE_POLLING': os.getenv('BOX_USE_POLLING', 'false (default)'),
|
|
'BOX_POLL_INTERVAL_SECONDS': os.getenv('BOX_POLL_INTERVAL_SECONDS', '60 (default)'),
|
|
}
|
|
|
|
all_ok = True
|
|
for key, value in vars_to_check.items():
|
|
status = '✓' if value and value != '(not set)' else '⚠'
|
|
if key == 'BOX_AS_USER_ID':
|
|
status = '⚠' # optional but flagged
|
|
print(f" {status} {key}: {value}")
|
|
if key == 'BOX_VIDEO_OPTIMIZER_FOLDER_ID' and not value:
|
|
all_ok = False
|
|
|
|
if not BOX_VIDEO_OPTIMIZER_FOLDER_ID:
|
|
print("\n ✗ BOX_VIDEO_OPTIMIZER_FOLDER_ID is required — add it to .env")
|
|
all_ok = False
|
|
|
|
return all_ok
|
|
|
|
|
|
def authenticate_and_discover():
|
|
print_section("3. Authenticating with Box")
|
|
|
|
try:
|
|
from box_client import BoxClient
|
|
except ImportError as e:
|
|
print(f" ✗ Could not import BoxClient: {e}")
|
|
print(" Make sure you are running from the backend/ directory")
|
|
print(" and that boxsdk is installed: pip install boxsdk[jwt]")
|
|
return None
|
|
|
|
client = BoxClient(
|
|
config_path=os.path.abspath(BOX_CONFIG_PATH),
|
|
as_user_id=BOX_AS_USER_ID
|
|
)
|
|
|
|
if not client.authenticate():
|
|
print(" ✗ Authentication failed — check credentials in oliver_box_config.json")
|
|
return None
|
|
|
|
return client
|
|
|
|
|
|
def list_users(box_client):
|
|
print_section("4. Enterprise Users (to identify BOX_AS_USER_ID)")
|
|
|
|
if BOX_AS_USER_ID:
|
|
print(f" BOX_AS_USER_ID already set: {BOX_AS_USER_ID}")
|
|
print(" Skipping user listing. Remove BOX_AS_USER_ID from .env to list all users.")
|
|
return
|
|
|
|
print(" Listing enterprise users so you can identify the correct BOX_AS_USER_ID:")
|
|
print(" (The user who owns/manages the VIDEO_OPTIMIZER Box folder)\n")
|
|
|
|
try:
|
|
users = box_client.list_enterprise_users()
|
|
if not users:
|
|
print(" ⚠ No users returned. The service account may not have user listing rights.")
|
|
print(" Ask DJP for the Box user ID of the folder owner.")
|
|
except Exception as e:
|
|
print(f" ⚠ Could not list users: {e}")
|
|
print(" This is not critical — ask DJP for the folder owner's Box user ID.")
|
|
|
|
|
|
def list_accessible_folders(box_client):
|
|
"""List folders the service account can already see (shared with it or owned by it)"""
|
|
print_section("4b. Folders Accessible to Service Account")
|
|
print(" Listing top-level folders the service account can see.")
|
|
print(" If VIDEO_OPTIMIZER is here, copy its ID into BOX_VIDEO_OPTIMIZER_FOLDER_ID in .env\n")
|
|
|
|
try:
|
|
items = box_client.client.folder('0').get_items(limit=100)
|
|
found = False
|
|
for item in items:
|
|
found = True
|
|
marker = " ← looks like it!" if 'video' in item.name.lower() or 'optimizer' in item.name.lower() else ""
|
|
print(f" [{item.type:6}] ID: {item.id:20} Name: {item.name}{marker}")
|
|
if not found:
|
|
print(" (no items — the service account hasn't had any folders shared with it yet)")
|
|
print()
|
|
print(" To fix: In Box, right-click the VIDEO_OPTIMIZER folder → Share → Invite")
|
|
print(" Invite this email as Editor:")
|
|
print(" AutomationUser_2499781_HJdLm0ZhaO@boxdevedition.com")
|
|
except Exception as e:
|
|
print(f" ⚠ Could not list accessible folders: {e}")
|
|
|
|
|
|
def discover_folders(box_client):
|
|
print_section("5. Discovering Box Folders")
|
|
|
|
if not BOX_VIDEO_OPTIMIZER_FOLDER_ID:
|
|
print(" ✗ BOX_VIDEO_OPTIMIZER_FOLDER_ID not set — cannot discover folders")
|
|
print(" Set it in .env then re-run this script.")
|
|
return {}
|
|
|
|
print(f" Looking inside folder ID: {BOX_VIDEO_OPTIMIZER_FOLDER_ID}")
|
|
folders = box_client.discover_folders(BOX_VIDEO_OPTIMIZER_FOLDER_ID)
|
|
|
|
if not folders:
|
|
print("\n ✗ No sub-folders found.")
|
|
print(" Make sure the following folders exist inside the VIDEO_OPTIMIZER folder:")
|
|
print(" IN — drop raw videos here")
|
|
print(" OUT_SUCCESS — successfully optimised videos + reports")
|
|
print(" OUT_FAILED — error reports for invalid/failed files")
|
|
print("\n Also ensure the Box service account has been shared on the VIDEO_OPTIMIZER folder.")
|
|
else:
|
|
required = ['IN', 'OUT_SUCCESS', 'OUT_FAILED']
|
|
missing = [r for r in required if r not in folders]
|
|
if missing:
|
|
print(f"\n ⚠ Missing folders: {missing}")
|
|
print(" Create these folders inside the VIDEO_OPTIMIZER folder in Box.")
|
|
|
|
return folders
|
|
|
|
|
|
def print_summary(folders):
|
|
print_section("6. Summary & Next Steps")
|
|
|
|
ready = bool(folders and all(f in folders for f in ['IN', 'OUT_SUCCESS', 'OUT_FAILED']))
|
|
|
|
if ready:
|
|
print(" ✓ Box integration is configured and folders are accessible.")
|
|
print("\n To start the service:")
|
|
print(" # Development (polling mode — no public URL needed):")
|
|
print(" BOX_USE_POLLING=true python backend/box_processor.py")
|
|
print()
|
|
print(" # Development (webhook mode — requires ngrok):")
|
|
print(" ngrok http 5001")
|
|
print(" # Then configure a Box webhook pointing to: https://<ngrok-url>/webhooks/box")
|
|
print(" python backend/box_processor.py")
|
|
print()
|
|
print(" # Test a specific file from the IN folder:")
|
|
print(" python backend/test_box_processor.py")
|
|
print()
|
|
print(" Folder IDs to note:")
|
|
for name, fid in folders.items():
|
|
print(f" {name:15} → {fid}")
|
|
else:
|
|
print(" ✗ Setup incomplete — resolve the issues above before starting the service.")
|
|
print()
|
|
print(" Common fixes:")
|
|
print(" 1. Create IN, OUT_SUCCESS, OUT_FAILED folders inside the VIDEO_OPTIMIZER folder")
|
|
print(" 2. Share the VIDEO_OPTIMIZER folder with the Box service account")
|
|
print(" 3. Set BOX_AS_USER_ID in .env if the folder is owned by a specific user")
|
|
print(" 4. Contact DJP for the folder IDs and correct user ID")
|
|
|
|
if not BOX_AS_USER_ID:
|
|
print()
|
|
print(" ⚠ BOX_AS_USER_ID is not set.")
|
|
print(" If the VIDEO_OPTIMIZER folder is owned by a specific Box user (not the")
|
|
print(" service account), set BOX_AS_USER_ID in .env to that user's ID.")
|
|
print(" Use the user list printed in step 4 above to identify the correct ID.")
|
|
|
|
if not os.getenv('BOX_WEBHOOK_SECRET'):
|
|
print()
|
|
print(" ⚠ BOX_WEBHOOK_SECRET is not set.")
|
|
print(" This is only required when using webhook mode.")
|
|
print(" Generate one and set it in both .env and the Box webhook configuration.")
|
|
|
|
print()
|
|
|
|
|
|
def main():
|
|
print("\n" + "=" * 70)
|
|
print(" BOX.COM SETUP & DIAGNOSTIC")
|
|
print("=" * 70)
|
|
|
|
# Step 1
|
|
if not check_config_file():
|
|
sys.exit(1)
|
|
|
|
# Step 2
|
|
check_env_vars()
|
|
|
|
# Step 3
|
|
box_client = authenticate_and_discover()
|
|
if not box_client:
|
|
sys.exit(1)
|
|
|
|
# Step 4
|
|
list_users(box_client)
|
|
|
|
# Step 4b
|
|
list_accessible_folders(box_client)
|
|
|
|
# Step 5
|
|
folders = discover_folders(box_client)
|
|
|
|
# Step 6
|
|
print_summary(folders)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|