feat: add Dockerfile2

This commit is contained in:
simple321vip
2026-07-10 10:59:01 +08:00
parent 844f578601
commit 16af9c5f4d
5 changed files with 235 additions and 61 deletions
@@ -1,20 +1,27 @@
package cn.violin.iam.controller;
import cn.violin.core.entity.UserEntity;
import cn.violin.core.iam.CheckRequest;
import cn.violin.core.iam.CheckResult;
import cn.violin.core.iam.CustomerBindingResponse;
import cn.violin.iam.dto.SubjectAccessReviewRequest;
import cn.violin.iam.dto.SubjectAccessReviewResponse;
import cn.violin.iam.mapper.UserMapper;
import cn.violin.iam.security.ServiceAllowlist;
import cn.violin.iam.security.ServiceAuthValidator;
import cn.violin.iam.service.SubjectAccessReviewService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
@RequestMapping("/api/v1/internal")
@RequiredArgsConstructor
@@ -24,6 +31,7 @@ public class InternalController {
private final SubjectAccessReviewService sarService;
private final ServiceAuthValidator serviceAuth;
private final ServiceAllowlist allowlist;
private final UserMapper userMapper;
@PostMapping("/check-permission")
public CheckResult checkPermission(HttpServletRequest httpReq,
@@ -49,4 +57,44 @@ public class InternalController {
.reason(resp.getReason())
.build();
}
/**
* Resolve the authoritative {@code customerId} for a given Authentik {@code sub}.
*
* <p>Service-to-service channel only: caller must present a valid
* {@code X-Service-*} HMAC; {@link ServiceAuthValidator#verifyAndReturnService}
* ensures non-empty service id and {@link ServiceAllowlist} is consulted
* downstream services can decide whether {@code sub} belongs to a customer
* they're allowed to read.</p>
*
* <p>The returned binding carries {@code active=true} when we observed a
* live {@code t_user} row with {@code is_deleted=false} AND a non-null
* {@code customer_id}; otherwise {@code active=false} so callers can
* distinguish "no binding" from "binding to unknown tenant".</p>
*/
@GetMapping("/users/{sub}/customer")
public CustomerBindingResponse resolveCustomer(HttpServletRequest httpReq,
@PathVariable String sub) {
// Reject unauthenticated callers.
serviceAuth.verifyAndReturnService(httpReq);
Optional<UserEntity> opt = userMapper.selectByUserId(sub);
if (opt.isEmpty()) {
return CustomerBindingResponse.builder()
.sub(sub)
.customerId(null)
.active(false)
.build();
}
UserEntity user = opt.get();
String customerId = user.getCustomerId();
boolean active = customerId != null
&& !customerId.isBlank()
&& Boolean.FALSE.equals(user.getIsDeleted());
return CustomerBindingResponse.builder()
.sub(sub)
.customerId(active ? customerId : null)
.active(active)
.build();
}
}