feat: enforce teacher admin ownership rules

main
chenyuan 2 months ago
parent c2b03be5ef
commit 840e7aa63e

@ -1,8 +1,10 @@
package com.sztzjy.linkCommerce.controller.stu;
import com.sztzjy.linkCommerce.annotation.AnonymousAccess;
import com.sztzjy.linkCommerce.entity.SchoolClass;
import com.sztzjy.linkCommerce.entity.TaskAllocation;
import com.sztzjy.linkCommerce.entity.TaskAllocationExample;
import com.sztzjy.linkCommerce.mapper.SchoolClassMapper;
import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
import com.sztzjy.linkCommerce.util.ResultEntity;
import io.swagger.annotations.Api;
@ -21,6 +23,8 @@ import java.util.UUID;
public class TaskAllocationController {
@Autowired
TaskAllocationMapper taskAllocationMapper;
@Autowired
SchoolClassMapper schoolClassMapper;
@PostMapping("/selectTaskAllocationByClassId")
@ApiOperation("根据班级ID查询任务分配")
@ -43,10 +47,17 @@ public class TaskAllocationController {
@ApiOperation("编辑任务分配")
@AnonymousAccess
@Transactional
public ResultEntity updateTaskAllocationByClassId(@RequestBody List<TaskAllocation> taskAllocationList, @RequestParam String classId, @RequestParam String schoolId) {
public ResultEntity updateTaskAllocationByClassId(@RequestBody List<TaskAllocation> taskAllocationList,
@RequestParam String classId,
@RequestParam String schoolId,
@RequestParam(required = false) String userId) {
if ("999999999".equals(schoolId) || "999999999".equals(classId)) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "超管数据无法修改");
}
SchoolClass schoolClass = schoolClassMapper.selectByPrimaryKey(classId);
if (schoolClass == null || userId == null || !userId.equals(schoolClass.getCreatedBy())) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能分配自己创建班级的任务");
}
TaskAllocationExample taskAllocationExample = new TaskAllocationExample();
taskAllocationExample.createCriteria().andClassIdEqualTo(classId);
taskAllocationMapper.deleteByExample(taskAllocationExample);
@ -59,7 +70,5 @@ public class TaskAllocationController {
taskAllocationMapper.insert(taskAllocation);
}
return new ResultEntity<>(HttpStatus.OK, "修改成功");
}
}

