diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImpl.java index b86d492..df6146b 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImpl.java @@ -197,11 +197,17 @@ public class TrainingTaskServiceImpl implements TrainingTaskService { @Override public List 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 defaults = trainingTaskMapper.selectList(null, null, null); - List classTasks = ensureClassTasksInitialized(teachingClassId, defaults, operator.getUserId()); - return filterEnabled(toTasks(classTasks), enabledOnly); + if (ownedByOperator) { + List 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 readClassTasks(String teachingClassId, List defaults) { + Map tasksByKey = new LinkedHashMap<>(); + List 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 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; diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImplTest.java index 3de30ee..360b9fc 100644 --- a/src/test/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImplTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/TrainingTaskServiceImplTest.java @@ -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 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();