Browse Source

fork课程、选择章节时判断是否有未授权课程的章节

guochao 5 năm trước cách đây
mục cha
commit
4daf368ca7

+ 21 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/OperationResourceDao.java

@@ -0,0 +1,21 @@
+package cn.iselab.mooctest.site.dao;
+
+import cn.iselab.mooctest.site.dao.adapter.UpdateAdapter;
+import cn.iselab.mooctest.site.models.OperationResource;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+/**
+ * @author guochao
+ * @date 2020-03-14 16:09
+ */
+@Transactional
+public interface OperationResourceDao extends PagingAndSortingRepository<OperationResource,Long>, CrudRepository<OperationResource,Long>,JpaSpecificationExecutor<OperationResource>, UpdateAdapter<OperationResource,Long> {
+
+
+    List<OperationResource> findAllByUserIdAndOperationNotAndResourceIdAndResDeletedAndResPublicStatusAndPublicStatusAndTypeAndIsDeleted(Long userId, String operation, Long resourceId, int resDeleted, int resIsPublic, int courseIsPublic, int type, int courseDeleted);
+}

+ 1 - 3
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/ThemeDetailDao.java

@@ -1,7 +1,6 @@
 package cn.iselab.mooctest.site.dao;
 
 import cn.iselab.mooctest.site.dao.adapter.UpdateAdapter;
-import cn.iselab.mooctest.site.models.CourseResource;
 import cn.iselab.mooctest.site.models.ThemeDetail;
 
 import org.springframework.data.domain.Page;
@@ -12,7 +11,6 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.data.repository.PagingAndSortingRepository;
 import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Component;
 
 import javax.transaction.Transactional;
 import java.util.List;
@@ -38,7 +36,7 @@ public interface ThemeDetailDao extends PagingAndSortingRepository<ThemeDetail,L
     @Query("update ThemeDetail t set t.status = :status where t.id= :id")
     void updateStatusById(@Param("id") Long id, @Param("status") int status);
 
-    List<ThemeDetail> findAllByTitleLikeAndTypeAndPublicStatusAndVisibilityAndReleasedAndIsDeleted(String courseName,int type, int publicStatus, int visibility,int released, int isDeleted);
+    List<ThemeDetail> findAllByTitleLikeAndTypeAndPublicStatusAndVisibilityNotAndReleasedAndIsDeleted(String courseName,int type, int publicStatus, int visibility,int released, int isDeleted);
 
     List<ThemeDetail> findAllByVisibilityIsNot(int visibility);
 }

+ 2 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/dao/User2ThemeDao.java

@@ -26,5 +26,7 @@ public interface User2ThemeDao extends CrudRepository<User2Theme,Long> {
     void updateOperationById(@Param("id") long id, @Param("operation") String operation);
 
     User2Theme findByUserIdAndThemeIdAndOperation(long userId, long themeId, String operation);
+
+    List<User2Theme> findByUserIdAndThemeIdAndOperationNot(long userId, long themeId, String operation);
 }
 

+ 64 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/OperationResource.java

@@ -0,0 +1,64 @@
+package cn.iselab.mooctest.site.models;
+
+import lombok.Data;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.sql.Timestamp;
+
+/**
+ * guochao
+ **/
+@Entity
+@Table(name = "course_resource_operation")
+@Data
+public class OperationResource {
+
+    @Id
+    private Long id;
+
+    @Column(name = "operation")
+    private String operation;
+
+    @Column(name = "user_id")
+    private Long userId;
+
+    @Column(name = "title")
+    private String title;
+
+    @Column(name = "owner_id")
+    private Long ownerId;
+
+    @Column(name = "status")
+    private Integer status;
+
+    @Column(name = "public")
+    private int publicStatus;
+
+    @Column(name = "type")
+    private int type;
+
+    @Column(name = "is_deleted")
+    private int isDeleted;
+
+    @Column(name = "released")
+    private int released;
+
+    @Column(name = "visibility")
+    private int visibility;
+
+    @Column(name = "resource_id")
+    private Long resourceId;
+
+    @Column(name = "res_owner_id")
+    private Long resOwnerId;
+
+    @Column(name = "res_deleted")
+    private int resDeleted;
+
+    @Column(name = "res_public_status")
+    private int resPublicStatus;
+
+}