@ -366,7 +366,8 @@ public class UserController {
public ResultEntity addSchoolClass(@ApiParam("学校ID") @RequestParam String schoolId,
@ApiParam("院系ID") @RequestParam String schoolFacultyId,
@ApiParam("专业ID") @RequestParam String schoolMajorId,
@ApiParam("班级名称") @RequestParam String className) {
@ApiParam("班级名称") @RequestParam String className,
@RequestParam(required = false) String userId) {
//先根据schoolId进行查询 如果不存在则返回
School school = schoolMapper.selectByPrimaryKey(schoolId);
if (school == null) {
@ -400,6 +401,7 @@ public class UserController {
schoolClass.setClassSn(schoolNamePY + "_" + classNamePY);
schoolClass.setCreateTime(new Date());
schoolClass.setSchoolId(schoolId);
schoolClass.setCreatedBy(userId);
int insert = schoolClassMapper.insert(schoolClass);
if (insert == 1) {
@ -462,6 +464,9 @@ public class UserController {
public ResultEntity deleteSchoolClass(@ApiParam("班级ID") @RequestParam String schoolClassId, @RequestParam String userId) {
//先查询useriD 是否够权限
Userinfo userInfo = userinfoMapper.selectByPrimaryKey(userId);
if (userInfo == null) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败-权限不足");
}
if (userInfo.getRole() == 1) {
int i = schoolClassMapper.deleteByPrimaryKey(schoolClassId);
if (i == 1) {
@ -471,9 +476,7 @@ public class UserController {
}
if (userInfo.getRole() == 3) {
SchoolClass schoolClass = schoolClassMapper.selectByPrimaryKey(schoolClassId);
String schoolId = schoolClass.getSchoolId();
String userInfoSchoolId = userInfo.getSchoolId();
if (schoolId.equals(userInfoSchoolId)) {
if (isClassOwner(schoolClass, userId)) {
int i = schoolClassMapper.deleteByPrimaryKey(schoolClassId);
if (i == 1) {
return new ResultEntity<>(HttpStatus.OK, "班级管理-删除成功");
@ -494,22 +497,25 @@ public class UserController {
}
//先查询useriD 是否够权限
Userinfo userInfo = userinfoMapper.selectByPrimaryKey(userId);
if (userInfo == null) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败-权限不足");
}
if (userInfo.getRole() == 1) {
int i = schoolClassMapper.updateByPrimaryKey(schoolClass);
int i = schoolClassMapper.updateByPrimaryKeySelective(schoolClass);
if (i == 1) {
return new ResultEntity<>(HttpStatus.OK, "班级管理-编辑成功");
}
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑成功");
}
if (userInfo.getRole() == 3) {
String schoolId = userInfo.getSchoolId();
SchoolClass schoolClass1 = schoolClassMapper.selectByPrimaryKey(schoolClass.getSchoolClassId());
if (schoolId.equals(schoolClass1.getSchoolId())) {
int i = schoolClassMapper.deleteByPrimaryKey(schoolClass.getSchoolClassId());
if (isClassOwner(schoolClass1, userId)) {
schoolClass.setCreatedBy(userId);
int i = schoolClassMapper.updateByPrimaryKeySelective(schoolClass);
if (i == 1) {
return new ResultEntity<>(HttpStatus.OK, "班级管理-删除成功");
return new ResultEntity<>(HttpStatus.OK, "班级管理-编辑成功");
}
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败");
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败");
}
}
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败-权限不足");
@ -561,6 +567,7 @@ public class UserController {
userInfo.setSchoolFacultyId(schoolFacultyId);
userInfo.setSchoolMajorId(schoolMajorId);
userInfo.setSchoolClassId(null);
userInfo.setTeacherAdmin(false);
userInfo.setCodeFrom("添加");
int insert = userinfoMapper.insert(userInfo);
@ -731,7 +738,8 @@ public class UserController {
@ApiParam("学生姓名") @RequestParam String name,
@ApiParam("学号") @RequestParam String userName,
@ApiParam("电话号码") @RequestParam(required = false) String phone,
@ApiParam("电子邮箱") @RequestParam(required = false) String email) {
@ApiParam("电子邮箱") @RequestParam(required = false) String email,
@RequestParam(required = false) String userId) {
//先根据schoolId进行查询 如果不存在则返回
School school = schoolMapper.selectByPrimaryKey(schoolId);
if (school == null) {
@ -751,6 +759,9 @@ public class UserController {
if (schoolClass == null) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该班级不存在");
}
if (StringUtils.isNotBlank(userId) && !canOperateClass(userId, schoolClassId)) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能维护自己创建班级的学生");
}
//检查userName是否已经存在
boolean b = userInfoService.existsByUserName(userName);
if (b) {
@ -853,7 +864,10 @@ public class UserController {
@PostMapping("/deleteStudent")
@ApiOperation("学生管理-删除")
@AnonymousAccess
public ResultEntity deleteStudent(@RequestParam String userId) {
public ResultEntity deleteStudent(@RequestParam String userId, @RequestParam(required = false) String operatorId) {
if (StringUtils.isNotBlank(operatorId) && !canOperateStudent(operatorId, userId)) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能维护自己创建班级的学生");
}
int i = userinfoMapper.deleteByPrimaryKey(userId);
if (i == 1) {
return new ResultEntity<>(HttpStatus.OK, "删除成功!");
@ -1015,6 +1029,36 @@ public class UserController {
return schoolClass == null ? "" : schoolClass.getClassName();
}
@ApiOperation("开放接口,自动同步学生信息")
private boolean isClassOwner(SchoolClass schoolClass, String userId) {
return schoolClass != null
&& StringUtils.isNotBlank(userId)
&& StringUtils.equals(schoolClass.getCreatedBy(), userId);
}
private boolean canOperateClass(String operatorId, String schoolClassId) {
Userinfo operator = userinfoMapper.selectByPrimaryKey(operatorId);
if (operator == null) {
return false;
}
if (Integer.valueOf(1).equals(operator.getRole())) {
return true;
}
if (!Integer.valueOf(3).equals(operator.getRole())) {
return false;
}
SchoolClass schoolClass = schoolClassMapper.selectByPrimaryKey(schoolClassId);
return isClassOwner(schoolClass, operatorId);
}
private boolean canOperateStudent(String operatorId, String studentId) {
Userinfo student = userinfoMapper.selectByPrimaryKey(studentId);
if (student == null || !Integer.valueOf(4).equals(student.getRole())) {
return false;
}
return canOperateClass(operatorId, student.getSchoolClassId());
}
@ApiOperation("开放接口,自动同步学生信息")
@PostMapping("synchronizationStudentInfoByAuto")
@AnonymousAccess

@ -33,6 +33,7 @@ public class ImportServiceImpl implements ImportService {
userInfo.setEmail(teacherImportDTO.getEmail());
userInfo.setCreateTime(new Date());
userInfo.setRole(3);
userInfo.setTeacherAdmin(false);
userInfo.setSchoolId(schoolService.selectSchoolIdBySchoolName(teacherImportDTO.getSchoolName()));
userInfo.setSchoolFacultyId(schoolService.selectFacultyIdBySchoolIdAndFacultyName(userInfo.getSchoolId(),teacherImportDTO.getSchoolFacultyName()));
userInfo.setSchoolMajorId(schoolService.selectMajorIdByFacultyIdAndMajorName(userInfo.getSchoolFacultyId(),teacherImportDTO.getSchoolMajorName()));

@ -0,0 +1,35 @@
package com.sztzjy.linkCommerce.controller.stu;
import com.sztzjy.linkCommerce.entity.SchoolClass;
import com.sztzjy.linkCommerce.mapper.SchoolClassMapper;
import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
import com.sztzjy.linkCommerce.util.ResultEntity;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class TaskAllocationControllerTest {
@Test
void teacherCannotUpdateTaskAllocationForClassCreatedByAnotherTeacher() {
TaskAllocationController controller = new TaskAllocationController();
controller.taskAllocationMapper = mock(TaskAllocationMapper.class);
controller.schoolClassMapper = mock(SchoolClassMapper.class);
SchoolClass schoolClass = new SchoolClass();
schoolClass.setSchoolClassId("class-1");
schoolClass.setCreatedBy("teacher-2");
when(controller.schoolClassMapper.selectByPrimaryKey("class-1")).thenReturn(schoolClass);
ResultEntity result = controller.updateTaskAllocationByClassId(Collections.emptyList(), "class-1", "school-1", "teacher-1");
assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode());
verify(controller.taskAllocationMapper, never()).deleteByExample(org.mockito.ArgumentMatchers.any());
}
}

@ -0,0 +1,167 @@
package com.sztzjy.linkCommerce.controller.stu;
import com.sztzjy.linkCommerce.entity.School;
import com.sztzjy.linkCommerce.entity.SchoolClass;
import com.sztzjy.linkCommerce.entity.SchoolFaculty;
import com.sztzjy.linkCommerce.entity.SchoolMajor;
import com.sztzjy.linkCommerce.entity.Userinfo;
import com.sztzjy.linkCommerce.mapper.SchoolClassMapper;
import com.sztzjy.linkCommerce.mapper.SchoolFacultyMapper;
import com.sztzjy.linkCommerce.mapper.SchoolMapper;
import com.sztzjy.linkCommerce.mapper.SchoolMajorMapper;
import com.sztzjy.linkCommerce.mapper.UserinfoMapper;
import com.sztzjy.linkCommerce.service.UserInfoService;
import com.sztzjy.linkCommerce.util.Pinyin4jUtil;
import com.sztzjy.linkCommerce.util.ResultEntity;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.http.HttpStatus;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class UserControllerTeacherAdminTest {
@Test
void addTeacherAccountAlwaysCreatesOrdinaryTeacher() {
UserController controller = controllerWithCommonMocks();
when(controller.userInfoService.existsByUserName("t001")).thenReturn(false);
when(controller.userinfoMapper.insert(any(Userinfo.class))).thenReturn(1);
ResultEntity result = controller.addTeacherAccount("school-1", "school", "faculty-1", "major-1",
"major", "张老师", "t001", null, null);
ArgumentCaptor<Userinfo> captor = ArgumentCaptor.forClass(Userinfo.class);
verify(controller.userinfoMapper).insert(captor.capture());
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals(3, captor.getValue().getRole());
assertFalse(captor.getValue().getTeacherAdmin());
}
@Test
void addSchoolClassStoresCreatorTeacher() {
UserController controller = controllerWithCommonMocks();
when(controller.schoolClassMapper.selectByExample(any())).thenReturn(Collections.emptyList());
when(controller.schoolClassMapper.insert(any(SchoolClass.class))).thenReturn(1);
when(controller.pinyin4jUtil.convertToPinyin(any())).thenReturn("py");
ResultEntity result = controller.addSchoolClass("school-1", "faculty-1", "major-1", "class-1", "teacher-1");
ArgumentCaptor<SchoolClass> captor = ArgumentCaptor.forClass(SchoolClass.class);
verify(controller.schoolClassMapper).insert(captor.capture());
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("teacher-1", captor.getValue().getCreatedBy());
}
@Test
void teacherCannotDeleteClassCreatedByAnotherTeacher() {
UserController controller = controllerWithCommonMocks();
Userinfo teacher = teacher("teacher-1");
SchoolClass schoolClass = classCreatedBy("teacher-2");
when(controller.userinfoMapper.selectByPrimaryKey("teacher-1")).thenReturn(teacher);
when(controller.schoolClassMapper.selectByPrimaryKey("class-1")).thenReturn(schoolClass);
ResultEntity result = controller.deleteSchoolClass("class-1", "teacher-1");
assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode());
verify(controller.schoolClassMapper, never()).deleteByPrimaryKey("class-1");
}
@Test
void teacherUpdatesOnlyOwnedClass() {
UserController controller = controllerWithCommonMocks();
Userinfo teacher = teacher("teacher-1");
SchoolClass existing = classCreatedBy("teacher-1");
SchoolClass update = new SchoolClass();
update.setSchoolClassId("class-1");
update.setClassName("new-class");
when(controller.userinfoMapper.selectByPrimaryKey("teacher-1")).thenReturn(teacher);
when(controller.schoolClassMapper.selectByPrimaryKey("class-1")).thenReturn(existing);
when(controller.schoolClassMapper.updateByPrimaryKeySelective(any(SchoolClass.class))).thenReturn(1);
ResultEntity result = controller.updateSchoolClass(update, "teacher-1");
assertEquals(HttpStatus.OK, result.getStatusCode());
verify(controller.schoolClassMapper).updateByPrimaryKeySelective(update);
verify(controller.schoolClassMapper, never()).deleteByPrimaryKey("class-1");
}
@Test
void teacherCannotDeleteStudentFromClassCreatedByAnotherTeacher() {
UserController controller = controllerWithCommonMocks();
Userinfo teacher = teacher("teacher-1");
Userinfo student = new Userinfo();
student.setUserId("student-1");
student.setRole(4);
student.setSchoolClassId("class-1");
when(controller.userinfoMapper.selectByPrimaryKey("teacher-1")).thenReturn(teacher);
when(controller.userinfoMapper.selectByPrimaryKey("student-1")).thenReturn(student);
when(controller.schoolClassMapper.selectByPrimaryKey("class-1")).thenReturn(classCreatedBy("teacher-2"));
ResultEntity result = controller.deleteStudent("student-1", "teacher-1");
assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode());
verify(controller.userinfoMapper, never()).deleteByPrimaryKey("student-1");
}
@Test
void teacherCanAddStudentOnlyToOwnedClass() {
UserController controller = controllerWithCommonMocks();
when(controller.schoolClassMapper.selectByPrimaryKey("class-1")).thenReturn(classCreatedBy("teacher-1"));
when(controller.userinfoMapper.selectByPrimaryKey("teacher-1")).thenReturn(teacher("teacher-1"));
when(controller.userInfoService.existsByUserName("s001")).thenReturn(false);
when(controller.userinfoMapper.insert(any(Userinfo.class))).thenReturn(1);
ResultEntity result = controller.addStudentAccount("school-1", "school", "faculty-1", "major-1",
"major", "class-1", "class-1", "学生", "s001", null, null, "teacher-1");
assertEquals(HttpStatus.OK, result.getStatusCode());
}
private UserController controllerWithCommonMocks() {
UserController controller = new UserController();
controller.schoolMapper = mock(SchoolMapper.class);
controller.schoolFacultyMapper = mock(SchoolFacultyMapper.class);
controller.schoolMajorMapper = mock(SchoolMajorMapper.class);
controller.schoolClassMapper = mock(SchoolClassMapper.class);
controller.userinfoMapper = mock(UserinfoMapper.class);
controller.userInfoService = mock(UserInfoService.class);
controller.pinyin4jUtil = mock(Pinyin4jUtil.class);
School school = new School();
school.setSchoolId("school-1");
school.setSchoolName("school");
SchoolFaculty faculty = new SchoolFaculty();
faculty.setSchoolFacultyId("faculty-1");
SchoolMajor major = new SchoolMajor();
major.setSchoolMajorId("major-1");
when(controller.schoolMapper.selectByPrimaryKey("school-1")).thenReturn(school);
when(controller.schoolFacultyMapper.selectByPrimaryKey("faculty-1")).thenReturn(faculty);
when(controller.schoolMajorMapper.selectByPrimaryKey("major-1")).thenReturn(major);
return controller;
}
private Userinfo teacher(String userId) {
Userinfo teacher = new Userinfo();
teacher.setUserId(userId);
teacher.setRole(3);
teacher.setSchoolId("school-1");
return teacher;
}
private SchoolClass classCreatedBy(String teacherId) {
SchoolClass schoolClass = new SchoolClass();
schoolClass.setSchoolClassId("class-1");
schoolClass.setSchoolId("school-1");
schoolClass.setCreatedBy(teacherId);
return schoolClass;
}
}

@ -0,0 +1,39 @@
package com.sztzjy.linkCommerce.service.impl;
import com.sztzjy.linkCommerce.entity.Userinfo;
import com.sztzjy.linkCommerce.entity.importDto.TeacherImportDTO;
import com.sztzjy.linkCommerce.mapper.UserinfoMapper;
import com.sztzjy.linkCommerce.service.SchoolService;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class ImportServiceImplTest {
@Test
void teacherImportCreatesOrdinaryTeacher() {
ImportServiceImpl service = new ImportServiceImpl();
service.schoolService = mock(SchoolService.class);
service.userInfoMapper = mock(UserinfoMapper.class);
when(service.schoolService.selectSchoolIdBySchoolName(any())).thenReturn("school-1");
when(service.schoolService.selectFacultyIdBySchoolIdAndFacultyName(any(), any())).thenReturn("faculty-1");
when(service.schoolService.selectMajorIdByFacultyIdAndMajorName(any(), any())).thenReturn("major-1");
TeacherImportDTO row = new TeacherImportDTO();
row.setTeacherName("张老师");
row.setUserName("t001");
service.processTeacherImport(Collections.singletonList(row));
ArgumentCaptor<Userinfo> captor = ArgumentCaptor.forClass(Userinfo.class);
verify(service.userInfoMapper).insert(captor.capture());
assertFalse(captor.getValue().getTeacherAdmin());
}
}
Loading…
Cancel
Save