Crystal.Sea hace 4 años
padre
commit
a44022b625
Se han modificado 23 ficheros con 473 adiciones y 167 borrados
  1. 1 1
      README.md
  2. 19 11
      ReleaseNotes.txt
  3. 1 1
      gradle.properties
  4. 11 0
      maxkey-core/src/main/java/org/maxkey/domain/ExcelImport.java
  5. 12 0
      maxkey-core/src/main/java/org/maxkey/domain/Organizations.java
  6. 198 1
      maxkey-persistence/src/main/java/org/maxkey/persistence/service/OrganizationsService.java
  7. 62 52
      maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java
  8. 12 12
      maxkey-persistence/src/test/resources/application.properties
  9. 1 1
      maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedJWTAdapter.java
  10. 1 1
      maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedJWTHS256Adapter.java
  11. 16 1
      maxkey-web-manage/src/main/java/org/maxkey/web/contorller/OrganizationsController.java
  12. 0 12
      maxkey-web-manage/src/main/java/org/maxkey/web/contorller/UserInfoController.java
  13. 11 0
      maxkey-web-manage/src/main/resources/messages/message.properties
  14. 13 1
      maxkey-web-manage/src/main/resources/messages/message_en.properties
  15. 11 0
      maxkey-web-manage/src/main/resources/messages/message_zh_CN.properties
  16. BIN
      maxkey-web-manage/src/main/resources/static/template/excel/Orgs_Import_Template.xlsx
  17. BIN
      maxkey-web-manage/src/main/resources/static/template/excel/Users_Import_Template.xlsx
  18. 67 0
      maxkey-web-manage/src/main/resources/templates/views/orgs/orgsImport.ftl
  19. 5 1
      maxkey-web-manage/src/main/resources/templates/views/orgs/orgsList.ftl
  20. 0 64
      maxkey-web-manage/src/main/resources/templates/views/userinfo/changeUserinfoStatus.ftl
  21. 7 2
      maxkey-web-manage/src/main/resources/templates/views/userinfo/userUpdate.ftl
  22. 22 3
      maxkey-web-manage/src/main/resources/templates/views/userinfo/usersImport.ftl
  23. 3 3
      maxkey-web-manage/src/main/resources/templates/views/userinfo/usersList.ftl

+ 1 - 1
README.md

@@ -89,7 +89,7 @@
 当前版本百度网盘下载,<a href="https://maxkey.top/zh/download.html" target="_blank"> 历史版本</a>
 | 版本    | 日期   |  下载地址  |  提取码  |
 | --------| :-----  | :----  | :----:  |
-| v 2.2.0 GA | 2020/09/24   |  <a href="https://pan.baidu.com/s/1gtgELidq1F-GwvmxKbY_oA" target="_blank">链接下载</a>  |  **0y9o**  |
+| v 2.3.0 GA | 2020/11/11   |  <a href="https://pan.baidu.com/s/17jAatKNlM6L649992kEMBQ" target="_blank">链接下载</a>  |  **h3zw**  |
 
 
 # Roadmap

+ 19 - 11
ReleaseNotes.txt

