Переглянути джерело

feat: group移植(未可用),还有老逻辑需要删除

370774330@qq.com 5 роки тому
батько
коміт
35d398b93d

+ 4 - 5
web/pom.xml

@@ -63,11 +63,6 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-mail</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-tomcat</artifactId>
-            <scope>provided</scope>
-        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -84,6 +79,10 @@
             <artifactId>mybatis-spring-boot-starter</artifactId>
             <version>2.1.4</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 2 - 0
web/src/main/java/seecoder/devcloud/web/DevcloudWebApplication.java

@@ -1,5 +1,6 @@
 package seecoder.devcloud.web;
 
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.annotation.ComponentScan;
@@ -14,6 +15,7 @@ import java.util.TimeZone;
 @EnableAsync
 @SpringBootApplication
 @ComponentScan({"seecoder.devcloud.api","seecoder.devcloud.common","seecoder.devcloud.web"})
+@MapperScan("seecoder.devcloud.web.dao")
 public class DevcloudWebApplication {
 
     public static void main(String[] args) {

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/dao/InsertUpdateSqlProvider.java

@@ -10,7 +10,7 @@ import java.util.Map;
 /**
  * @author PuHong Weng
  * @date 2021/3/1
- * @description: 帮助快速写插入和更新的,注意 pojo类的字段要和数据库表对应
+ * @description: 帮助快速写插入和更新的,注意 pojo类的字段要和数据库表对应, 用法示例见 UserMapper.class
  */
 public class InsertUpdateSqlProvider {
     public static String insert(Object obj) {

+ 35 - 0
web/src/main/java/seecoder/devcloud/web/dao/user/GroupMapper.java

@@ -0,0 +1,35 @@
+package seecoder.devcloud.web.dao.user;
+
+
+
+import org.apache.ibatis.annotations.*;
+import seecoder.devcloud.web.dao.InsertUpdateSqlProvider;
+import seecoder.devcloud.web.po.user.Group;
+
+import java.awt.geom.GeneralPath;
+import java.util.List;
+
+/**
+ * Description:
+ *
+ * @author xxz
+ * Created on 10/30/2018
+ */
+@Mapper
+public interface GroupMapper {
+
+
+    @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
+    @SelectKey(statement = "select LAST_INSERT_KEY()", keyProperty = "id", before = false, resultType = Long.class)
+    @InsertProvider(type = InsertUpdateSqlProvider.class, method = "insert")
+    int insert(Group group);
+
+    @UpdateProvider(type= InsertUpdateSqlProvider.class, method="updateById")
+    int update(Group group);
+
+
+    Group findGroupById(Integer id);
+    Group findGroupByShareLink(String shareLink);
+
+
+}

+ 19 - 0
web/src/main/java/seecoder/devcloud/web/enums/GroupType.java

@@ -0,0 +1,19 @@
+package seecoder.devcloud.web.enums;
+
+/**
+ * Description:
+ * 群组类型
+ *
+ * @author xxz
+ * Created on 10/26/2018
+ */
+public enum GroupType {
+    /**
+     * 课程内由学生组成的小组
+     */
+    GROUP,
+    /**
+     * 课程
+     */
+    CLASS
+}

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/config/SwaggerConfig.java → web/src/main/java/seecoder/devcloud/web/infrastructure/config/SwaggerConfig.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.config;
+package seecoder.devcloud.web.infrastructure.config;
 
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;

+ 81 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/security/WebSecurityConfiguration.java

@@ -0,0 +1,81 @@
+//package seecoder.devcloud.web.infrastructure.security;
+//
+//
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+//import org.springframework.security.config.annotation.web.builders.WebSecurity;
+//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+//import org.springframework.security.core.userdetails.UserDetailsService;
+//import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+//import seecoder.devcloud.api.ApplicationProperties;
+//import seecoder.devcloud.web.dao.user.UserMapper;
+//import seecoder.devcloud.web.service.user.UserService;
+//
+//
+//@EnableWebSecurity
+//@EnableGlobalMethodSecurity(jsr250Enabled = true)
+//public class WebSecurityConfiguration {
+////	@Configuration
+////	@Order(Ordered.LOWEST_PRECEDENCE)
+////	public static class ApiWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
+////		@Override
+////		protected void configure(HttpSecurity http) throws Exception {
+////			http.antMatcher("/api/**")
+////					.authorizeRequests()
+////					.anyRequest().authenticated()
+////					.and()
+////					.httpBasic()
+////					.and()
+////					.csrf().disable()
+////					.cors();
+////		}
+////	}
+//
+//	@Configuration
+//	public static class DefaultWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
+//		private final UserDetailsService userDetailsService;
+//		private final LoginRedirectHandler loginRedirectHandler;
+//		@Autowired
+//		private UserMapper userMapper;
+//		@Autowired
+//		private ApplicationProperties applicationProperties;
+//		@Autowired
+//		private UserService userService;
+//
+//		@Autowired
+//		public DefaultWebSecurityConfiguration(UserDetailsServiceImpl userDetailsService, LoginRedirectHandler loginRedirectHandler) {
+//			this.userDetailsService = userDetailsService;
+//			this.loginRedirectHandler = loginRedirectHandler;
+//		}
+//		@Override
+//		protected void configure(HttpSecurity http) throws Exception {
+//			JwtAuthenticationFilter jwtAuthenticationFilter =
+//					new JwtAuthenticationFilter(authenticationManager(),
+//							userDetailsService, new RestAuthorEntry(),
+//							new AntPathRequestMatcher("/api/auth/receive", "GET"),
+//							applicationProperties,
+//							userMapper,
+//							userService);
+//			http
+//					.authorizeRequests()
+//						.antMatchers("/api/auth/register","/test" ,"/internal/**").permitAll()
+//			 			.antMatchers("/file/**").hasAnyAuthority(TEACHER_AUTHORITY.getAuthority(), ADMIN_AUTHORITY.getAuthority())
+//						.anyRequest().authenticated()
+//						.and()
+//						.addFilter(jwtAuthenticationFilter)
+//						.cors()
+//						.and()
+//						.csrf().disable();
+//		}
+//
+//		@Override
+//		public void configure(WebSecurity web) throws Exception {
+//			web
+//					.ignoring()
+//					.antMatchers("/api/auth/register","/test" ,"/internal/**");
+//		}
+//	}
+//}

+ 16 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/security/WebSecurityConstants.java

@@ -0,0 +1,16 @@
+package seecoder.devcloud.web.infrastructure.security;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+public abstract class WebSecurityConstants {
+	private static final String ROLE_PREFIX = "ROLE_";
+
+	public static final String STUDENT_ROLE = "STUDENT";
+	public static final String TEACHER_ROLE = "TEACHER";
+	public static final String ADMIN_ROLE = "ADMIN";
+
+	public static final GrantedAuthority STUDENT_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + STUDENT_ROLE);
+	public static final GrantedAuthority TEACHER_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + TEACHER_ROLE);
+	public static final GrantedAuthority ADMIN_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + ADMIN_ROLE);
+}

+ 42 - 0
web/src/main/java/seecoder/devcloud/web/po/user/Group.java

@@ -0,0 +1,42 @@
+package seecoder.devcloud.web.po.user;
+
+
+import lombok.Data;
+import seecoder.devcloud.web.enums.GroupType;
+
+import java.util.List;
+
+/**
+ * Description:
+ * 小组的实体类
+ *
+ * @author xxz
+ * Created on 10/26/2018
+ */
+@Data
+public class Group {
+
+    private Integer id;
+
+    private Integer namespace;
+    /**
+     * 小组类型
+     */
+    private GroupType type;
+
+    /**
+     * 小组的加组链接
+     */
+    private String shareLink;
+
+    /**
+     * 组名
+     */
+    private String name;
+
+    /**
+     * 小组成员
+     */
+    private List<User> members;
+
+}

+ 121 - 0
web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImp.java

@@ -0,0 +1,121 @@
+//package seecoder.devcloud.web.service.impl.user;
+//
+//
+//import org.gitlab4j.api.GitLabApiException;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.ApplicationContext;
+//import org.springframework.stereotype.Service;
+//import org.springframework.transaction.annotation.Transactional;
+//import seecoder.devcloud.api.gitlab.GitlabApi;
+//import seecoder.devcloud.api.gitlab.model.GitlabGroup;
+//import seecoder.devcloud.common.exceptions.EntityNotFoundException;
+//import seecoder.devcloud.web.dao.user.GroupMapper;
+//import seecoder.devcloud.web.dao.user.UserMapper;
+//import seecoder.devcloud.web.enums.GroupType;
+//import seecoder.devcloud.web.po.user.Group;
+//import seecoder.devcloud.web.po.user.User;
+//import seecoder.devcloud.web.service.user.GroupService;
+//import seecoder.devcloud.web.vo.user.CustomUserDetails;
+//import seecoder.devcloud.web.vo.user.GroupVO;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.UUID;
+//
+///**
+// * @ClassName GroupServiceImp
+// * @PackageName com.moekr.moocoder.logic.service.impl
+// * @Author sheen
+// * @Date 2019/1/9
+// * @Version 1.0
+// * @Description //TODO
+// **/
+//@Service
+//public class GroupServiceImp implements GroupService {
+//    private final GroupMapper groupMapper;
+//    private final UserMapper userMapper;
+//    private final GitlabApi gitlabApi;
+//    @Autowired
+//    ApplicationContext applicationContext;
+//
+//    @Autowired
+//    public GroupServiceImp(GroupMapper groupMapper, UserMapper userMapper, GitlabApi gitlabApi) {
+//        this.groupMapper = groupMapper;
+//        this.userMapper = userMapper;
+//        this.gitlabApi = gitlabApi;
+//    }
+//
+//    @Override
+//    @Transactional
+//    public GroupVO createGroup(String name, Integer courseId, CustomUserDetails userDetails) throws EntityNotFoundException {
+//
+//        User user = userMapper.findByUsername(userDetails.getUsername());
+//        final boolean isJoin = user.getGroup().stream()
+//                .anyMatch(g -> g.getCourses().getId().equals(courseId));
+//        if (isJoin) {
+//            throw new RuntimeException("已经加入小组!");
+//        }
+//        //todo:判断学生是否选课
+//        List<User> members = new ArrayList<>();
+//        members.add(user);
+//        GitlabGroup gitGroup;
+//        try {
+//            gitGroup = gitlabApi.createGroup(name);
+//            gitlabApi.addMemberToGroup(gitGroup.getId(), user.getId());
+//        } catch (GitLabApiException e) {
+//            throw new RuntimeException("创建Group时发生异常[" + e.getMessage() + "]");
+//        }
+//        Group group = new Group();
+//        group.setId(gitGroup.getId());
+//        group.setMembers(members);
+//        group.setName(name);
+//        group.setNamespace(gitGroup.getNamespace());
+//        group.setShareLink(UUID.randomUUID().toString().replace("-", ""));
+//        group.setType(GroupType.GROUP);
+//        groupMapper.insert(group);
+//        userMapper.save(user);
+//        // 发出小组创建的事件
+//        GroupVO groupVO = new GroupVO(group);
+//        applicationContext.publishEvent(new GroupCreateEvent(this, courseId, groupVO));
+//        return groupVO;
+//    }
+//
+//
+//    @Override
+//    @Transactional
+//    public GroupVO addMember(String code, CustomUserDetails userDetails) throws EntityNotFoundException {
+//        Group group = groupMapper.findGroupByShareLink(code);
+//        if (group == null) {
+//            throw new EntityNotFoundException("小组码错误!");
+//        }
+//        User user = userMapper.findByUsername(userDetails.getUsername());
+//        final boolean haveCourse = user.getCourses().contains(group.getCourses());
+//        if (!haveCourse) {
+//            throw new RuntimeException("尚未加入课程!");
+//        } else {
+//            final boolean isJoin = user.getGroup().stream()
+//                    .anyMatch(g -> g.getCourses().getId().equals(group.getCourses().getId()));
+//            if (isJoin) {
+//                throw new RuntimeException("已经加入小组!");
+//            }
+//            group.getMembers().add(user);
+//            try {
+//                gitlabApi.addMemberToGroup(group.getId(), user.getId());
+//            } catch (GitLabApiException e) {
+//                throw new RuntimeException("将成员加入Group时发生异常[" + e.getMessage() + "]");
+//            }
+//            groupMapper.save(group);
+//            userMapper.save(user);
+//            return new GroupVO(group);
+//        }
+//
+//    }
+//
+//
+//    @Override
+//    public GroupVO getGroupsById(Integer groupId) {
+//        Group get= groupMapper.findById(groupId).orElseGet(Group::new);
+//
+//        return new GroupVO(get);
+//    }
+//}

+ 26 - 0
web/src/main/java/seecoder/devcloud/web/service/user/GroupService.java

@@ -0,0 +1,26 @@
+package seecoder.devcloud.web.service.user;
+
+
+
+import seecoder.devcloud.common.exceptions.EntityNotFoundException;
+import seecoder.devcloud.web.vo.user.CustomUserDetails;
+import seecoder.devcloud.web.vo.user.GroupVO;
+import seecoder.devcloud.web.vo.user.InnerGroupVO;
+
+import java.util.List;
+
+/**
+ * @InterfaceName GroupService
+ * @PackageName com.moekr.moocoder.logic.service.impl
+ * @Author sheen
+ * @Date 2019/1/9
+ * @Version 1.0
+ * @Description //TODO
+ **/
+public interface GroupService {
+    GroupVO createGroup(String name, Integer courseId, CustomUserDetails userDetails) throws EntityNotFoundException;
+
+    GroupVO addMember(String code, CustomUserDetails userDetails) throws EntityNotFoundException;
+
+    GroupVO getGroupsById(Integer groupId);
+}

+ 85 - 0
web/src/main/java/seecoder/devcloud/web/vo/user/CustomUserDetails.java

@@ -0,0 +1,85 @@
+package seecoder.devcloud.web.vo.user;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import lombok.*;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import seecoder.devcloud.web.po.user.User;
+
+import java.util.Collections;
+import java.util.Set;
+
+import static seecoder.devcloud.web.enums.UserIdentity.STUDENT;
+import static seecoder.devcloud.web.enums.UserIdentity.TEACHER;
+import static seecoder.devcloud.web.infrastructure.security.WebSecurityConstants.*;
+
+
+@Data
+@EqualsAndHashCode
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CustomUserDetails implements UserDetails {
+	private Integer id;
+	private String username;
+	private String password;
+	private Set<GrantedAuthority> authorities;
+
+	CustomUserDetails(User user) {
+		BeanUtils.copyProperties(user, this);
+		switch (user.getRole()) {
+			case STUDENT:
+				this.authorities = Collections.singleton(STUDENT_AUTHORITY);
+				break;
+			case TEACHER:
+				this.authorities = Collections.singleton(TEACHER_AUTHORITY);
+				break;
+			default:
+				throw new UsernameNotFoundException(username);
+		}
+	}
+
+	CustomUserDetails(String username, String password) {
+		this.id = 0;
+		this.username = username;
+		this.password = DigestUtils.sha256Hex(password);
+		this.authorities = Collections.singleton(ADMIN_AUTHORITY);
+	}
+
+	@Override
+	public boolean isAccountNonExpired() {
+		return true;
+	}
+
+	@Override
+	public boolean isAccountNonLocked() {
+		return true;
+	}
+
+	@Override
+	public boolean isCredentialsNonExpired() {
+		return true;
+	}
+
+	@Override
+	public boolean isEnabled() {
+		return true;
+	}
+
+	public boolean isStudent() {
+		return authorities.contains(STUDENT_AUTHORITY);
+	}
+
+	public boolean isTeacher() {
+		return authorities.contains(TEACHER_AUTHORITY);
+	}
+
+	public boolean isAdmin() {
+		return authorities.contains(ADMIN_AUTHORITY);
+	}
+}

+ 31 - 0
web/src/main/java/seecoder/devcloud/web/vo/user/InnerGroupVO.java

@@ -0,0 +1,31 @@
+package seecoder.devcloud.web.vo.user;
+
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import seecoder.devcloud.web.po.user.Group;
+import seecoder.devcloud.web.po.user.User;
+
+import java.util.List;
+
+/**
+ * 暂定为系统内部给作业部分使用的VO
+ */
+@Data
+@EqualsAndHashCode(exclude = {"members"})
+@ToString(exclude = {"members"})
+public class InnerGroupVO {
+    private Integer id;
+    private Integer namespace;
+    private String name;
+    private List<User> members;
+
+
+    public InnerGroupVO(Group group) {
+        this.id = group.getId();
+        this.namespace = group.getNamespace();
+        this.name = group.getName();
+        this.members = group.getMembers();
+    }
+}

+ 2 - 2
web/src/main/resources/application-wph.yml

@@ -1,13 +1,13 @@
 spring:
   datasource:
-    url: jdbc:mysql://localhost:3306/seecoder?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
+    url: jdbc:mysql://192.168.99.105:30006/seecoder?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
     username: root
     password: 123456
 
   mail:
     host: smtp.qq.com
     username: 370774330@qq.com
-    password: Wshengdasogood0
+    password: test
 server:
   port: 8080
 

+ 1 - 1
web/src/test/java/seecoder/devcloud/web/ArchitectWebApplicationTests.java → web/src/test/java/seecoder/devcloud/web/DevcloudWebApplicationTests.java

@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
 @SpringBootTest
-class devcloudWebApplicationTests {
+class DevcloudWebApplicationTests {
 
 
 }