Show public activities to everrybody

This commit is contained in:
Tim Zöller 2025-12-02 22:01:27 +01:00
parent 9c745cf07d
commit d47daa6dfc
3 changed files with 39 additions and 8 deletions

View file

@ -71,6 +71,9 @@ public class SecurityConfig {
// Public endpoints - Timeline API (read-only) // Public endpoints - Timeline API (read-only)
.requestMatchers(HttpMethod.GET, "/api/timeline/public").permitAll() .requestMatchers(HttpMethod.GET, "/api/timeline/public").permitAll()
// Public endpoints - Individual activity details (GET only, for public activities)
.requestMatchers(HttpMethod.GET, "/api/activities/*").permitAll()
// Public endpoints - Activity track data (for public activities) // Public endpoints - Activity track data (for public activities)
.requestMatchers(HttpMethod.GET, "/api/activities/*/track").permitAll() .requestMatchers(HttpMethod.GET, "/api/activities/*/track").permitAll()
@ -90,8 +93,11 @@ public class SecurityConfig {
.requestMatchers(HttpMethod.POST, "/api/activities/*/comments").authenticated() .requestMatchers(HttpMethod.POST, "/api/activities/*/comments").authenticated()
.requestMatchers(HttpMethod.DELETE, "/api/activities/*/comments/*").authenticated() .requestMatchers(HttpMethod.DELETE, "/api/activities/*/comments/*").authenticated()
// Protected endpoints - Activities API // Protected endpoints - Activities API (upload, edit, delete)
.requestMatchers("/api/activities/**").authenticated() .requestMatchers(HttpMethod.POST, "/api/activities/upload").authenticated()
.requestMatchers(HttpMethod.PUT, "/api/activities/*").authenticated()
.requestMatchers(HttpMethod.DELETE, "/api/activities/*").authenticated()
.requestMatchers(HttpMethod.GET, "/api/activities").authenticated() // List of user's own activities
// Protected endpoints - Timeline API (user-specific) // Protected endpoints - Timeline API (user-specific)
.requestMatchers("/api/timeline/**").authenticated() .requestMatchers("/api/timeline/**").authenticated()

View file

@ -208,9 +208,11 @@ public class ActivityController {
/** /**
* Retrieves an activity by ID. * Retrieves an activity by ID.
* Public activities can be viewed without authentication.
* Non-public activities require authentication and ownership/follower access.
* *
* @param id the activity ID * @param id the activity ID
* @param userDetails the authenticated user * @param userDetails the authenticated user (optional)
* @return the activity * @return the activity
*/ */
@GetMapping("/{id}") @GetMapping("/{id}")
@ -218,14 +220,33 @@ public class ActivityController {
@PathVariable UUID id, @PathVariable UUID id,
@AuthenticationPrincipal UserDetails userDetails @AuthenticationPrincipal UserDetails userDetails
) { ) {
UUID userId = getUserId(userDetails); // First try to get the activity directly
Activity activity = fitFileService.getActivityById(id);
Activity activity = fitFileService.getActivity(id, userId);
if (activity == null) { if (activity == null) {
return ResponseEntity.notFound().build(); return ResponseEntity.notFound().build();
} }
ActivityDTO dto = ActivityDTO.fromEntity(activity); // Check visibility
if (activity.getVisibility() == Activity.Visibility.PUBLIC) {
// Public activities are always accessible
ActivityDTO dto = ActivityDTO.fromEntity(activity);
return ResponseEntity.ok(dto);
}
// For non-public activities, require authentication
if (userDetails == null) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
UUID userId = getUserId(userDetails);
// Check if user has access (owner or follower)
Activity checkedActivity = fitFileService.getActivity(id, userId);
if (checkedActivity == null) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
ActivityDTO dto = ActivityDTO.fromEntity(checkedActivity);
return ResponseEntity.ok(dto); return ResponseEntity.ok(dto);
} }

View file

@ -595,12 +595,16 @@
// Setup like button click handler // Setup like button click handler
document.getElementById('likeBtn').addEventListener('click', handleLikeClick); document.getElementById('likeBtn').addEventListener('click', handleLikeClick);
// Show comment form for authenticated users
document.getElementById('commentForm').style.display = 'block';
// Setup comment form submit handler // Setup comment form submit handler
document.getElementById('addCommentForm').addEventListener('submit', handleCommentSubmit); document.getElementById('addCommentForm').addEventListener('submit', handleCommentSubmit);
} else { } else {
// Show login prompt for non-authenticated users // Show login prompt for non-authenticated users
document.getElementById('loginPrompt').style.display = 'block'; document.getElementById('loginPrompt').style.display = 'block';
document.getElementById('likeBtn').disabled = true; // Hide like button for non-authenticated users
document.getElementById('likeBtn').style.display = 'none';
} }
} }