@@ -1,28 +1,36 @@
-MaxKey v 2.3.0 GA	2020/11/**
+MaxKey v 2.3.0 GA	2020/11/12
  	*(MAXKEY-200901)  基于spring session的集群会话共享功能 
     *(MAXKEY-200902) 单点注销功能,应用可以配置为NONE/BACK_CHANNEL/FRONT_CHANNEL三种方式,支持CAS/SAML/Default
 	*(MAXKEY-200903)  用户在线实时更新功能
-	*(MAXKEY-200904)  批量Excel用户导入功能
-	*(MAXKEY-200905)  用户注册功能
-	*(MAXKEY-200906)  用户状态修改
-	*(MAXKEY-200907)  用户详情显示问题
-	*(MAXKEY-200908)  应用修改时数字大于4为长度格式化问题
+	*(MAXKEY-200904)  定制用户模板,实现批量Excel用户导入功能
+	*(MAXKEY-200905)   定制机构模板,实现批量Excel机构导入功能
+	*(MAXKEY-200906)  用户注册功能
+	*(MAXKEY-200907)  用户状态修改
+	*(MAXKEY-200908)  用户详情显示问题
+	*(MAXKEY-200909)  应用修改时数字大于4为长度格式化问题
 	*(MAXKEY-200910)  注销后,点击重新登陆跳转问题
 	*(MAXKEY-200911)  增加SP登录跳转功能,支持knox的认证
 	*(MAXKEY-200912)  构建脚本的优化和更新
-	*(MAXKEY-200913)  权限控制 RoleAdministrators 
+	*(MAXKEY-200913)  管理员权限控制 RoleAdministrators 
 	*(MAXKEY-200914)  社交账号登录优化
 	*(MAXKEY-200915)  列表界面中未”选择“情况下,弹出界面错误
 	*(MAXKEY-200916) jib(docker) 支持 ,感谢https://github.com/alanland
-	*(MAXKEY-200916)  登录过程的优化
-	*(MAXKEY-200917)  认证的优化,支持@Principal的注入
-	*(MAXKEY-200918) 应用单点登录时,用户访问权限控制
-	*(MAXKEY-200920)  依赖jar引用、更新和升级
+	*(MAXKEY-200917)  登录过程的优化
+	*(MAXKEY-200918)  认证的优化,支持@Principal的注入
+	*(MAXKEY-200919) 应用单点登录时,用户访问权限控制
+	*(MAXKEY-200920) maxkey-mgt 项目配置文件的验证码启用不启用配置未生效
+	*(MAXKEY-200921) 登录图标改进
+	*(MAXKEY-200922)  官方网站的优化
+	*(MAXKEY-200923)  依赖jar引用、更新和升级
 	    druid 1.2.1
 	    JustAuth 1.15.8
 	    simple-http 1.0.3
 	    spring-session 2.3.1.RELEASE
 	    druid-spring-boot-starter 1.2.1
+	    xmlbeans  3.0.1
+	    commons-compress 1.20
+	    poi 4.1.2
+	    commons-collections4 4.4
  
 MaxKey v 2.2.0 GA	2020/09/24
 	*(MAXKEY-200801)  官方网站内容调整,初步增加英文版支持,增加新闻、合作伙伴及与CAS等开源产品对比

+ 1 - 1
gradle.properties

@@ -1,5 +1,5 @@
 group	=maxkey.top
-version	=2.2.0.RELEASE
+version	=2.3.0.RELEASE
 vendor	=https://www.maxkey.top
 author	=shimingxy
 #Version For use jar

+ 11 - 0
maxkey-core/src/main/java/org/maxkey/domain/ExcelImport.java

@@ -44,6 +44,9 @@ public class ExcelImport extends JpaBaseDomain {
  
     @JsonIgnore
     protected MultipartFile excelFile;
+    
+    
+    String updateExist;
 
     public ExcelImport() {
         super();
@@ -57,6 +60,14 @@ public class ExcelImport extends JpaBaseDomain {
         this.id = id;
     }
 
+    public String getUpdateExist() {
+        return updateExist;
+    }
+
+    public void setUpdateExist(String updateExist) {
+        this.updateExist = updateExist;
+    }
+
     public MultipartFile getExcelFile() {
         return excelFile;
     }

+ 12 - 0
maxkey-core/src/main/java/org/maxkey/domain/Organizations.java

@@ -80,6 +80,8 @@ public class Organizations extends JpaBaseDomain implements Serializable {
     private String sortIndex;
     @Column
     private String description;
+    
+    private String status;
 
     public Organizations() {
         // TODO Auto-generated constructor stub
@@ -286,6 +288,16 @@ public class Organizations extends JpaBaseDomain implements Serializable {
     public void setSortIndex(String sortIndex) {
         this.sortIndex = sortIndex;
     }
+    
+    
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
 
     @Override
     public String toString() {

+ 198 - 1
maxkey-persistence/src/main/java/org/maxkey/persistence/service/OrganizationsService.java

@@ -17,7 +17,22 @@
 
 package org.maxkey.persistence.service;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
 import org.apache.mybatis.jpa.persistence.JpaBaseService;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.maxkey.domain.Organizations;
 import org.maxkey.identity.kafka.KafkaIdentityAction;
 import org.maxkey.identity.kafka.KafkaIdentityTopic;
@@ -25,6 +40,10 @@ import org.maxkey.identity.kafka.KafkaProvisioningService;
 import org.maxkey.persistence.mapper.OrganizationsMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.common.collect.Lists;
 
 @Service
 public class OrganizationsService  extends JpaBaseService<Organizations>{
@@ -71,5 +90,183 @@ public class OrganizationsService  extends JpaBaseService<Organizations>{
          }
          return false;
 	 }
-	
+	 
+	    public boolean importing(MultipartFile file) {
+	        if(file ==null){
+	            return false;
+	        }
+	        InputStream is = null;
+	        Workbook wb = null;
+	        List<Organizations> orgsList = null;
+	        try {
+	            is = file.getInputStream();
+	            
+	            String xls = ".xls";
+	            String xlsx = ".xlsx";
+	            int columnSize = 46;
+	            orgsList = Lists.newArrayList();
+	            if (file.getOriginalFilename().toLowerCase().endsWith(xls)) {
+	                wb = new HSSFWorkbook(is);
+	            } else if (file.getOriginalFilename().toLowerCase().endsWith(xlsx)) {
+	                wb = new XSSFWorkbook(is);
+	            } else {
+	                throw new RuntimeException("maxKey用户导入没有Excel类型");
+	            }
+
+	            int sheetSize = wb.getNumberOfSheets();
+	            //遍历sheet页
+	            for (int i = 0; i < sheetSize; i++) {
+	                Sheet sheet = wb.getSheetAt(i);
+
+	                int rowSize = sheet.getLastRowNum() + 1;
+	                //遍历行
+	                for (int j = 1; j < rowSize; j++) {
+	                    Row row = sheet.getRow(j);
+	                    //略过空行和前3行
+	                    if (row == null || j <3 ) {
+	                        continue;
+	                    } else {
+	                        //其他行是数据行
+	                        Organizations organization =new Organizations();
+
+	                        for (int k = 0; k < columnSize; k++) {
+	                            if (k == 0) {
+	                                // 上级编码
+	                                Cell cell = row.getCell(k);
+	                                organization.setParentId(getValue(cell));
+	                            } else if (k == 1) {
+	                                // 上级名称
+	                                Cell cell = row.getCell(k);
+	                                organization.setParentName(getValue(cell));
+	                            } else if (k == 2) {
+	                                // 机构编码
+	                                Cell cell = row.getCell(k);
+	                                organization.setId(getValue(cell));
+	                            } else if (k == 3) {
+	                                // 机构名称
+	                                Cell cell = row.getCell(k);
+	                                organization.setName(getValue(cell));
+	                            } else if (k == 4) {
+	                                // 机构全称
+	                                Cell cell = row.getCell(k);
+	                                organization.setFullName(getValue(cell));
+	                            } else if (k == 5) {
+	                                // 编码路径
+	                                Cell cell = row.getCell(k);
+	                                organization.setCodePath(getValue(cell));
+	                            } else if (k == 6) {
+	                                // 名称路径
+	                                Cell cell = row.getCell(k);
+	                                organization.setNamePath(getValue(cell));
+	                            } else if (k == 7) {
+	                                // 机构类型
+	                                Cell cell = row.getCell(k);
+	                                organization.setType(getValue(cell));
+	                            } else if (k == 8) {
+	                                // 所属分支机构
+	                                Cell cell = row.getCell(k);
+	                                organization.setDivision(getValue(cell));
+	                            } else if (k == 9) {
+	                                // 级别
+	                                Cell cell = row.getCell(k);
+	                                String level=getValue(cell);
+	                                organization.setLevel(level.equals("") ? "1" : level);
+	                            } else if (k == 10) {
+	                                // 排序
+	                                Cell cell = row.getCell(k);
+	                                String sortIndex=getValue(cell);
+	                                organization.setSortIndex(sortIndex.equals("") ? "1" : sortIndex);
+	                            } else if (k == 11) {
+	                                // 联系人
+	                                Cell cell = row.getCell(k);
+	                                organization.setContact(getValue(cell));
+	                            } else if (k == 12) {
+	                                // 联系电话
+	                                Cell cell = row.getCell(k);
+	                                organization.setPhone(getValue(cell));
+	                            }else if (k == 13) {
+	                                // 邮箱
+	                                Cell cell = row.getCell(k);
+	                                organization.setEmail(getValue(cell));
+	                            }else if (k == 14) {
+	                                // 传真
+	                                Cell cell = row.getCell(k);
+	                                organization.setFax(getValue(cell));
+	                            }else if (k == 24) {
+	                                // 工作-国家
+	                                Cell cell = row.getCell(k);
+	                                organization.setCountry(getValue(cell));
+	                            }else if (k == 25) {
+	                                // 工作-省
+	                                Cell cell = row.getCell(k);
+	                                organization.setRegion(getValue(cell));
+	                            }else if (k == 26) {
+	                                // 工作-城市
+	                                Cell cell = row.getCell(k);
+	                                organization.setLocality(getValue(cell));
+	                            }else if (k == 27) {
+	                                // 工作-地址
+	                                Cell cell = row.getCell(k);
+	                                organization.setLocality(getValue(cell));
+	                            }else if (k == 28) {
+	                                // 邮编
+	                                Cell cell = row.getCell(k);
+	                                organization.setPostalCode(getValue(cell));
+	                            }else if (k == 29) {
+	                                // 详细描述
+	                                Cell cell = row.getCell(k);
+	                                organization.setDescription(getValue(cell));
+	                            }
+	                        }
+	                        organization.setStatus("1");
+	                        orgsList.add(organization);
+	                    }
+	                    
+	                }
+	            }
+	            // 数据去重
+	            if(CollectionUtils.isEmpty(orgsList)){
+	                orgsList = orgsList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getId()))), ArrayList::new));
+	            }
+	           
+	        } catch (IOException e) {
+	            e.printStackTrace();
+	        }finally {
+	            if (is != null) {
+	                try {
+	                    is.close();
+	                } catch (IOException e) {
+	                    e.printStackTrace();
+	                }
+	            }
+	            if(wb != null) {
+	                try {
+	                    wb.close();
+	                } catch (IOException e) {
+	                    e.printStackTrace();
+	                }
+	            }
+	        }
+	       
+	        return batchInsert(orgsList);
+	    }
+
+	 /**
+	     *       根据数据格式返回数据
+     *
+     * @param cell
+     * @return
+     */
+    public static String getValue(Cell cell) {
+        if (cell == null) {
+            return "";
+        } else if (cell.getCellType() == CellType.BOOLEAN) {
+            return String.valueOf(cell.getBooleanCellValue());
+        } else if (cell.getCellType() == CellType.NUMERIC) {
+            cell.setBlank();
+            return String.valueOf(cell.getStringCellValue().trim());
+        } else {
+            return String.valueOf(cell.getStringCellValue().trim());
+        }
+    }
 }

