guardia-mall/backend/src/main/java/com/zioinfo/mall/member/MemberController.java

68 lines
2.7 KiB
Java

package com.zioinfo.mall.member;
import com.zioinfo.mall.common.ApiResponse;
import com.zioinfo.mall.integration.CrmClient;
import com.zioinfo.mall.integration.ItsmSecuritySanitizer;
import com.zioinfo.mall.member.mapper.MemberMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** 회원 API — /api/mall/member. 본인 프로필 + CRM 인사이트 연계(새니타이즈). */
@RestController
@RequestMapping("/api/mall/member")
@RequiredArgsConstructor
public class MemberController {
private final MemberMapper mapper;
private final CrmClient crmClient;
@GetMapping("/me")
public ApiResponse<MallMember> me(Authentication auth) {
return ApiResponse.ok(mapper.findByUsername(auth.getName()));
}
@PutMapping("/me")
public ApiResponse<MallMember> update(@RequestBody MallMember m, Authentication auth) {
m.setUsername(auth.getName());
mapper.upsert(m);
return ApiResponse.ok(mapper.findByUsername(auth.getName()));
}
/**
* 관리자 회원 목록/검색 — MANAGER+ 전용.
*
* <p>보안 불변: 이메일·전화번호는 매퍼에서 마스킹된 값만, 상세 주소는 비포함(MallMemberSummary).
* 주문수·누적결제액 집계 동반. 키워드(아이디/이름)·등급 필터 지원.
*/
@GetMapping("/admin")
@PreAuthorize("hasAnyRole('ADMIN','MANAGER')")
public ApiResponse<Map<String, Object>> adminList(
@RequestParam(required = false) String keyword,
@RequestParam(required = false) String tier,
@RequestParam(defaultValue = "100") int limit) {
int safeLimit = (limit <= 0 || limit > 500) ? 100 : limit;
List<MallMemberSummary> items = mapper.adminList(keyword, tier, safeLimit);
int total = mapper.countAdminList(keyword, tier);
Map<String, Object> out = new LinkedHashMap<>();
out.put("items", items);
out.put("total", total);
return ApiResponse.ok(out);
}
/** CRM 고객 인사이트(구매 성향) — 응답은 ItsmSecuritySanitizer로 정제. */
@GetMapping("/me/insight")
public ApiResponse<Map<String, Object>> insight(Authentication auth) {
Map<String, Object> raw = crmClient.getCustomerInsight(auth.getName());
Object cleaned = ItsmSecuritySanitizer.clean(raw == null ? new LinkedHashMap<>() : raw);
@SuppressWarnings("unchecked")
Map<String, Object> safe = (Map<String, Object>) cleaned;
return ApiResponse.ok(safe);
}
}