+ 4 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/models/ThemeDetail.java

@@ -30,6 +30,10 @@ public class ThemeDetail {
     public static final Integer IS_PUBLIC = 0;
     public static final Integer IS_PRIVATE = 1;
 
+    // deletedStatus
+    public static final Integer IS_DELETED = 1;
+    public static final Integer NOT_DELETED = 0;
+
     // theme type
     public static final Integer COURSE = 0;
 

+ 14 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/OperationRecourseService.java

@@ -0,0 +1,14 @@
+package cn.iselab.mooctest.site.service;
+
+import cn.iselab.mooctest.site.models.OperationResource;
+
+import java.util.List;
+
+/**
+ * @author guochao
+ * @date 2020-03-14 16:15
+ */
+public interface OperationRecourseService {
+
+    List<OperationResource> getOperationRecourseList(Long userId, String operation, Long resourceId, int resDeleted, int resIsPublic, int courseIsPublic, int type, int courseDeleted);
+}

+ 1 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/User2ThemeService.java

@@ -18,6 +18,7 @@ public interface User2ThemeService {
     User2Theme findByUserIdAndThemeId(long userId, long themeId);
     List<User2Theme> findAllByUserIdAndThemeId(long userId, long themeId);
     User2Theme findByUserIdAndThemeIdAndOperation(long userId, long themeId, String operation);
+    List<User2Theme> findByUserIdAndThemeIdAndOperationNot(long userId, long themeId, String operation);
     void updateOperationById(long id, String operation);
     List<User2Theme> findByUserId(long userId);
 

+ 25 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/OperationRecourseServiceImpl.java

@@ -0,0 +1,25 @@
+package cn.iselab.mooctest.site.service.impl;
+
+import cn.iselab.mooctest.site.dao.OperationResourceDao;
+import cn.iselab.mooctest.site.models.OperationResource;
+import cn.iselab.mooctest.site.service.OperationRecourseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author guochao
+ * @date 2020-03-14 16:16
+ */
+@Service
+public class OperationRecourseServiceImpl implements OperationRecourseService {
+
+    @Autowired
+    private OperationResourceDao operationResourceDao;
+
+    @Override
+    public List<OperationResource> getOperationRecourseList(Long userId, String operation, Long resourceId, int resDeleted, int resIsPublic, int courseIsPublic, int type, int courseDeleted) {
+        return operationResourceDao.findAllByUserIdAndOperationNotAndResourceIdAndResDeletedAndResPublicStatusAndPublicStatusAndTypeAndIsDeleted(userId, operation, resourceId, resDeleted, resIsPublic, courseIsPublic, type, courseDeleted);
+    }
+}

+ 1 - 1
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/ThemeServiceImpl.java

@@ -511,7 +511,7 @@ public class ThemeServiceImpl implements ThemeService {
 
     @Override
     public List<ThemeDetail> getThemeDetailByCourseName(String courseName){
-        return themeDetailDao.findAllByTitleLikeAndTypeAndPublicStatusAndVisibilityAndReleasedAndIsDeleted("%"+courseName+"%", ThemeDetail.COURSE, ThemeDetail.IS_PUBLIC, CourseVisibility.PART_OPEN.getVisibility(), ThemeDetail.RELEASED, 0);
+        return themeDetailDao.findAllByTitleLikeAndTypeAndPublicStatusAndVisibilityNotAndReleasedAndIsDeleted("%"+courseName+"%", ThemeDetail.COURSE, ThemeDetail.IS_PUBLIC, CourseVisibility.NONE_OPEN.getVisibility(), ThemeDetail.RELEASED, 0);
     }
 
     @Override

+ 5 - 0
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/service/impl/User2ThemeServiceImpl.java

@@ -44,6 +44,11 @@ public class User2ThemeServiceImpl implements User2ThemeService {
     }
 
     @Override
+    public List<User2Theme> findByUserIdAndThemeIdAndOperationNot(long userId, long themeId, String operation) {
+        return user2ThemeDao.findByUserIdAndThemeIdAndOperationNot(userId,themeId,operation);
+    }
+
+    @Override
     public void updateOperationById(long id, String operation) {
         user2ThemeDao.updateOperationById(id, operation);
     }

+ 2 - 2
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/ctrl/ThemeController.java

@@ -82,7 +82,7 @@ public class ThemeController extends BaseSearchController {
     }
 
     /**
-     * fork课程时,教师对课程fork指定班级
+     * fork课程时,教师对课程fork指定班级,并校验是否具有未授权课程的章节
      * @param themeId
      * @return
      */
@@ -578,7 +578,7 @@ public class ThemeController extends BaseSearchController {
     }
 
     /**
-     * 管理员为教师授权课程-查找课程(公开的、已发布的、未删除的、付费课程)
+     * 管理员为教师授权课程-查找课程(公开的、已发布的、未删除的、公开课程)
      * @param courseName
      * @return
      */

+ 75 - 3
mooctest-site-server/src/main/java/cn/iselab/mooctest/site/web/logic/impl/ThemeLogicImpl.java

@@ -23,12 +23,10 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
-import javax.mail.Session;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -81,6 +79,8 @@ public class ThemeLogicImpl implements ThemeLogic {
     @Autowired
     private User2RoleService user2RoleService;
     @Autowired
+    private OperationRecourseService operationRecourseService;
+    @Autowired
     private RoleService roleService;
     @Autowired
     private OSSLogic ossLogic;
@@ -109,11 +109,65 @@ public class ThemeLogicImpl implements ThemeLogic {
 
     @Override
     public List<GroupVO> getForkCourseGroups(long themeId) {
-        Theme2Group theme2Group = theme2GroupService.findByThemeId(themeId);
+        // 判断对被fork课程的使用权限
         Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
+        List<User2Theme> user2ThemeList = user2ThemeService.findAllByUserIdAndThemeId(userId, themeId);
+        // 使用权限要为* 或者 use
+        List<User2Theme> user2Themes = user2ThemeList.stream().filter(user2Theme -> user2Theme.getOperation() != User2Theme.AUTH_VIEW).collect(Collectors.toList());
+        if(user2Themes.size() <= 0){
+            throw new HttpBadRequestException("fork失败,当前用户并无对此课程的使用权限!");
+        }
+        // 判断对被fork课程的章节是否是 已授权的非自定义课程中的章节
+        // 获取被fork课程的所有章节 -> 所有公开的章节
+        List<Long> courseResourceIdList = themeService.getThemeEntityRelations(themeId, EntityTypeEnum.COURSE_RESOURCE).stream().map(ThemeEntityRelations::getEntityId).collect(Collectors.toList());
+        boolean canFork = true;
+        String message = "";
+        // 如果存在章节则需要判断
+        if(courseResourceIdList.size() > 0){
+            List<Long> publicResourceIdList = courseResourceService.getCourseResourceById(courseResourceIdList).stream()
+                    .filter(resource -> resource.getPublicStatus() == CourseResource.IS_PUBLIC)
+                    .map(CourseResource::getId).collect(Collectors.toList());
+            // 如果存在公开的章节则需要判断
+            if(publicResourceIdList.size() > 0){
+                // 根据这些公开章节获取所有已使用当前章节的 公开课程
+                for(Long resourceId : publicResourceIdList){
+                    List<OperationResource> operationRecourseList = operationRecourseService.getOperationRecourseList(userId, User2Theme.AUTH_VIEW, resourceId, CourseResource.NOT_Deleted, CourseResource.IS_PUBLIC, ThemeDetail.IS_PUBLIC, ThemeDetail.COURSE, ThemeDetail.NOT_DELETED);
+                    if(operationRecourseList.size() <= 0){
+                        canFork = false;
+                        message += " \"" + courseResourceService.getCourseResourceByResourceId(resourceId).getTitle() + "\"";
+                    }
+                }
+            }
+        }
+        if(!canFork){
+            throw new HttpBadRequestException("fork失败,被fork的课程中含有未授权的课程中的章节:" + message + "!");
+        }
+
+        // 允许被fork
+        Theme2Group theme2Group = theme2GroupService.findByThemeId(themeId);
         List<Group> groups = groupService.getGroupsByOwnerId(userId);
         List<GroupVO> groupVOs = groupVOWrapper.wrap(groups);
         return groupVOs.stream().filter(groupVO -> !groupVO.getId().equals(theme2Group.getGroupId())).collect(Collectors.toList());
+
+//        List<List<Boolean>> flagBooleanList = publicResourceIdList.stream().map(publicResourceId -> {
+//            List<Long> themeDetailIdList = themeService.getThemeEntityRelationsByEntityId(publicResourceId, EntityTypeEnum.COURSE_RESOURCE)
+//                    .stream().map(ThemeEntityRelations::getThemeId).collect(Collectors.toList());
+//            // 根据这些公开章节获取所有已使用当前章节的公开课程,判断是否具有这些公开课程的使用权限
+//            return themeDetailIdList.stream().map(themeDetailId -> {
+//                // 获取公开课程,判断使用去哪些
+//                if(themeService.getThemeDetailById(themeDetailId)!=null && themeService.getThemeDetailById(themeDetailId).getPublicStatus() == ThemeDetail.IS_PUBLIC){
+//                    if (user2ThemeService.findByUserIdAndThemeIdAndOperationNot(userId, themeDetailId, User2Theme.AUTH_VIEW).size() > 0) {
+//                        return true;
+//                    }
+//                }
+//                return false;
+//            }).collect(Collectors.toList());
+//        }).collect(Collectors.toList());
+//        for(List<Boolean> flags : flagBooleanList){
+//            if(flags.contains(true)){
+//                canFork = true;
+//            }
+//        }
     }
 
     @Override
@@ -896,6 +950,24 @@ public class ThemeLogicImpl implements ThemeLogic {
         Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute("userId");
         // 章节实体
         List<CourseResourceVO> courseResourceVOS = entityVOList.stream().filter(entityVO -> entityVO.getEntityType().equals(EntityTypeEnum.COURSE_RESOURCE)).map(entityVO -> {
+            // 判断对add的章节是否是 已授权的非自定义课程中的章节
+            boolean canAdd = true;
+            String message = "";
+            CourseResource resource = courseResourceService.getCourseResourceByResourceId(entityVO.getEntityId());
+            // 如果存在公开的章节则需要判断
+            if(resource.getPublicStatus() == CourseResource.IS_PUBLIC){
+                // 根据这些公开章节获取所有已使用当前章节的 公开课程
+                List<OperationResource> operationRecourseList = operationRecourseService.getOperationRecourseList(userId, User2Theme.AUTH_VIEW, resource.getId(), CourseResource.NOT_Deleted, CourseResource.IS_PUBLIC, ThemeDetail.IS_PUBLIC, ThemeDetail.COURSE, ThemeDetail.NOT_DELETED);
+                if(operationRecourseList.size() <= 0){
+                    canAdd = false;
+                    message += " \"" + resource.getTitle() + "\"";
+                }
+            }
+
+            if(!canAdd){
+                throw new HttpBadRequestException("添加"+message+"章节失败,您未此章节所属公开课程的使用权限!");
+            }
+
             // entityVO.getThemeId()此时entityVO中传了当前课程的id
             ThemeDetail themeDetail = themeService.getThemeDetailById(entityVO.getThemeId());
             // 根据课程的公开类型 设置章节的默认预览状态