package jnpf.elnService.template;
|
|
import jnpf.database.util.TenantDataSourceUtil;
|
import jnpf.elnEntity.ElnDocumentFileVo;
|
import jnpf.elnEntity.template.ElnTemplateVersionEntity;
|
import jnpf.elnMapper.ElnTemplateMapper;
|
import jnpf.util.JsonUtil;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.StringUtils;
|
|
import java.util.List;
|
import java.util.Objects;
|
import java.util.stream.Collectors;
|
|
@Service
|
public class TemplateAnnotationAuthorizer {
|
|
private static final String DRAFT = "DRAFT";
|
private static final String ENABLED = "enabled";
|
|
private final TemplateAnnotationTicketService ticketService;
|
private final TemplateLookup templateLookup;
|
private final AnnotationAccess annotationAccess;
|
private final TenantRoute tenantRoute;
|
|
@Autowired
|
public TemplateAnnotationAuthorizer(TemplateAnnotationTicketService ticketService,
|
ElnTemplateMapper templateMapper,
|
ElnTemplateAnnotationAccessService annotationAccessService) {
|
this(ticketService, templateMapper::selectById, annotationAccessService::canAnnotate,
|
new TenantRoute() {
|
@Override
|
public void switchTo(String tenantId) {
|
TenantDataSourceUtil.switchTenant(tenantId);
|
}
|
|
@Override
|
public void clear() {
|
TenantDataSourceUtil.clearLocalTenantInfo();
|
}
|
});
|
}
|
|
TemplateAnnotationAuthorizer(TemplateAnnotationTicketService ticketService,
|
TemplateLookup templateLookup,
|
AnnotationAccess annotationAccess,
|
TenantRoute tenantRoute) {
|
this.ticketService = ticketService;
|
this.templateLookup = templateLookup;
|
this.annotationAccess = annotationAccess;
|
this.tenantRoute = tenantRoute;
|
}
|
|
public TemplateAnnotationAuthorization authorize(String ticket, String templateId) {
|
return authorize(ticket, templateId, false);
|
}
|
|
public TemplateAnnotationAuthorization authorize(String ticket) {
|
return authorize(ticket, null, true);
|
}
|
|
private TemplateAnnotationAuthorization authorize(String ticket, String templateId,
|
boolean useTicketTemplateId) {
|
boolean authorized = false;
|
try {
|
TemplateAnnotationTicketService.AnnotationTicketContext context = ticketService.parse(ticket);
|
String expectedTemplateId = useTicketTemplateId ? context.getTemplateId() : templateId;
|
if (!Objects.equals(context.getTemplateId(), expectedTemplateId)) {
|
throw unauthorized();
|
}
|
if (!annotationAccess.canAnnotate(context.getTenantId(), context.getUserId(),
|
context.getTemplateId(), context.getFileId())) {
|
throw forbidden();
|
}
|
switchTenant(context.getTenantId());
|
|
ElnTemplateVersionEntity template = findTemplate(expectedTemplateId);
|
if (template == null) {
|
throw conflict();
|
}
|
if (!Objects.equals(context.getTenantId(), template.getFTenantId())
|
|| !Objects.equals(context.getTemplateId(), template.getId())) {
|
throw unauthorized();
|
}
|
String fileId = uniqueDocxFileId(template.getMubanFile());
|
if (!Objects.equals(context.getFileId(), fileId)) {
|
throw unauthorized();
|
}
|
if ((template.getFDeleteMark() != null && template.getFDeleteMark() != 0)
|
|| !DRAFT.equals(template.getBizStatus()) || !ENABLED.equals(template.getBizEnabled())) {
|
throw conflict();
|
}
|
TemplateAnnotationAuthorization authorization = new TemplateAnnotationAuthorization(
|
context.getTenantId(), context.getUserId(), template.getId(), fileId);
|
authorized = true;
|
return authorization;
|
} finally {
|
if (!authorized) {
|
tenantRoute.clear();
|
}
|
}
|
}
|
|
private void switchTenant(String tenantId) {
|
try {
|
tenantRoute.switchTo(tenantId);
|
} catch (RuntimeException e) {
|
throw unauthorized();
|
}
|
}
|
|
private ElnTemplateVersionEntity findTemplate(String templateId) {
|
try {
|
return templateLookup.findById(templateId);
|
} catch (RuntimeException e) {
|
throw conflict();
|
}
|
}
|
|
private String uniqueDocxFileId(String attachments) {
|
try {
|
List<ElnDocumentFileVo> files = JsonUtil.getJsonToList(attachments, ElnDocumentFileVo.class);
|
if (files == null) {
|
throw conflict();
|
}
|
List<String> docxFileIds = files.stream()
|
.filter(Objects::nonNull)
|
.filter(file -> "docx".equalsIgnoreCase(file.getFileExtension()))
|
.map(ElnDocumentFileVo::getFileId)
|
.filter(StringUtils::hasText)
|
.collect(Collectors.toList());
|
if (docxFileIds.size() != 1) {
|
throw conflict();
|
}
|
return docxFileIds.get(0);
|
} catch (AnnotationAuthorizationException e) {
|
throw e;
|
} catch (RuntimeException e) {
|
throw conflict();
|
}
|
}
|
|
private AnnotationAuthorizationException unauthorized() {
|
return new AnnotationAuthorizationException(401, "标注 Ticket 无效");
|
}
|
|
private AnnotationAuthorizationException forbidden() {
|
return new AnnotationAuthorizationException(403, "当前请求无模板标注权限");
|
}
|
|
private AnnotationAuthorizationException conflict() {
|
return new AnnotationAuthorizationException(409, "模板当前不可标注");
|
}
|
|
interface TemplateLookup {
|
ElnTemplateVersionEntity findById(String templateId);
|
}
|
|
interface AnnotationAccess {
|
boolean canAnnotate(String tenantId, String userId, String templateId, String fileId);
|
}
|
|
interface TenantRoute {
|
void switchTo(String tenantId);
|
|
void clear();
|
}
|
|
public static class AnnotationAuthorizationException extends RuntimeException {
|
private static final long serialVersionUID = 1L;
|
private final int status;
|
|
private AnnotationAuthorizationException(int status, String message) {
|
super(message);
|
this.status = status;
|
}
|
|
public int getStatus() {
|
return status;
|
}
|
}
|
}
|