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 me(Authentication auth) { return ApiResponse.ok(mapper.findByUsername(auth.getName())); } @PutMapping("/me") public ApiResponse update(@RequestBody MallMember m, Authentication auth) { m.setUsername(auth.getName()); mapper.upsert(m); return ApiResponse.ok(mapper.findByUsername(auth.getName())); } /** * 관리자 회원 목록/검색 — MANAGER+ 전용. * *

보안 불변: 이메일·전화번호는 매퍼에서 마스킹된 값만, 상세 주소는 비포함(MallMemberSummary). * 주문수·누적결제액 집계 동반. 키워드(아이디/이름)·등급 필터 지원. */ @GetMapping("/admin") @PreAuthorize("hasAnyRole('ADMIN','MANAGER')") public ApiResponse> 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 items = mapper.adminList(keyword, tier, safeLimit); int total = mapper.countAdminList(keyword, tier); Map out = new LinkedHashMap<>(); out.put("items", items); out.put("total", total); return ApiResponse.ok(out); } /** CRM 고객 인사이트(구매 성향) — 응답은 ItsmSecuritySanitizer로 정제. */ @GetMapping("/me/insight") public ApiResponse> insight(Authentication auth) { Map raw = crmClient.getCustomerInsight(auth.getName()); Object cleaned = ItsmSecuritySanitizer.clean(raw == null ? new LinkedHashMap<>() : raw); @SuppressWarnings("unchecked") Map safe = (Map) cleaned; return ApiResponse.ok(safe); } }