package com.xuqm.tenant.controller; import com.xuqm.common.model.ApiResponse; import com.xuqm.tenant.dto.CreateAppRequest; import com.xuqm.tenant.entity.AppEntity; import com.xuqm.tenant.entity.TenantEntity; import com.xuqm.tenant.repository.TenantRepository; import com.xuqm.tenant.service.AppService; import com.xuqm.tenant.service.EmailService; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/apps") public class AppController { private final AppService appService; private final EmailService emailService; private final TenantRepository tenantRepository; public AppController(AppService appService, EmailService emailService, TenantRepository tenantRepository) { this.appService = appService; this.emailService = emailService; this.tenantRepository = tenantRepository; } @GetMapping public ResponseEntity>> list(@AuthenticationPrincipal String tenantId) { return ResponseEntity.ok(ApiResponse.success(appService.listByTenant(tenantId))); } @GetMapping("/{id}") public ResponseEntity> get(@PathVariable String id, @AuthenticationPrincipal String tenantId) { return ResponseEntity.ok(ApiResponse.success(appService.getById(id, tenantId))); } @PostMapping public ResponseEntity> create(@Valid @RequestBody CreateAppRequest req, @AuthenticationPrincipal String tenantId) { return ResponseEntity.ok(ApiResponse.success(appService.create(tenantId, req))); } @PutMapping("/{id}") public ResponseEntity> update(@PathVariable String id, @Valid @RequestBody CreateAppRequest req, @AuthenticationPrincipal String tenantId) { return ResponseEntity.ok(ApiResponse.success(appService.update(id, tenantId, req))); } @DeleteMapping("/{id}") public ResponseEntity> delete(@PathVariable String id, @AuthenticationPrincipal String tenantId) { appService.delete(id, tenantId); return ResponseEntity.ok(ApiResponse.ok()); } /** Step 1: send email verification code for secret reveal or reset. */ @PostMapping("/{id}/request-secret-verify") public ResponseEntity> requestSecretVerify( @PathVariable String id, @RequestParam String purpose, @AuthenticationPrincipal String tenantId) { appService.getById(id, tenantId); TenantEntity tenant = tenantRepository.findById(tenantId) .orElseThrow(() -> new RuntimeException("Tenant not found")); emailService.sendVerificationCode(tenant.getEmail(), purpose); return ResponseEntity.ok(ApiResponse.ok()); } /** Step 2a: verify code and return the full appSecret. */ @PostMapping("/{id}/reveal-secret") public ResponseEntity>> revealSecret( @PathVariable String id, @RequestBody Map body, @AuthenticationPrincipal String tenantId) { AppEntity app = appService.getById(id, tenantId); TenantEntity tenant = tenantRepository.findById(tenantId) .orElseThrow(() -> new RuntimeException("Tenant not found")); emailService.verify(tenant.getEmail(), body.get("code"), "REVEAL_SECRET"); return ResponseEntity.ok(ApiResponse.success(Map.of("appSecret", app.getAppSecret()))); } /** Step 2b: verify code and regenerate appSecret (old one invalidated immediately). */ @PostMapping("/{id}/reset-secret") public ResponseEntity>> resetSecret( @PathVariable String id, @RequestBody Map body, @AuthenticationPrincipal String tenantId) { AppEntity app = appService.getById(id, tenantId); TenantEntity tenant = tenantRepository.findById(tenantId) .orElseThrow(() -> new RuntimeException("Tenant not found")); emailService.verify(tenant.getEmail(), body.get("code"), "RESET_SECRET"); String newSecret = appService.resetSecret(id, tenantId); return ResponseEntity.ok(ApiResponse.success(Map.of("appSecret", newSecret))); } }