target fix
This commit is contained in:
@@ -7,6 +7,7 @@ import kz.konturai.parser.service.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -35,11 +36,13 @@ public class TargetingCampaignController {
|
||||
if (StringUtils.hasText(userIdHeader)) {
|
||||
return userIdHeader;
|
||||
}
|
||||
String userId = jwtService.extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) {
|
||||
throw new IllegalArgumentException("Cannot resolve user identity: X-User-Id header or valid Authorization token required");
|
||||
try {
|
||||
String userId = jwtService.extractUserIdFromHeader(authHeader);
|
||||
return userId; // Может быть null если токен истёк
|
||||
} catch (Exception e) {
|
||||
log.warn("[Targeting] Failed to extract userId from token: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
@PostMapping("/campaigns")
|
||||
@@ -48,6 +51,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@RequestBody TargetingCampaignRequest request) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Create campaign requested by {}", userId);
|
||||
return ResponseEntity.ok(campaignService.createCampaign(request, userId));
|
||||
}
|
||||
@@ -59,6 +64,8 @@ public class TargetingCampaignController {
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Get campaigns for {}", userId);
|
||||
return ResponseEntity.ok(campaignService.getUserCampaigns(userId, page, size));
|
||||
}
|
||||
@@ -69,6 +76,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Get campaign {} for {}", id, userId);
|
||||
return ResponseEntity.ok(campaignService.getCampaignById(id, userId));
|
||||
}
|
||||
@@ -79,6 +88,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Pause campaign {}", id);
|
||||
return ResponseEntity.ok(campaignService.pauseCampaign(id, userId));
|
||||
}
|
||||
@@ -89,6 +100,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Resume campaign {}", id);
|
||||
return ResponseEntity.ok(campaignService.resumeCampaign(id, userId));
|
||||
}
|
||||
@@ -100,6 +113,8 @@ public class TargetingCampaignController {
|
||||
@PathVariable String id,
|
||||
@RequestParam(defaultValue = "last_7d") String datePreset) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Get insights for campaign {}", id);
|
||||
return ResponseEntity.ok(campaignService.getCampaignInsights(id, userId, datePreset));
|
||||
}
|
||||
@@ -110,6 +125,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Force sync insights for campaign {}", id);
|
||||
campaignService.getCampaignById(id, userId);
|
||||
campaignService.syncInsights(id);
|
||||
@@ -122,6 +139,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Evaluate AB Test for {}", id);
|
||||
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
||||
return ResponseEntity.ok(abTestingService.evaluateABTest(campaign));
|
||||
@@ -158,6 +177,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@RequestBody Map<String, String> body) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
String campaignId = body.get("campaignId");
|
||||
log.info("[Targeting] Optimize budget for campaign {}", campaignId);
|
||||
TargetingCampaign campaign = campaignService.getCampaignById(campaignId, userId);
|
||||
@@ -173,6 +194,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@RequestBody Map<String, String> body) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
String platform = body.get("platform");
|
||||
String adAccountId = body.get("adAccountId");
|
||||
|
||||
@@ -190,6 +213,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
||||
String status = campaign.getStatus();
|
||||
boolean isTerminal = "active".equals(status) || "failed".equals(status) || "paused".equals(status);
|
||||
@@ -210,6 +235,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
// Проверяем существование кампании и права доступа
|
||||
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
||||
|
||||
@@ -224,8 +251,7 @@ public class TargetingCampaignController {
|
||||
|
||||
return ResponseEntity.accepted().body(Map.of(
|
||||
"status", "PROCESSING",
|
||||
"message", "Предсказание еще не готово и было запущено автоматически. Попробуйте через 5-10 секунд."
|
||||
));
|
||||
"message", "Предсказание еще не готово и было запущено автоматически. Попробуйте через 5-10 секунд."));
|
||||
}
|
||||
|
||||
@PostMapping("/campaigns/{id}/predict")
|
||||
@@ -234,6 +260,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
||||
log.info("[Targeting] Manual predict trigger for campaign {}", id);
|
||||
predictionService.generateAsync(campaign);
|
||||
@@ -248,6 +276,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
||||
return ResponseEntity.ok(campaign.getInsights() != null ? campaign.getInsights() : List.of());
|
||||
}
|
||||
@@ -260,6 +290,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Retry campaign {}", id);
|
||||
return ResponseEntity.ok(campaignService.retryCampaign(id, userId));
|
||||
}
|
||||
@@ -273,6 +305,8 @@ public class TargetingCampaignController {
|
||||
@PathVariable String id,
|
||||
@RequestBody Map<String, Double> body) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Update budget for campaign {}", id);
|
||||
return ResponseEntity.ok(campaignService.updateBudget(id, userId,
|
||||
body.get("totalBudget"), body.get("dailyBudget")));
|
||||
@@ -285,6 +319,8 @@ public class TargetingCampaignController {
|
||||
@PathVariable String id,
|
||||
@RequestBody TargetingAudienceProfile audience) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Update audience for campaign {}", id);
|
||||
return ResponseEntity.ok(campaignService.updateAudience(id, userId, audience));
|
||||
}
|
||||
@@ -297,33 +333,39 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String strategyId) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Direct Facebook publish for strategy {} requested by {}", strategyId, userId);
|
||||
|
||||
|
||||
try {
|
||||
String postId = marketingStrategyV3Service.publishFirstFacebookPost(strategyId);
|
||||
return ResponseEntity.ok(Map.of(
|
||||
"success", true,
|
||||
"message", "Пост успешно опубликован в Facebook",
|
||||
"postId", postId
|
||||
));
|
||||
"postId", postId));
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "error", e.getMessage()));
|
||||
} catch (kz.konturai.parser.exception.FacebookTokenExpiredException e) {
|
||||
log.error("Facebook token expired: {}", e.getMessage());
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "error", "Токен Facebook истёк. Пожалуйста, обновите токен (facebook.page.token) в файле application.properties."));
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "error",
|
||||
"Токен Facebook истёк. Пожалуйста, обновите токен (facebook.page.token) в файле application.properties."));
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getMessage() != null && e.getMessage().contains("[Facebook] API Error")) {
|
||||
log.error("Facebook API Error: {}", e.getMessage());
|
||||
if (e.getMessage().contains("publish_actions")) {
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "error", "Указан токен Пользователя, а не Страницы (User Token). Facebook запрещает публикацию через личные токены. Сгенерируйте именно Page Access Token."));
|
||||
}
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "error", "Ошибка со стороны Facebook API: " + e.getMessage()));
|
||||
log.error("Facebook API Error: {}", e.getMessage());
|
||||
if (e.getMessage().contains("publish_actions")) {
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "error",
|
||||
"Указан токен Пользователя, а не Страницы (User Token). Facebook запрещает публикацию через личные токены. Сгенерируйте именно Page Access Token."));
|
||||
}
|
||||
return ResponseEntity.badRequest()
|
||||
.body(Map.of("success", false, "error", "Ошибка со стороны Facebook API: " + e.getMessage()));
|
||||
}
|
||||
log.error("Failed to publish post: ", e);
|
||||
return ResponseEntity.internalServerError().body(Map.of("success", false, "error", "Не удалось опубликовать пост"));
|
||||
return ResponseEntity.internalServerError()
|
||||
.body(Map.of("success", false, "error", "Не удалось опубликовать пост"));
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to publish post: ", e);
|
||||
return ResponseEntity.internalServerError().body(Map.of("success", false, "error", "Не удалось опубликовать пост"));
|
||||
return ResponseEntity.internalServerError()
|
||||
.body(Map.of("success", false, "error", "Не удалось опубликовать пост"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,6 +377,8 @@ public class TargetingCampaignController {
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String id) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
return ResponseEntity.ok(campaignService.getAdSets(id, userId));
|
||||
}
|
||||
|
||||
@@ -346,7 +390,27 @@ public class TargetingCampaignController {
|
||||
@PathVariable String adSetId,
|
||||
@RequestBody TargetingAdSet adSet) {
|
||||
String userId = resolveUserId(userIdHeader, authHeader);
|
||||
if (userId == null)
|
||||
return unauthorizedResponse();
|
||||
log.info("[Targeting] Update adSet {} for campaign {}", adSetId, id);
|
||||
return ResponseEntity.ok(campaignService.updateAdSet(id, adSetId, userId, adSet));
|
||||
}
|
||||
|
||||
// ── Helper methods ───────────────────────────────────────────────────────
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> ResponseEntity<T> unauthorizedResponse() {
|
||||
return (ResponseEntity<T>) ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body(ApiResponse.error(
|
||||
"Не авторизован",
|
||||
new ErrorResponse("UNAUTHORIZED", "Требуется авторизация. Предоставьте валидный JWT токен.")));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> ResponseEntity<T> forbiddenResponse() {
|
||||
return (ResponseEntity<T>) ResponseEntity.status(HttpStatus.FORBIDDEN)
|
||||
.body(ApiResponse.error(
|
||||
"Доступ запрещён",
|
||||
new ErrorResponse("FORBIDDEN", "У вас нет прав для доступа к этому ресурсу.")));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user