mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
feat(oauth): add client_credentials grant for machine clients and fix PlaceAvatar stale image retry
- Add OAuth 2.0 client_credentials flow so AI agents and scripts can obtain tokens directly via client_id + client_secret without any browser interaction - New DB column allows_client_credentials on oauth_clients; machine clients skip redirect URI requirement and are forced confidential - New issueClientCredentialsToken() issues access-only tokens (no refresh token, RFC 6749 §4.4) - UI: "Machine client" checkbox in create-client modal, hides redirect URI field, shows indigo badge on existing machine clients - Advertise client_credentials in OAuth discovery document - 8 new integration tests (OAUTH-CC-001–008) - i18n: 4 new keys across all 15 languages - Fix PlaceAvatar: re-fetch photo via API on image_url load failure before falling back to initials - Update MCP wiki docs with new Option B machine client setup guide
This commit is contained in:
@@ -18,6 +18,7 @@ interface PlaceAvatarProps {
|
||||
export default React.memo(function PlaceAvatar({ place, size = 32, category }: PlaceAvatarProps) {
|
||||
const [photoSrc, setPhotoSrc] = useState<string | null>(place.image_url || null)
|
||||
const [visible, setVisible] = useState(false)
|
||||
const imageUrlFailed = useRef(false)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const placesPhotosEnabled = useAuthStore(s => s.placesPhotosEnabled)
|
||||
|
||||
@@ -86,7 +87,18 @@ export default React.memo(function PlaceAvatar({ place, size = 32, category }: P
|
||||
alt={place.name}
|
||||
decoding="async"
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||
onError={() => setPhotoSrc(null)}
|
||||
onError={() => {
|
||||
if (!imageUrlFailed.current && photoSrc === place.image_url && (place.google_place_id || place.osm_id)) {
|
||||
imageUrlFailed.current = true
|
||||
const photoId = place.google_place_id || place.osm_id!
|
||||
const cacheKey = `refetch:${photoId}`
|
||||
fetchPhoto(cacheKey, photoId, place.lat ?? undefined, place.lng ?? undefined, place.name,
|
||||
entry => { setPhotoSrc(entry.thumbDataUrl || entry.photoUrl) }
|
||||
)
|
||||
} else {
|
||||
setPhotoSrc(null)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user