+ 62 - 52
maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java

@@ -90,7 +90,6 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 	 */
 	@Override
 	public UserInfoMapper getMapper() {
-		// TODO Auto-generated method stub
 		return (UserInfoMapper)super.getMapper();
 	}
 	
@@ -357,10 +356,11 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
             return false;
         }
         InputStream is = null;
+        Workbook wb = null;
         List<UserInfo> userInfoList = null;
         try {
             is = file.getInputStream();
-            Workbook wb;
+            
             String xls = ".xls";
             String xlsx = ".xlsx";
             int columnSize = 46;
@@ -382,15 +382,14 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
                 //遍历行
                 for (int j = 1; j < rowSize; j++) {
                     Row row = sheet.getRow(j);
-                    //略过空行和第一
-                    if (row == null || j <2 ) {
+                    //略过空行和前3
+                    if (row == null || j <3 ) {
                         continue;
                     } else {
                         //其他行是数据行
                         UserInfo userInfo = new UserInfo();
                         userInfo.setCreatedDate(DateUtils.formatDateTime(new Date()));
 
-                        int rangeType = -1;
                         for (int k = 0; k < columnSize; k++) {
                             if (k == 0) {
                                 // 登录账号
@@ -401,61 +400,62 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
                                 Cell cell = row.getCell(k);
                                 userInfo.setPassword(getValue(cell));
                             } else if (k == 2) {
-                                // 员工编码
-                                Cell cell = row.getCell(k);
-                                userInfo.setEmployeeNumber(getValue(cell));
-                            } else if (k == 3) {
-                                // 用户类型
-                                Cell cell = row.getCell(k);
-                                userInfo.setUserType(getValue(cell));
-                            } else if (k == 4) {
-                                // 用户名
+                                // 用户显示
                                 Cell cell = row.getCell(k);
                                 userInfo.setDisplayName(getValue(cell));
-                            } else if (k == 5) {
+                            } else if (k == 3) {
                                 // 姓
                                 Cell cell = row.getCell(k);
                                 userInfo.setFamilyName(getValue(cell));
-                            } else if (k == 6) {
+                            } else if (k == 4) {
                                 // 名
                                 Cell cell = row.getCell(k);
                                 userInfo.setGivenName(getValue(cell));
-                            } else if (k == 7) {
+                            } else if (k == 5) {
                                 // 中间名
                                 Cell cell = row.getCell(k);
                                 userInfo.setMiddleName(getValue(cell));
-                            } else if (k == 8) {
+                            } else if (k == 6) {
                                 // 昵称
                                 Cell cell = row.getCell(k);
                                 userInfo.setNickName(getValue(cell));
-                            } else if (k == 9) {
+                            } else if (k == 7) {
                                 // 性别
                                 Cell cell = row.getCell(k);
-                                userInfo.setGender(Integer.valueOf(getValue(cell)));
-                            } else if (k == 10) {
-                                // AD域账号
-                                Cell cell = row.getCell(k);
-                                userInfo.setWindowsAccount(getValue(cell));
-                            } else if (k == 11) {
-                                // 出生日期
-                                Cell cell = row.getCell(k);
-                                userInfo.setBirthDate(getValue(cell));
-                            } else if (k == 12) {
+                                String gender = getValue(cell);
+                                userInfo.setGender(gender.equals("")? 1 : Integer.valueOf(getValue(cell)));
+                            } else if (k == 8) {
                                 // 语言偏好
                                 Cell cell = row.getCell(k);
                                 userInfo.setPreferredLanguage(getValue(cell));
-                            } else if (k == 13) {
+                            } else if (k == 9) {
                                 // 时区
                                 Cell cell = row.getCell(k);
                                 userInfo.setTimeZone(getValue(cell));
-                            }else if (k == 14) {
+                            } else if (k == 10) {
+                                // 用户类型
+                                Cell cell = row.getCell(k);
+                                userInfo.setUserType(getValue(cell));
+                            } else if (k == 11) {
+                                // 员工编码
+                                Cell cell = row.getCell(k);
+                                userInfo.setEmployeeNumber(getValue(cell));
+                            } else if (k == 12) {
+                                // AD域账号
+                                Cell cell = row.getCell(k);
+                                userInfo.setWindowsAccount(getValue(cell));
+                            }else if (k == 13) {
                                 // 所属机构
                                 Cell cell = row.getCell(k);
                                 userInfo.setOrganization(getValue(cell));
-                            }else if (k == 15) {
+                            }else if (k == 14) {
                                 // 分支机构
                                 Cell cell = row.getCell(k);
                                 userInfo.setDivision(getValue(cell));
+                            }else if (k == 15) {
+                                // 部门编号
+                                Cell cell = row.getCell(k);
+                                userInfo.setDepartmentId(getValue(cell));
                             }else if (k == 16) {
                                 // 部门名称
                                 Cell cell = row.getCell(k);
@@ -528,54 +528,58 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
                                 // 证件号码
                                 Cell cell = row.getCell(k);
                                 userInfo.setIdCardNo(getValue(cell));
-                            }else if (k == 34) {
+                            } else if (k == 34) {
+                                // 出生日期
+                                Cell cell = row.getCell(k);
+                                userInfo.setBirthDate(getValue(cell));
+                            }else if (k == 35) {
                                 // 婚姻状态 todo 现在数据字段类型是 tinyint
 //                                Cell cell = row.getCell(k);
 //                                userInfo.setMarried(getValue(cell));
-                            }else if (k == 35) {
+                            }else if (k == 36) {
                                 // 开始工作时间
                                 Cell cell = row.getCell(k);
                                 userInfo.setStartWorkDate(getValue(cell));
-                            }else if (k == 36) {
+                            }else if (k == 37) {
+                                // 个人主页
+                                Cell cell = row.getCell(k);
+                                userInfo.setWebSite(getValue(cell));
+                            }else if (k == 38) {
+                                // 即时通讯
+                                Cell cell = row.getCell(k);
+                                userInfo.setDefineIm(getValue(cell));
+                            }else if (k == 39) {
                                 // 国家
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomeCountry(getValue(cell));
-                            }else if (k == 37) {
+                            }else if (k == 40) {
                                 // 省
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomeRegion(getValue(cell));
-                            }else if (k == 38) {
+                            }else if (k == 41) {
                                 // 城市
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomeLocality(getValue(cell));
-                            }else if (k == 39) {
+                            }else if (k == 42) {
                                 // 家庭地址
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomeStreetAddress(getValue(cell));
-                            }else if (k == 40) {
+                            }else if (k == 43) {
                                 // 家庭邮编
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomePostalCode(getValue(cell));
-                            }else if (k == 41) {
+                            }else if (k == 44) {
                                 // 家庭传真
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomeFax(getValue(cell));
-                            }else if (k == 42) {
+                            }else if (k == 45) {
                                 // 家庭电话
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomePhoneNumber(getValue(cell));
-                            }else if (k == 43) {
+                            }else if (k == 46) {
                                 // 家庭邮箱
                                 Cell cell = row.getCell(k);
                                 userInfo.setHomeEmail(getValue(cell));
-                            }else if (k == 44) {
-                                // 个人主页
-                                Cell cell = row.getCell(k);
-                                userInfo.setWebSite(getValue(cell));
-                            }else if (k == 45) {
-                                // 即时通讯
-                                Cell cell = row.getCell(k);
-                                userInfo.setDefineIm(getValue(cell));
                             }
                         }
                         userInfo.setStatus(1);
@@ -595,7 +599,13 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
                 try {
                     is.close();
                 } catch (IOException e) {
-                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+            if(wb != null) {
+                try {
+                    wb.close();
+                } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
@@ -617,7 +627,7 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
         } else if (cell.getCellType() == CellType.BOOLEAN) {
             return String.valueOf(cell.getBooleanCellValue());
         } else if (cell.getCellType() == CellType.NUMERIC) {
-            cell.setCellType(CellType.STRING);
+            cell.setBlank();
             return String.valueOf(cell.getStringCellValue().trim());
         } else {
             return String.valueOf(cell.getStringCellValue().trim());

+ 12 - 12
maxkey-persistence/src/test/resources/application.properties

@@ -24,7 +24,7 @@ spring.servlet.multipart.max-file-size=4194304
 #server.servlet.encoding.force=true
 #datasource
 spring.datasource.username=root
-spring.datasource.password=root
+spring.datasource.password=maxkey
 spring.datasource.url=jdbc:mysql://localhost/maxkey?autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC
 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
@@ -69,24 +69,24 @@ spring.messages.encoding=UTF-8
 spring.main.banner-mode=log
 spring.main.allow-bean-definition-overriding=true
 
-###########【Kafka集群】###########
+###########\u3010Kafka\u96c6\u7fa4\u3011###########
 spring.kafka.bootstrap-servers=localhost:9092
-###########【初始化生产者配置】###########
-# 重试次数
+###########\u3010\u521d\u59cb\u5316\u751f\u4ea7\u8005\u914d\u7f6e\u3011###########
+# \u91cd\u8bd5\u6b21\u6570
 spring.kafka.producer.retries=0
-# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
+# \u5e94\u7b54\u7ea7\u522b:\u591a\u5c11\u4e2a\u5206\u533a\u526f\u672c\u5907\u4efd\u5b8c\u6210\u65f6\u5411\u751f\u4ea7\u8005\u53d1\u9001ack\u786e\u8ba4(\u53ef\u90090\u30011\u3001all/-1)
 spring.kafka.producer.acks=1
-# 批量大小
+# \u6279\u91cf\u5927\u5c0f
 spring.kafka.producer.batch-size=16384
-# 提交延时
+# \u63d0\u4ea4\u5ef6\u65f6
 spring.kafka.producer.properties.linger.ms=0
-# 当生产端积累的消息达到batch-size或接收到消息linger.ms后,生产者就会将消息提交给kafka
-# linger.ms为0表示每接收到一条消息就提交给kafka,这时候batch-size其实就没用了
+# \u5f53\u751f\u4ea7\u7aef\u79ef\u7d2f\u7684\u6d88\u606f\u8fbe\u5230batch-size\u6216\u63a5\u6536\u5230\u6d88\u606flinger.ms\u540e,\u751f\u4ea7\u8005\u5c31\u4f1a\u5c06\u6d88\u606f\u63d0\u4ea4\u7ed9kafka
+# linger.ms\u4e3a0\u8868\u793a\u6bcf\u63a5\u6536\u5230\u4e00\u6761\u6d88\u606f\u5c31\u63d0\u4ea4\u7ed9kafka,\u8fd9\u65f6\u5019batch-size\u5176\u5b9e\u5c31\u6ca1\u7528\u4e86
 
-# 生产端缓冲区大小
+# \u751f\u4ea7\u7aef\u7f13\u51b2\u533a\u5927\u5c0f
 spring.kafka.producer.buffer-memory = 33554432
-# Kafka提供的序列化和反序列化类
+# Kafka\u63d0\u4f9b\u7684\u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316\u7c7b
 spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
 spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
-# 自定义分区器
+# \u81ea\u5b9a\u4e49\u5206\u533a\u5668
 # spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner

+ 1 - 1
maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedJWTAdapter.java

@@ -69,7 +69,7 @@ public class TokenBasedJWTAdapter extends AbstractAuthorizeAdapter {
 				.claim("user_id", userInfo.getId())
 				.claim("external_id", userInfo.getId())
 				.claim("locale", userInfo.getLocale())
-				.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket())
+				.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket().getTicketId())
 				.claim("kid", jwtSignerService.getDefaultSignerKeyId())
 				.build();
 		

+ 1 - 1
maxkey-protocols/maxkey-protocol-tokenbased/src/main/java/org/maxkey/authz/token/endpoint/adapter/TokenBasedJWTHS256Adapter.java

@@ -69,7 +69,7 @@ public class TokenBasedJWTHS256Adapter extends AbstractAuthorizeAdapter {
 				.claim("email", userInfo.getWorkEmail())
 				.claim("name", userInfo.getUsername())
 				.claim("user_id", userInfo.getId())
-				.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket())
+				.claim(WebConstants.ONLINE_TICKET_NAME, authentication.getOnlineTicket().getTicketId())
 				.claim("external_id", userInfo.getId())
 				.claim("locale", userInfo.getLocale())
 				.claim("kid", "SYMMETRIC-KEY")

+ 16 - 1
maxkey-web-manage/src/main/java/org/maxkey/web/contorller/OrganizationsController.java

@@ -21,13 +21,17 @@ import java.util.HashMap;
 import java.util.List;
 
 import org.apache.mybatis.jpa.persistence.JpaPageResults;
+import org.maxkey.constants.ConstantsOperateMessage;
+import org.maxkey.domain.ExcelImport;
 import org.maxkey.domain.Organizations;
 import org.maxkey.persistence.service.OrganizationsService;
 import org.maxkey.web.WebContext;
 import org.maxkey.web.component.TreeNode;
 import org.maxkey.web.component.TreeNodeList;
 import org.maxkey.web.message.Message;
+import org.maxkey.web.message.MessageScope;
 import org.maxkey.web.message.MessageType;
+import org.maxkey.web.message.OperateType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -195,7 +199,18 @@ public class OrganizationsController {
   public ModelAndView orgUsersList() { return new ModelAndView("orgs/orgUsersList"); }
 
 
-
+  @RequestMapping(value = "/import")
+  public ModelAndView importing(@ModelAttribute("excelImportFile")ExcelImport excelImportFile)  {
+      ModelAndView modelAndView=new ModelAndView("/orgs/orgsImport");
+      
+      if (excelImportFile.getExcelFile() != null && !excelImportFile.getExcelFile().isEmpty() && organizationsService.importing(excelImportFile.getExcelFile())) {
+           new Message(WebContext.getI18nValue(ConstantsOperateMessage.INSERT_SUCCESS), null, MessageType.success, OperateType.add, MessageScope.DB);
+      }else {
+           new Message(WebContext.getI18nValue(ConstantsOperateMessage.INSERT_ERROR), MessageType.error);
+      }
+      
+      return modelAndView;
+  }
 
 
 

+ 0 - 12
maxkey-web-manage/src/main/java/org/maxkey/web/contorller/UserInfoController.java

@@ -272,18 +272,6 @@ public class UserInfoController {
 		}
 	}
 	
-	@ResponseBody
-	@RequestMapping(value="/changeUserinfoStatus")  
-	public Message changeUserinfoStatus( @ModelAttribute("userInfo")UserInfo userInfo) {
-		_logger.debug(userInfo.getId());
-		if(userInfoService.update(userInfo)) {
-			return  new Message(WebContext.getI18nValue(ConstantsOperateMessage.UPDATE_SUCCESS),MessageType.success);
-			
-		} else {
-			return  new Message(WebContext.getI18nValue(ConstantsOperateMessage.UPDATE_ERROR),MessageType.error);
-		}
-	}
-	
     @RequestMapping(value = "/import")
     public ModelAndView importing(@ModelAttribute("excelImportFile")ExcelImport excelImportFile)  {
         ModelAndView modelAndView=new ModelAndView("/userinfo/usersImport");

+ 11 - 0
maxkey-web-manage/src/main/resources/messages/message.properties

@@ -50,6 +50,8 @@ common.text.status.invalid=\u65e0\u6548
 common.text.status.expired=\u8fc7\u671f
 common.text.status.delete=\u5220\u9664
 common.text.description=\u63cf\u8ff0
+common.text.yes=\u662f
+common.text.no=\u5426
 
 main.rpt.newuser=\u5f53\u6708\u65b0\u7528\u6237
 main.rpt.activeuser=\u672c\u6708\u6d3b\u8dc3\u7528\u6237
@@ -447,6 +449,7 @@ button.text.delete.member=\u5220\u9664\u6210\u5458
 button.text.generate=\u751f\u6210
 button.text.view=\u67e5\u770b
 button.text.hidden=\u9690\u85cf
+button.text.import=\u5bfc\u5165
 
 log.loginhistory.id=\u7f16\u53f7
 log.loginhistory.sessionId=\u4f1a\u8bdd
@@ -487,6 +490,14 @@ message.action.update.success=\u66f4\u65b0\u64cd\u4f5c\u6210\u529f
 message.action.update.error=\u66f4\u65b0\u64cd\u4f5c\u5931\u8d25
 message.action.delete.success=\u5220\u9664\u64cd\u4f5c\u6210\u529f
 message.action.delete.error=\u5220\u9664\u64cd\u4f5c\u5931\u8d25
+message.action.import.success=\u6279\u91cf\u5bfc\u5165\u6210\u529f
+message.action.import.error=\u6279\u91cf\u5bfc\u5165\u5931\u8d25
+
+import.title=\u6279\u91cf\u5bfc\u5165\u6570\u636e
+import.file.select=\u9009\u62e9\u5bfc\u5165\u6587\u4ef6
+import.template.download=\u4e0b\u8f7d\u6a21\u677f
+import.update.exist=\u66f4\u65b0\u5b58\u5728\u6570\u636e
+import.tip=\u63d0\u793a\uff1a\u4ec5\u5141\u8bb8\u5bfc\u5165\u201cxls\u201d\u6216\u8005\u201cxlsx\u201d\u683c\u5f0f\u7684\u6587\u4ef6 
 
 navs.system=\u7cfb\u7edf
 navs.home=\u9996\u9875

+ 13 - 1
maxkey-web-manage/src/main/resources/messages/message_en.properties

@@ -50,6 +50,8 @@ common.text.status.invalid=invalid
 common.text.status.expired=expired
 common.text.status.delete=delete
 common.text.description=description
+common.text.yes=yes
+common.text.no=no
 
 
 main.rpt.newuser=New Users/Month
@@ -441,11 +443,12 @@ button.text.search=Search
 button.text.expandsearch=Expand
 button.text.collapsesearch=Collapse
 button.text.cancel=Cancel
-button.text.add.member=Ddd member
+button.text.add.member=Add member
 button.text.delete.member=Delete member
 button.text.generate=Generate
 button.text.view=View
 button.text.hidden=Hidden
+button.text.import=Import
 
 
 log.loginhistory.id=id
@@ -487,6 +490,15 @@ message.action.update.success=Update Success
 message.action.update.error=Update Error
 message.action.delete.success=Delete Success
 message.action.delete.error=Delete Error
+message.action.import.success=Import Success
+message.action.import.error=Import Error
+
+import.title=Batch Import Data
+import.file.select=Import File
+import.template.download=Download Template
+import.update.exist=Update Exist Data
+import.tip=Tip\uff1aolny Import \u201cxls\u201d or \u201cxlsx\u201d file\u3002
+
 
 navs.system=System
 navs.home=Home

+ 11 - 0
maxkey-web-manage/src/main/resources/messages/message_zh_CN.properties

@@ -50,6 +50,8 @@ common.text.status.invalid=\u65e0\u6548
 common.text.status.expired=\u8fc7\u671f
 common.text.status.delete=\u5220\u9664
 common.text.description=\u63cf\u8ff0
+common.text.yes=\u662f
+common.text.no=\u5426
 
 main.rpt.newuser=\u5f53\u6708\u65b0\u7528\u6237
 main.rpt.activeuser=\u672c\u6708\u6d3b\u8dc3\u7528\u6237
@@ -447,6 +449,7 @@ button.text.delete.member=\u5220\u9664\u6210\u5458
 button.text.generate=\u751f\u6210
 button.text.view=\u67e5\u770b
 button.text.hidden=\u9690\u85cf
+button.text.import=\u5bfc\u5165
 
 log.loginhistory.id=\u7f16\u53f7
 log.loginhistory.sessionId=\u4f1a\u8bdd
@@ -487,6 +490,14 @@ message.action.update.success=\u66f4\u65b0\u64cd\u4f5c\u6210\u529f
 message.action.update.error=\u66f4\u65b0\u64cd\u4f5c\u5931\u8d25
 message.action.delete.success=\u5220\u9664\u64cd\u4f5c\u6210\u529f
 message.action.delete.error=\u5220\u9664\u64cd\u4f5c\u5931\u8d25
+message.action.import.success=\u6279\u91cf\u5bfc\u5165\u6210\u529f
+message.action.import.error=\u6279\u91cf\u5bfc\u5165\u5931\u8d25
+
+import.title=\u6279\u91cf\u5bfc\u5165\u6570\u636e
+import.file.select=\u9009\u62e9\u5bfc\u5165\u6587\u4ef6
+import.template.download=\u4e0b\u8f7d\u6a21\u677f
+import.update.exist=\u66f4\u65b0\u5b58\u5728\u6570\u636e
+import.tip=\u63d0\u793a\uff1a\u4ec5\u5141\u8bb8\u5bfc\u5165\u201cxls\u201d\u6216\u8005\u201cxlsx\u201d\u683c\u5f0f\u7684\u6587\u4ef6 
 
 navs.system=\u7cfb\u7edf
 navs.home=\u9996\u9875

BIN
maxkey-web-manage/src/main/resources/static/template/excel/Orgs_Import_Template.xlsx


BIN
maxkey-web-manage/src/main/resources/static/template/excel/Users_Import_Template.xlsx


+ 67 - 0
maxkey-web-manage/src/main/resources/templates/views/orgs/orgsImport.ftl

@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<#include  "../layout/header.ftl"/>
+	<#include  "../layout/common.cssjs.ftl"/>
+	<style   type="text/css">
+	  .table th, .table td {
+	    padding: .2rem;
+	    vertical-align: middle;
+	  }
+	</style>
+
+	<script type="text/javascript">
+	<!--
+	$(function(){	
+					
+	});
+	//-->
+	</script>
+</head>
+<body>
+
+<form 
+	enctype="multipart/form-data" 
+	method="post" type="label" autoclose="true"  action="<@base/>/orgs/import"  
+	class="needs-validation" novalidate> 
+
+	  <table   class="table table-bordered" >
+			<tbody>
+			<tr>
+				<th nowrap="nowrap"><@locale code="import.file.select" /></th>
+				<td>
+					<input class="form-control"  type="file" id="excelFile" name="excelFile"  />
+				</td>
+			</tr>
+			<tr>
+				<td  colspan="2">
+					<a href="<@base/>/static/template/excel/Users_Import_Template.xlsx" ><@locale code="import.template.download" /></>
+				</td>
+			</tr>
+			<tr>
+				<th><@locale code="import.update.exist" /> </th>
+				<td>
+					<select name="updateExist"  id="updateExist" class="form-control" >
+						<option value="no" selected > <@locale code="common.text.no" /></option>
+						<option value="yes"> <@locale code="common.text.yes" /> </option>
+					</select>
+				</td>
+			</tr>
+			<tr>
+				<th colspan="2" style="color: red;">
+					<@locale code="import.tip" /> 
+				</th>
+			</tr>
+			<tr>
+				<td colspan="2"  class="center">
+					<input id="_method" type="hidden" name="_method"  value="post"/>
+		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="submit"    id="submitBtn" value="<@locale code="button.text.import" />"/>
+		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="button"    id="closeBtn" value="<@locale code="common.alert.closeText" />"/>
+		    		
+				</td>
+			</tr>
+		</tbody>
+	  </table>
+</form>
+</body>
+</html>

+ 5 - 1
maxkey-web-manage/src/main/resources/templates/views/orgs/orgsList.ftl

@@ -183,7 +183,11 @@ $(function () {
 					 	</form>
 				</td>
 				<td colspan="2"> 
-					 <div id="tool_box_right">	    
+					 <div id="tool_box_right">	
+					 	<input class="button btn btn-success mr-3 window" id="usersImportBtn" type="button" 
+						 		value="<@locale code="button.text.import"/>" 
+						 		    wurl="<@base/>/orgs/import" wwidth="400px" wheight="250px" />
+						 		        
 						 <input class="button btn btn-success mr-3" id="addBtn" type="button" value="<@locale code="button.text.add"/>" 
 						 		    wurl="<@base/>/orgs/forwardAdd"
 						 		    wwidth="620"

+ 0 - 64
maxkey-web-manage/src/main/resources/templates/views/userinfo/changeUserinfoStatus.ftl

@@ -1,64 +0,0 @@
-<!DOCTYPE HTML>
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<#include  "../layout/header.ftl"/>
-	<#include  "../layout/common.cssjs.ftl"/>
-	<style   type="text/css">
-	  .table th, .table td {
-	    padding: .2rem;
-	    vertical-align: middle;
-	  }
-	</style>
-
-	<script type="text/javascript">
-	<!--
-	$(function(){	
-					
-	});
-	//-->
-	</script>
-</head>
-<body>
-
-<form id="actionForm"  method="post" type="label" autoclose="true"  action="<@base/>/userinfo/changeUserinfoStatus"  class="needs-validation" novalidate> 
-
-	  <table   class="table table-bordered" >
-			<tbody>
-			<tr>
-				<th><@locale code="userinfo.displayName" /> :</th>
-				<td>
-					<input readonly type="hidden" id="id" name="id" class="required" title="" value="${model.id}"/>
-					<input readonly type="text" id="displayName" name="displayName"  class="form-control"  title="" value="${model.displayName}"/>
-					
-				</td>
-			</tr>
-			<tr>
-				<th><@locale code="userinfo.username" /> :</th>
-				<td>
-					<input readonly type="text" id="username" name="username"  class="form-control"  title="" value="${model.username}"/>
-					
-				</td>
-			</tr>
-			<tr>
-				<th><@locale code="userinfo.status" />:</th>
-				<td>
-				<select name="status"  id="status" class="form-control" >
-						<option value="1"   <#if 1==model.status>selected</#if>><@locale code="userinfo.status.active" /></option>
-						<option value="2"   <#if 2==model.status>selected</#if>><@locale code="userinfo.status.withdrawn" /></option>
-						<option value="3"   <#if 3==model.status>selected</#if>><@locale code="userinfo.status.inactive" /></option>
-						<option value="4"   <#if 4==model.status>selected</#if>><@locale code="userinfo.status.retiree" /></option>
-				</select>
-				</td>
-			</tr>
-			<tr>
-				<td colspan="2"  class="center">
-					<input id="_method" type="hidden" name="_method"  value="post"/>
-		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="submit"    id="submitBtn" value="<@locale code="button.text.save" />"/>
-		    		
-				</td>
-			</tr>
-		</tbody>
-	  </table>
-</form>
-</body>
-</html>

+ 7 - 2
maxkey-web-manage/src/main/resources/templates/views/userinfo/userUpdate.ftl

@@ -50,9 +50,14 @@
 			<input type="hidden" id="id" name="id" value="${model.id!""}"/>
 			<input  class="form-control"  type="text" id="username" name="username"  title="" value="${model.username!""}"/>
 		</td>
-		<td style="width:15%;"><@locale code="login.text.password" />:</td>
+		<td style="width:15%;"><@locale code="userinfo.status" />:</td>
 		<td style="width:35%;">
-			<input  class="form-control"  type="password" id="password" name="password"  title="" value=""/>
+			<select name="status"  id="status" class="form-control" >
+						<option value="1"   <#if 1==model.status>selected</#if>><@locale code="userinfo.status.active" /></option>
+						<option value="2"   <#if 2==model.status>selected</#if>><@locale code="userinfo.status.withdrawn" /></option>
+						<option value="3"   <#if 3==model.status>selected</#if>><@locale code="userinfo.status.inactive" /></option>
+						<option value="4"   <#if 4==model.status>selected</#if>><@locale code="userinfo.status.retiree" /></option>
+				</select>
 		</td>
 	</tr>
 	<tr>

+ 22 - 3
maxkey-web-manage/src/main/resources/templates/views/userinfo/usersImport.ftl

@@ -28,16 +28,35 @@
 	  <table   class="table table-bordered" >
 			<tbody>
 			<tr>
-				<th><@locale code="userinfo.displayName" /> :</th>
+				<th nowrap="nowrap"><@locale code="import.file.select" /></th>
 				<td>
 					<input class="form-control"  type="file" id="excelFile" name="excelFile"  />
 				</td>
 			</tr>
-			
+			<tr>
+				<td  colspan="2">
+					<a href="<@base/>/static/template/excel/Users_Import_Template.xlsx" ><@locale code="import.template.download" /></>
+				</td>
+			</tr>
+			<tr>
+				<th><@locale code="import.update.exist" /> </th>
+				<td>
+					<select name="updateExist"  id="updateExist" class="form-control" >
+						<option value="no" selected > <@locale code="common.text.no" /></option>
+						<option value="yes"> <@locale code="common.text.yes" /> </option>
+					</select>
+				</td>
+			</tr>
+			<tr>
+				<th colspan="2" style="color: red;">
+					<@locale code="import.tip" /> 
+				</th>
+			</tr>
 			<tr>
 				<td colspan="2"  class="center">
 					<input id="_method" type="hidden" name="_method"  value="post"/>
-		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="submit"    id="submitBtn" value="<@locale code="button.text.save" />"/>
+		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="submit"    id="submitBtn" value="<@locale code="button.text.import" />"/>
+		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="button"    id="closeBtn" value="<@locale code="common.alert.closeText" />"/>
 		    		
 				</td>
 			</tr>

+ 3 - 3
maxkey-web-manage/src/main/resources/templates/views/userinfo/usersList.ftl

@@ -201,12 +201,12 @@ $(function () {
 				<td colspan="2"> 
 					 <div id="tool_box_right">
 					 	<input class="button btn btn-warning mr-3" id="changepwdBtn" type="button" value="<@locale code="login.password.changepassword"/>" />
-						<input class="button btn btn-warning mr-3 window" id="changepwdBtnHidden" type="button"
+						<input class="button btn btn-warning mr-3 window" id="changepwdBtnHidden" type="hidden"
 						 value="<@locale code="login.password.changepassword"/>" 
 						 		    wurl="<@base/>/userinfo/forwardChangePassword" wwidth="600px" wheight="250px" />
 						 		    
-						 <input class="button btn btn-warning mr-3 window" id="usersImportBtn" type="button" 
-						 		value="<@locale code="Import"/>" 
+						 <input class="button btn btn-success mr-3 window" id="usersImportBtn" type="button" 
+						 		value="<@locale code="button.text.import"/>" 
 						 		    wurl="<@base/>/userinfo/import" wwidth="400px" wheight="250px" />