feat: LDAP avatar support via lldap

- Create tinker-tickets service account in lldap (lldap_strict_readonly)
- Add /api/user_avatar.php: binds to lldap, fetches avatar attribute,
  caches JPEG to uploads/avatars/, returns 404 sentinel for missing photos
- Install php8.2-ldap on LXC 132 (beta) and LXC coding server
- Update layout_header.php: show lt-avatar with photo overlay + initials fallback
- Update TicketView.php: comment avatars use photo overlay pattern
- Add .lt-avatar-img / .lt-avatar-initials CSS for photo-over-initials layout
- Add LDAP_* config keys to config.php and .env.example

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-28 20:47:08 -04:00
parent 87f878ee6b
commit 18bf1fde0e
6 changed files with 243 additions and 5 deletions
+11 -2
View File
@@ -370,11 +370,12 @@ include __DIR__ . '/layout_header.php';
$threadClass = $parentId ? 'comment-reply' : 'comment-root';
$dateStr = date('M d, Y H:i', strtotime($comment['created_at']));
$editedIndicator = !empty($comment['updated_at']) ? ' <span class="comment-edited lt-text-xs lt-text-muted">(edited)</span>' : '';
// Avatar initials + color
// Avatar initials + color (fallback when no photo)
$words = array_filter(explode(' ', $displayName));
$initials = strtoupper(implode('', array_map(fn($w) => $w[0], array_slice($words, 0, 2))));
$avatarColors = ['lt-avatar--orange', 'lt-avatar--green', 'lt-avatar--purple', ''];
$avatarColor = $avatarColors[abs(crc32($displayName)) % count($avatarColors)];
$commentUserId = (int)($comment['user_id'] ?? 0);
?>
<div class="comment <?= $depthClass ?> <?= $threadClass ?>"
data-comment-id="<?= $commentId ?>"
@@ -384,7 +385,15 @@ include __DIR__ . '/layout_header.php';
<?php if ($parentId): ?><div class="thread-line" aria-hidden="true"></div><?php endif ?>
<div class="comment-content">
<div class="comment-header lt-flex lt-flex-gap-sm lt-flex-align-center">
<div class="lt-avatar lt-avatar--xs <?= $avatarColor ?>" aria-hidden="true"><?= htmlspecialchars($initials) ?></div>
<div class="lt-avatar lt-avatar--xs <?= $avatarColor ?>" aria-hidden="true">
<?php if ($commentUserId > 0): ?>
<img src="/api/user_avatar.php?user_id=<?= $commentUserId ?>"
alt=""
class="lt-avatar-img"
onerror="this.style.display='none'">
<?php endif ?>
<span class="lt-avatar-initials"><?= htmlspecialchars($initials) ?></span>
</div>
<span class="comment-user lt-text-amber"><?= htmlspecialchars($displayName) ?></span>
<span class="comment-date lt-text-xs lt-text-muted">
<span class="ts-cell"