fix: keep non-owner class task reads read-only

main
chenyuan 4 weeks ago
parent 6d7e16f7e0
commit 61a129af96

@ -197,11 +197,17 @@ public class TrainingTaskServiceImpl implements TrainingTaskService {
@Override
public List<TrainingTask> listForTeachingClass(String teachingClassId, Boolean enabledOnly, JwtUser operator) {
requireReadableTeachingClass(teachingClassId, operator);
ensureDefaultTasks(null);
SchoolClass teachingClass = requireReadableTeachingClass(teachingClassId, operator);
boolean ownedByOperator = StringUtils.equals(teachingClass.getCreatedBy(), operator.getUserId());
if (ownedByOperator) {
ensureDefaultTasks(null);
}
List<TrainingTask> defaults = trainingTaskMapper.selectList(null, null, null);
List<TrainingTaskClassConfig> classTasks = ensureClassTasksInitialized(teachingClassId, defaults, operator.getUserId());
return filterEnabled(toTasks(classTasks), enabledOnly);
if (ownedByOperator) {
List<TrainingTaskClassConfig> classTasks = ensureClassTasksInitialized(teachingClassId, defaults, operator.getUserId());
return filterEnabled(toTasks(classTasks), enabledOnly);
}
return filterEnabled(readClassTasks(teachingClassId, defaults), enabledOnly);
}
@Override
@ -381,12 +387,34 @@ public class TrainingTaskServiceImpl implements TrainingTaskService {
throw new IllegalArgumentException("Teaching class not found");
}
if (operator == null || StringUtils.isBlank(operator.getUserId())
|| StringUtils.isBlank(operator.getSchoolId()) || StringUtils.isBlank(schoolClass.getSchoolId())
|| !StringUtils.equals(operator.getSchoolId(), schoolClass.getSchoolId())) {
throw new IllegalArgumentException("Teaching class is unavailable");
}
return schoolClass;
}
private List<TrainingTask> readClassTasks(String teachingClassId, List<TrainingTask> defaults) {
Map<String, TrainingTask> tasksByKey = new LinkedHashMap<>();
List<TrainingTask> sourceTasks = defaults == null || defaults.isEmpty() ? defaultTasks() : defaults;
for (TrainingTask task : sourceTasks) {
if (task != null && StringUtils.isNotBlank(task.getTaskKey())) {
tasksByKey.put(task.getTaskKey(), task);
}
}
if (trainingTaskClassConfigMapper != null) {
List<TrainingTaskClassConfig> classTasks = trainingTaskClassConfigMapper.selectListByTeachingClass(teachingClassId, null);
if (classTasks != null) {
for (TrainingTaskClassConfig classTask : classTasks) {
if (classTask != null && StringUtils.isNotBlank(classTask.getTaskKey())) {
tasksByKey.put(classTask.getTaskKey(), toTask(classTask));
}
}
}
}
return sortTasks(new ArrayList<>(tasksByKey.values()));
}
private String resolveStudentTeachingClassId(String studentUserId) {
if (StringUtils.isBlank(studentUserId) || teachingClassStudentMapper == null) {
return null;

@ -336,6 +336,46 @@ class TrainingTaskServiceImplTest {
() -> service.requireReadableTeachingClass("class-2", reader));
}
@Test
void nonOwnerSameSchoolClassTaskReadDoesNotWriteConfigurations() {
TrainingTaskServiceImpl service = new TrainingTaskServiceImpl();
service.trainingTaskMapper = mock(TrainingTaskMapper.class);
service.trainingTaskClassConfigMapper = mock(TrainingTaskClassConfigMapper.class);
service.schoolClassMapper = mock(SchoolClassMapper.class);
SchoolClass schoolClass = teachingClass("class-2", "teacher-a");
schoolClass.setSchoolId("school-1");
when(service.schoolClassMapper.selectByPrimaryKey("class-2")).thenReturn(schoolClass);
TrainingTask defaultTask = storedTask("task-1", "new-product-survey");
when(service.trainingTaskMapper.selectList(null, null, null)).thenReturn(Collections.singletonList(defaultTask));
when(service.trainingTaskClassConfigMapper.selectListByTeachingClass("class-2", null)).thenReturn(Collections.emptyList());
JwtUser reader = new JwtUser();
reader.setUserId("teacher-b");
reader.setSchoolId("school-1");
List<TrainingTask> result = service.listForTeachingClass("class-2", false, reader);
assertEquals(1, result.size());
verify(service.trainingTaskClassConfigMapper, never()).insertSelective(any());
verify(service.trainingTaskClassConfigMapper, never()).updateByPrimaryKeySelective(any());
verify(service.trainingTaskClassConfigMapper, never()).deleteByTeachingClass(anyString());
verify(service.trainingTaskClassConfigMapper, never()).deleteByTeachingClassAndTaskKey(anyString(), anyString());
}
@Test
void teacherCannotReadTeachingClassWhenSchoolIdIsMissing() {
TrainingTaskServiceImpl service = new TrainingTaskServiceImpl();
service.schoolClassMapper = mock(SchoolClassMapper.class);
SchoolClass schoolClass = teachingClass("class-2", "teacher-a");
when(service.schoolClassMapper.selectByPrimaryKey("class-2")).thenReturn(schoolClass);
JwtUser reader = new JwtUser();
reader.setUserId("teacher-b");
assertThrows(IllegalArgumentException.class,
() -> service.requireReadableTeachingClass("class-2", reader));
}
@Test
void restoreClassTaskDefaultDeletesOnlySelectedClassTaskCopy() {
TrainingTaskServiceImpl service = new TrainingTaskServiceImpl();

Loading…
Cancel
Save