mirror of
https://gitea.gofwd.group/Forward_Group/ballistic-builder-spring.git
synced 2026-01-20 08:41:04 -05:00
added support for a new builds/detials page and endpoints
This commit is contained in:
@@ -37,19 +37,29 @@ public class SecurityConfig {
|
||||
.cors(c -> c.configurationSource(corsConfigurationSource()))
|
||||
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
// public
|
||||
|
||||
// ----------------------------
|
||||
// Public
|
||||
// ----------------------------
|
||||
.requestMatchers("/api/auth/**").permitAll()
|
||||
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
|
||||
.requestMatchers("/actuator/health", "/actuator/info").permitAll()
|
||||
.requestMatchers("/api/products/gunbuilder/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/builds").permitAll()
|
||||
|
||||
// protected
|
||||
// Public builds feed + public build detail (1 path segment only)
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/builds").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/builds/*").permitAll()
|
||||
|
||||
// ----------------------------
|
||||
// Protected
|
||||
// ----------------------------
|
||||
.requestMatchers("/api/v1/builds/me/**").authenticated()
|
||||
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
|
||||
// everything else (adjust later as you lock down)
|
||||
|
||||
// Everything else (adjust later as you lock down)
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
|
||||
// run JWT before AnonymousAuth sets principal="anonymousUser"
|
||||
.addFilterBefore(jwtAuthenticationFilter, AnonymousAuthenticationFilter.class);
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import group.goforward.battlbuilder.web.dto.BuildDto;
|
||||
import group.goforward.battlbuilder.web.dto.BuildFeedCardDto;
|
||||
import group.goforward.battlbuilder.web.dto.BuildSummaryDto;
|
||||
import group.goforward.battlbuilder.web.dto.UpdateBuildRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -34,6 +34,15 @@ public class BuildV1Controller {
|
||||
return ResponseEntity.ok(buildService.listPublicBuilds(limit == null ? 50 : limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Public build detail for /builds/{uuid}
|
||||
* GET /api/v1/builds/{uuid}
|
||||
*/
|
||||
@GetMapping("/{uuid}")
|
||||
public ResponseEntity<BuildDto> getPublicBuild(@PathVariable("uuid") UUID uuid) {
|
||||
return ResponseEntity.ok(buildService.getPublicBuild(uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Vault builds (authenticated user).
|
||||
* GET /api/v1/builds/me?limit=100
|
||||
@@ -75,7 +84,6 @@ public class BuildV1Controller {
|
||||
return ResponseEntity.ok(buildService.updateMyBuild(uuid, req));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a build (authenticated user; must own build).
|
||||
* DELETE /api/v1/builds/me/{uuid}
|
||||
|
||||
@@ -17,5 +17,8 @@ public interface BuildRepository extends JpaRepository<Build, Integer> {
|
||||
|
||||
Page<Build> findByUserIdAndDeletedAtIsNullOrderByUpdatedAtDesc(Integer userId, Pageable pageable);
|
||||
|
||||
Optional<Build> findByUuidAndIsPublicTrueAndDeletedAtIsNull(UUID uuid);
|
||||
|
||||
Optional<Build> findByUuidAndDeletedAtIsNull(UUID uuid);
|
||||
|
||||
}
|
||||
@@ -20,5 +20,7 @@ public interface BuildService {
|
||||
|
||||
BuildDto updateMyBuild(UUID uuid, UpdateBuildRequest req);
|
||||
|
||||
BuildDto getPublicBuild(UUID uuid);
|
||||
|
||||
void deleteMyBuild(UUID uuid);
|
||||
}
|
||||
@@ -112,6 +112,31 @@ public class BuildServiceImpl implements BuildService {
|
||||
.toList();
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Public build detail (/builds/{uuid})
|
||||
// GET /api/v1/builds/public/{uuid}
|
||||
// ---------------------------
|
||||
@Override
|
||||
public BuildDto getPublicBuild(UUID uuid) {
|
||||
if (uuid == null) throw new IllegalArgumentException("uuid is required");
|
||||
|
||||
Build build = buildRepository.findByUuidAndDeletedAtIsNull(uuid)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Build not found"));
|
||||
|
||||
// Only allow public builds here (and not deleted)
|
||||
if (!Boolean.TRUE.equals(build.getIsPublic())) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Build not found");
|
||||
}
|
||||
|
||||
List<BuildItem> items = buildItemRepository.findByBuild_Id(build.getId());
|
||||
|
||||
BuildDto dto = toBuildDto(build, items);
|
||||
hydrateBuildDtoItems(dto); // keep consistent with getMyBuild
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------
|
||||
// Vault list (/builds/me)
|
||||
// ---------------------------
|
||||
|
||||
@@ -7,7 +7,18 @@ public interface EmailService {
|
||||
|
||||
EmailRequest sendEmailHtml(String recipient, String subject, String htmlBody, String textBody);
|
||||
|
||||
EmailRequest sendEmailHtml(String recipient, String subject, String htmlBody, String textBody, String templateKey);
|
||||
// ✅ convenience overload for templates
|
||||
default EmailRequest sendEmailHtml(
|
||||
String recipient,
|
||||
String subject,
|
||||
String htmlBody,
|
||||
String textBody,
|
||||
String templateKey
|
||||
) {
|
||||
EmailRequest req = sendEmailHtml(recipient, subject, htmlBody, textBody);
|
||||
req.setTemplateKey(templateKey);
|
||||
return req;
|
||||
}
|
||||
|
||||
void deleteById(Integer id);
|
||||
}
|
||||
Reference in New Issue
Block a user