Open public routes

This commit is contained in:
2025-12-10 13:37:27 +01:00
parent 8e43ad0ff1
commit 6a15569d0c
4 changed files with 32 additions and 20 deletions

View File

@@ -2,6 +2,7 @@ package com.imgfloat.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -30,6 +31,10 @@ public class SecurityConfig {
"/swagger-ui.html",
"/swagger-ui/**"
).permitAll()
.requestMatchers(HttpMethod.GET, "/view/*/broadcast").permitAll()
.requestMatchers(HttpMethod.GET, "/api/channels/*/assets/visible").permitAll()
.requestMatchers(HttpMethod.GET, "/api/channels/*/canvas").permitAll()
.requestMatchers(HttpMethod.GET, "/api/channels/*/assets/*/content").permitAll()
.requestMatchers("/ws/**").permitAll()
.anyRequest().authenticated()
)

View File

@@ -107,20 +107,12 @@ public class ChannelApiController {
}
@GetMapping("/assets/visible")
public Collection<AssetView> listVisible(@PathVariable("broadcaster") String broadcaster,
OAuth2AuthenticationToken authentication) {
String login = TwitchUser.from(authentication).login();
if (!channelDirectoryService.isBroadcaster(broadcaster, login)) {
throw new ResponseStatusException(FORBIDDEN, "Only broadcaster can load public overlay");
}
public Collection<AssetView> listVisible(@PathVariable("broadcaster") String broadcaster) {
return channelDirectoryService.getVisibleAssets(broadcaster);
}
@GetMapping("/canvas")
public CanvasSettingsRequest getCanvas(@PathVariable("broadcaster") String broadcaster,
OAuth2AuthenticationToken authentication) {
String login = TwitchUser.from(authentication).login();
ensureAuthorized(broadcaster, login);
public CanvasSettingsRequest getCanvas(@PathVariable("broadcaster") String broadcaster) {
return channelDirectoryService.getCanvasSettings(broadcaster);
}
@@ -179,8 +171,14 @@ public class ChannelApiController {
public ResponseEntity<byte[]> getAssetContent(@PathVariable("broadcaster") String broadcaster,
@PathVariable("assetId") String assetId,
OAuth2AuthenticationToken authentication) {
boolean authorized = false;
if (authentication != null) {
String login = TwitchUser.from(authentication).login();
ensureAuthorized(broadcaster, login);
authorized = channelDirectoryService.isBroadcaster(broadcaster, login)
|| channelDirectoryService.isAdmin(broadcaster, login);
}
if (authorized) {
return channelDirectoryService.getAssetContent(broadcaster, assetId)
.map(content -> ResponseEntity.ok()
.contentType(MediaType.parseMediaType(content.mediaType()))
@@ -188,6 +186,13 @@ public class ChannelApiController {
.orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Asset not found"));
}
return channelDirectoryService.getVisibleAssetContent(broadcaster, assetId)
.map(content -> ResponseEntity.ok()
.contentType(MediaType.parseMediaType(content.mediaType()))
.body(content.bytes()))
.orElseThrow(() -> new ResponseStatusException(FORBIDDEN, "Asset not available"));
}
@DeleteMapping("/assets/{assetId}")
public ResponseEntity<?> delete(@PathVariable("broadcaster") String broadcaster,
@PathVariable("assetId") String assetId,

View File

@@ -44,14 +44,8 @@ public class ViewController {
@org.springframework.web.bind.annotation.GetMapping("/view/{broadcaster}/broadcast")
public String broadcastView(@org.springframework.web.bind.annotation.PathVariable("broadcaster") String broadcaster,
OAuth2AuthenticationToken authentication,
Model model) {
String login = TwitchUser.from(authentication).login();
if (!channelDirectoryService.isBroadcaster(broadcaster, login)) {
throw new ResponseStatusException(FORBIDDEN, "Only the broadcaster can render this view");
}
model.addAttribute("broadcaster", broadcaster.toLowerCase());
model.addAttribute("username", login);
return "broadcast";
}
}

View File

@@ -219,6 +219,14 @@ public class ChannelDirectoryService {
.flatMap(this::decodeAssetData);
}
public Optional<AssetContent> getVisibleAssetContent(String broadcaster, String assetId) {
String normalized = normalize(broadcaster);
return assetRepository.findById(assetId)
.filter(asset -> normalized.equals(asset.getBroadcaster()))
.filter(asset -> !asset.isHidden())
.flatMap(this::decodeAssetData);
}
public boolean isBroadcaster(String broadcaster, String username) {
return broadcaster != null && broadcaster.equalsIgnoreCase(username);
}