项目权限

This commit is contained in:
wanxiaoli 2026-04-03 12:06:24 +08:00
parent b1ee7c5f61
commit dc5691e1f6
17 changed files with 299 additions and 69 deletions

View File

@ -153,7 +153,16 @@ public class AlgorithmController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -295,7 +295,16 @@ public class AlgorithmModelController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -48,7 +48,16 @@ public class CriticalDataController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -189,7 +189,16 @@ public class DeviceController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -442,7 +442,16 @@ public class EventController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -173,7 +173,16 @@ public class MaterialController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -55,10 +55,9 @@ public class ProjectController {
project.setVisibility(projectAccessHelper.normalizeVisibility(project.getVisibility()));
}
if (project.getCreator() == null || project.getCreator().isBlank()) {
var u = userService.getUserInfo();
if (u != null) project.setCreator(u.getId());
project.setCreator(currentAccount());
}
project.setModifier(currentUsername());
project.setModifier(currentAccount());
return projectService.save(project);
}
@ -76,12 +75,12 @@ public class ProjectController {
if (project.getProjectId() != null) {
projectAccessHelper.assertCanWriteProject(project.getProjectId());
}
project.setModifier(currentUsername());
project.setModifier(currentAccount());
project.setUpdatedAt(LocalDateTime.now());
return projectService.updateById(project);
}
@Log(value = "修改项目可见性", module = "项目管理")
@Log(value = "修改项目权限", module = "项目管理")
@PutMapping("/{id}/visibility")
@Operation(summary = "修改项目可见性", description = "仅项目所有者或管理员可修改PRIVATE/READONLY/PUBLIC")
public boolean updateVisibility(@PathVariable @Parameter(description = "项目ID", required = true) String id,
@ -94,18 +93,27 @@ public class ProjectController {
Project p = new Project();
p.setProjectId(id);
p.setVisibility(projectAccessHelper.normalizeVisibility(visibility));
p.setModifier(currentUsername());
p.setModifier(currentAccount());
p.setUpdatedAt(LocalDateTime.now());
return projectService.updateById(p);
}
private String currentUsername() {
private String currentAccount() {
try {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}
@ -218,11 +226,13 @@ public class ProjectController {
qw.like("name", name);
}
if (!projectAccessHelper.isAdmin()) {
String account = projectAccessHelper.currentAccount();
String uid = projectAccessHelper.currentUserId();
qw.and(w -> w.isNull("visibility")
.or().eq("visibility", "")
.or().eq("visibility", "PUBLIC")
.or().eq("visibility", "READONLY")
.or().eq("creator", account)
.or().eq("creator", uid));
}
Page<Project> page = new Page<>(pageNum, pageSize, true);
@ -287,7 +297,7 @@ public class ProjectController {
Project updated = new Project();
updated.setProjectId(id);
updated.setTopology(json);
updated.setModifier(currentUsername());
updated.setModifier(currentAccount());
updated.setUpdatedAt(LocalDateTime.now());
projectService.updateById(updated);
return ResponseEntity.ok(Map.of(

View File

@ -180,7 +180,16 @@ public class ScenarioController {
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -4,9 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.business.css.domain.Scenario;
import com.yfd.business.css.domain.ScenarioResult;
import com.yfd.business.css.domain.Device;
import com.yfd.business.css.security.ProjectAccessHelper;
import com.yfd.business.css.service.ScenarioResultService;
import com.yfd.business.css.service.ScenarioService;
import com.yfd.business.css.service.DeviceService;
import java.io.IOException;
@ -30,6 +32,8 @@ public class ScenarioResultController {
private ScenarioService scenarioService;
@Resource
private ProjectAccessHelper projectAccessHelper;
@Resource
private DeviceService deviceService;
/**
* 根据场景ID分页查询模拟结果
@ -116,11 +120,11 @@ public class ScenarioResultController {
queryWrapper.le("step", stepTo);
}
List<ScenarioResult> results = scenarioResultService.list(queryWrapper.orderByAsc("step"));
List<ScenarioResult> results = scenarioResultService.list(queryWrapper.orderByAsc("device_id").orderByAsc("step"));
// 创建Excel工作簿
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("情景结果数据");
String scenarioName = sc != null && sc.getName() != null ? sc.getName() : scenarioId;
// 创建表头样式
CellStyle headerStyle = workbook.createCellStyle();
@ -145,52 +149,92 @@ public class ScenarioResultController {
dataStyle.setWrapText(true);
// 创建表头
String[] headers = {"场景名称", "设备名称", "时点", "属性值", "Keff值"};
if (deviceId != null && !deviceId.isEmpty()) {
Device dev = deviceService.getById(deviceId);
String deviceName = dev != null && dev.getName() != null ? dev.getName() : deviceId;
Sheet sheet = workbook.createSheet(deviceName);
Row headerRow = sheet.createRow(0);
String[] headers = {"场景ID", "设备ID", "时点", "属性值", "Keff值"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerStyle);
}
// 填充数据
int rowNum = 1;
for (ScenarioResult result : results) {
Row row = sheet.createRow(rowNum++);
Cell cell0 = row.createCell(0);
cell0.setCellValue(result.getScenarioId());
cell0.setCellValue(scenarioName);
cell0.setCellStyle(dataStyle);
Cell cell1 = row.createCell(1);
cell1.setCellValue(result.getDeviceId());
cell1.setCellValue(deviceName);
cell1.setCellStyle(dataStyle);
Cell cell2 = row.createCell(2);
cell2.setCellValue(result.getStep());
cell2.setCellStyle(dataStyle);
Cell cell3 = row.createCell(3);
cell3.setCellValue(result.getAttrState().toString());
cell3.setCellValue(result.getAttrState());
cell3.setCellStyle(dataStyle);
Cell cell4 = row.createCell(4);
cell4.setCellValue(result.getKeffValue().doubleValue());
cell4.setCellValue(result.getKeffValue() == null ? 0.0 : result.getKeffValue().doubleValue());
cell4.setCellStyle(dataStyle);
}
// 自动调整列宽
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i);
// 设置最小列宽
if (sheet.getColumnWidth(i) < 20 * 256) {
sheet.setColumnWidth(i, 20 * 256);
}
// 设置最大列宽
if (sheet.getColumnWidth(i) > 50 * 256) {
sheet.setColumnWidth(i, 50 * 256);
}
}
} else {
java.util.Map<String, java.util.List<ScenarioResult>> byDevice = new java.util.LinkedHashMap<>();
for (ScenarioResult r : results) {
byDevice.computeIfAbsent(r.getDeviceId(), k -> new java.util.ArrayList<>()).add(r);
}
for (java.util.Map.Entry<String, java.util.List<ScenarioResult>> entry : byDevice.entrySet()) {
String did = entry.getKey();
Device dev = deviceService.getById(did);
String deviceName = dev != null && dev.getName() != null ? dev.getName() : did;
Sheet sheet = workbook.createSheet(deviceName);
Row headerRow = sheet.createRow(0);
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerStyle);
}
int rowNum = 1;
for (ScenarioResult result : entry.getValue()) {
Row row = sheet.createRow(rowNum++);
Cell cell0 = row.createCell(0);
cell0.setCellValue(scenarioName);
cell0.setCellStyle(dataStyle);
Cell cell1 = row.createCell(1);
cell1.setCellValue(deviceName);
cell1.setCellStyle(dataStyle);
Cell cell2 = row.createCell(2);
cell2.setCellValue(result.getStep());
cell2.setCellStyle(dataStyle);
Cell cell3 = row.createCell(3);
cell3.setCellValue(result.getAttrState());
cell3.setCellStyle(dataStyle);
Cell cell4 = row.createCell(4);
cell4.setCellValue(result.getKeffValue() == null ? 0.0 : result.getKeffValue().doubleValue());
cell4.setCellStyle(dataStyle);
}
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i);
if (sheet.getColumnWidth(i) < 20 * 256) {
sheet.setColumnWidth(i, 20 * 256);
}
if (sheet.getColumnWidth(i) > 50 * 256) {
sheet.setColumnWidth(i, 50 * 256);
}
}
}
}
// 写入响应输出流
workbook.write(response.getOutputStream());

View File

@ -1,6 +1,8 @@
package com.yfd.business.css.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
@ -49,7 +51,12 @@ public class ModelTrainTask implements Serializable {
@TableField("error_log")
private String errorLog;
@TableField(value = "feature_map_config")
@JsonIgnore
private String featureMapConfigJson;
@TableField(exist = false)
@JsonProperty("featureMapConfig")
private Map<String, Object> featureMapConfig;
@TableField(value = "created_at")

View File

@ -27,6 +27,53 @@ public class ProjectAccessHelper {
return u == null ? null : u.getId();
}
public String currentAccount() {
try {
SysUser u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
} catch (Exception ignored) {
}
try {
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
} catch (Exception ignored) {
}
return null;
}
public String currentNickname() {
try {
String n = userService.getUsername();
if (n != null && !n.isBlank() && !"anonymous".equalsIgnoreCase(n)) return n;
} catch (Exception ignored) {
}
try {
SysUser u = userService.getUserInfo();
if (u != null && u.getNickname() != null && !u.getNickname().isBlank()) {
return u.getNickname();
}
} catch (Exception ignored) {
}
return null;
}
private boolean isOwner(Project p) {
if (p == null) return false;
String creator = p.getCreator();
if (creator == null || creator.isBlank()) return false;
String account = currentAccount();
if (account != null && account.equals(creator)) return true;
String uid = currentUserId();
if (uid != null && uid.equals(creator)) return true;
String nickname = currentNickname();
return nickname != null && nickname.equals(creator);
}
public void assertCanReadProject(String projectId) {
Project p = projectService.getById(projectId);
if (p == null) {
@ -61,10 +108,10 @@ public class ProjectAccessHelper {
if (p == null) return false;
if (isAdmin()) return true;
String visibility = normalizeVisibility(p.getVisibility());
System.out.println("visibility="+visibility);
if ("PUBLIC".equals(visibility) || "READONLY".equals(visibility)) return true;
if ("PRIVATE".equals(visibility)) {
String uid = currentUserId();
return uid != null && uid.equals(p.getCreator());
return isOwner(p);
}
return true;
}
@ -72,8 +119,7 @@ public class ProjectAccessHelper {
public boolean canWrite(Project p) {
if (p == null) return false;
if (isAdmin()) return true;
String uid = currentUserId();
if (uid != null && uid.equals(p.getCreator())) return true;
if (isOwner(p)) return true;
String visibility = normalizeVisibility(p.getVisibility());
return "PUBLIC".equals(visibility);
}
@ -81,8 +127,7 @@ public class ProjectAccessHelper {
public boolean canManageVisibility(Project p) {
if (p == null) return false;
if (isAdmin()) return true;
String uid = currentUserId();
return uid != null && uid.equals(p.getCreator());
return isOwner(p);
}
public String normalizeVisibility(String visibility) {

View File

@ -236,7 +236,16 @@ public class CriticalDataServiceImpl
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -204,7 +204,16 @@ public class DeviceServiceImpl
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -202,7 +202,16 @@ public class MaterialServiceImpl
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
return "anonymous";
}
return userService.getUsername();
var u = userService.getUserInfo();
if (u != null && u.getUsername() != null && !u.getUsername().isBlank()) {
return u.getUsername();
}
var m = userService.getNameInfo();
if (m != null) {
String username = m.get("username");
if (username != null && !username.isBlank()) return username;
}
return "anonymous";
} catch (Exception e) {
return "anonymous";
}

View File

@ -157,6 +157,7 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
params.put("feature_map", task.getFeatureMapConfig());
try {
task.setTrainParams(objectMapper.writeValueAsString(params));
task.setFeatureMapConfigJson(objectMapper.writeValueAsString(task.getFeatureMapConfig()));
} catch (JsonProcessingException ignored) {
}
}
@ -322,6 +323,15 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
if (task == null) {
throw new BizException("任务不存在");
}
if ((task.getFeatureMapConfig() == null || task.getFeatureMapConfig().isEmpty())
&& task.getFeatureMapConfigJson() != null
&& !task.getFeatureMapConfigJson().isBlank()) {
try {
Map<String, Object> fm = objectMapper.readValue(task.getFeatureMapConfigJson(), new TypeReference<Map<String, Object>>() {});
task.setFeatureMapConfig(fm);
} catch (Exception ignored) {
}
}
// 由于改为 WebSocket 异步推送这里简化为直接查库返回
return task;
}

View File

@ -312,6 +312,20 @@
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>17</release>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>

View File

@ -0,0 +1,10 @@
package com.yfd.platform.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@Configuration
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig {
}