Browse Source

添加后台新增用户的接口

huxz 7 years ago
parent
commit
6e705c6251

+ 2 - 2
gradle/persist-publish.gradle

@@ -20,7 +20,7 @@ task persistJar(type: Jar) {
     baseName "sso-persist"
     from sourceSets.main.output
     exclude "spring", "config"
-    include "**/entity/**", "**/dao/**", "**/core/**"
+    include "**/entity/**", "**/dao/**", "**/core/**", "**/util/**"
 }
 
 task persistSourcesJar(type: Jar) {
@@ -28,7 +28,7 @@ task persistSourcesJar(type: Jar) {
     classifier 'sources'
     from sourceSets.main.allSource
     exclude "spring", "config"
-    include "**/entity/**", "**/dao/**"
+    include "**/entity/**", "**/dao/**", "**/core/**", "**/util/**"
 }
 
 // Create artifact for other project import

+ 18 - 8
sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/UserManageController.java

@@ -1,13 +1,15 @@
 package com.uas.sso.sso.backend.api;
 
 import com.uas.sso.entity.User;
+import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
-import com.uas.sso.sso.backend.service.UserService;
+import com.uas.sso.sso.backend.service.UserBackendService;
 import com.uas.sso.sso.backend.support.ResultBean;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Pageable;
 import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -23,11 +25,11 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping(path = "/api/user")
 public class UserManageController {
 
-    private final UserService userService;
+    private final UserBackendService userBackendService;
 
     @Autowired
-    public UserManageController(UserService userService) {
-        this.userService = userService;
+    public UserManageController(UserBackendService userBackendService) {
+        this.userBackendService = userBackendService;
     }
 
     @RequestMapping(method = RequestMethod.GET, path = "//showUserByPagination",
@@ -38,14 +40,15 @@ public class UserManageController {
             @RequestParam(required = false) String key,
             @RequestParam(required = false) String keyword) {
         // Controller中的Pageable类型参数默认根据查询参数 page 和 size 注入并实例化
-        return new ResultBean<>(userService.showUserByPagination(page, fromApp, mobileValidCode, key, keyword));
+        return new ResultBean<>(
+                userBackendService.showUserByPagination(page, fromApp, mobileValidCode, key, keyword));
     }
 
     @RequestMapping(method = RequestMethod.GET, path = "//showEnUserByPagination",
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
     public ResultBean<org.springframework.data.domain.Page<User>> showEnUserByPagination(Pageable page, Long spaceUU) {
 
-        return new ResultBean<>(userService.showEnUserByPagination(page, spaceUU));
+        return new ResultBean<>(userBackendService.showEnUserByPagination(page, spaceUU));
     }
 
     @RequestMapping(method = RequestMethod.GET, path = "//searchUserByKeyword",
@@ -53,13 +56,20 @@ public class UserManageController {
     public ResultBean<List<User>> searchUserByKeyword(@RequestParam("spaceUU") Long spaceUu,
             String key, String keyword) {
 
-        return new ResultBean<>(userService.searchUserByKeyword(spaceUu, key, keyword));
+        return new ResultBean<>(userBackendService.searchUserByKeyword(spaceUu, key, keyword));
     }
 
     @RequestMapping(method = RequestMethod.PUT, path = "//modifyUserInfo",
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
     public ResultBean<Boolean> modifyUserInfo(@RequestBody UpdateUserInfo userInfo) {
 
-        return new ResultBean<>(userService.modifyUserInfo(userInfo));
+        return new ResultBean<>(userBackendService.modifyUserInfo(userInfo));
+    }
+
+    @RequestMapping(method = RequestMethod.POST, path = "//addNewUser",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public ResultBean<User> addNewUser(@RequestBody @Validated AddNewUserInfo userInfo) {
+
+        return new ResultBean<>(userBackendService.addNewUser(userInfo));
     }
 }

+ 80 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/dto/AddNewUserInfo.java

@@ -0,0 +1,80 @@
+package com.uas.sso.sso.backend.dto;
+
+import com.uas.sso.entity.User;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 新增用户信息DTO.
+ *
+ * @author huxz
+ */
+public class AddNewUserInfo {
+
+    /**
+     * 会员名
+     */
+    @NotNull(message = "个人名称不能为空")
+    private String vipName;
+
+    /**
+     * 手机号
+     */
+    @NotNull(message = "用户手机号不能为空")
+    private String mobile;
+
+    /**
+     * 用户邮箱
+     */
+    private String email;
+
+    /**
+     * 用户密码
+     */
+    @NotNull(message = "用户密码不能为空")
+    private String password;
+
+    public String getVipName() {
+        return vipName;
+    }
+
+    public void setVipName(String vipName) {
+        this.vipName = vipName;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = mobile;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public User fillUserInfo(User user) {
+        if (user == null) {
+            user = new User();
+        }
+
+        user.setVipName(this.vipName);
+        user.setMobile(this.mobile);
+        user.setEmail(this.email);
+        user.setPassword(this.password);
+        return user;
+    }
+}

+ 10 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserService.java → sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserBackendService.java

@@ -1,6 +1,7 @@
 package com.uas.sso.sso.backend.service;
 
 import com.uas.sso.entity.User;
+import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
 import java.util.List;
 import javax.validation.constraints.NotNull;
@@ -12,7 +13,7 @@ import org.springframework.data.domain.Pageable;
  *
  * @author huxz
  */
-public interface UserService {
+public interface UserBackendService {
 
     /**
      * 分页获取用户信息.
@@ -53,5 +54,13 @@ public interface UserService {
      * @return  操作状态
      */
     Boolean modifyUserInfo(UpdateUserInfo userInfo);
+
+    /**
+     * 后台新增用户。
+     *
+     * @param userInfo  用户信息
+     * @return  新创建的用户
+     */
+    User addNewUser(AddNewUserInfo userInfo);
 }
 

+ 49 - 4
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserServiceImpl.java → sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserBackendServiceImpl.java

@@ -1,13 +1,20 @@
 package com.uas.sso.sso.backend.service.impl;
 
 import com.uas.sso.core.Const;
+import com.uas.sso.core.Status;
+import com.uas.sso.dao.AppDao;
 import com.uas.sso.dao.UserDao;
+import com.uas.sso.entity.App;
 import com.uas.sso.entity.User;
+import com.uas.sso.entity.UserRecord;
 import com.uas.sso.entity.Userspace;
 import com.uas.sso.sso.backend.AuthenticationUtils;
+import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
 import com.uas.sso.sso.backend.exceptions.ValidationFailedException;
-import com.uas.sso.sso.backend.service.UserService;
+import com.uas.sso.sso.backend.service.UserBackendService;
+import com.uas.sso.util.InfoAsyncUtils;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -24,17 +31,20 @@ import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
 /**
- * An implementations of {@code UserService}.
+ * An implementations of {@code UserBackendService}.
  *
  * @author huxz
  */
 @Service
-public class UserServiceImpl implements UserService {
+public class UserBackendServiceImpl implements UserBackendService {
+
+    private final AppDao appDao;
 
     private final UserDao userDao;
 
     @Autowired
-    public UserServiceImpl(UserDao userDao) {
+    public UserBackendServiceImpl(AppDao appDao, UserDao userDao) {
+        this.appDao = appDao;
         this.userDao = userDao;
     }
 
@@ -162,4 +172,39 @@ public class UserServiceImpl implements UserService {
         return true;
     }
 
+    @Override
+    public User addNewUser(AddNewUserInfo userInfo) {
+        emailHasRegistered(userInfo.getMobile());
+
+        User user = userInfo.fillUserInfo(new User());
+        if (StringUtils.isEmpty(user.getMobileArea())) {
+            user.setMobileArea(Const.CONTINENT);
+        }
+
+        user.setRegisterDate(new Timestamp(System.currentTimeMillis()));
+        Long uu = userDao.findMaxUU();
+        user.setUserUU(uu == null ? 10000 : (uu + 1));
+        user.setSalt(String.valueOf(user.getUserUU()));
+        user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
+        user.setEmailValidCode((short) Status.NOT_APPLYING.getCode());
+        user.setIdentityValidCode((short) Status.NOT_APPLYING.getCode());
+        user.setPassword(InfoAsyncUtils.encryptePassword(Const.ENCRY_FORMAT, user.getPassword(), user.getSalt()));
+        user.setUserRecord(new UserRecord());
+        user.setFromApp("sso");
+        user  = userDao.save(user);
+
+        List<App> appList = appDao.findAll();
+        List<String> urlsFromApps = InfoAsyncUtils.getUserBackUrlsFromApps(appList);
+
+        InfoAsyncUtils.syncUserInfo(urlsFromApps, user.toView(), "管理新增用户");
+        return user;
+    }
+
+    private void emailHasRegistered(String mobile) {
+        User user = userDao.findByMobile(mobile);
+        if (user != null) {
+            throw new ValidationFailedException("手机号已经注册");
+        }
+    }
+
 }

+ 1 - 1
sso-server/src/main/java/com/uas/sso/core/Const.java

@@ -26,7 +26,7 @@ public class Const {
     /**
      * 用户uu号正则
      */
-    public static String REGEXP_USERUU_NUMBER = "^[0-9]{10}$";
+    public static String REGEXP_USERUU_NUMBER = "^[0-9]{5, 10}$";
 
     /**
      * 中国大陆

+ 120 - 0
sso-server/src/main/java/com/uas/sso/util/InfoAsyncUtils.java

@@ -0,0 +1,120 @@
+package com.uas.sso.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.uas.sso.common.encrypt.MD5;
+import com.uas.sso.common.util.HttpUtil;
+import com.uas.sso.core.Const;
+import com.uas.sso.core.ICallable;
+import com.uas.sso.entity.App;
+import com.uas.sso.entity.UserView;
+import com.uas.sso.exception.AccountException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.springframework.util.Assert;
+
+/**
+ * Utils class is designed to sync user information with other apps
+ * and handle user information.
+ *
+ * @author huxz
+ */
+public class InfoAsyncUtils {
+
+    public static final Logger logger = Logger.getLogger(InfoAsyncUtils.class);
+
+    /**
+     * 生成加密密码
+     *
+     * @param format 密码加密格式
+     * @param password 明文密码
+     * @param salt 盐值
+     * @return 密文密码
+     */
+    public static String encryptePassword(String format, String password, String salt) {
+        // 验证加密格式
+        if (StringUtils.isEmpty(format)) {
+            return password;
+        }
+
+        // 验证密码信息,长度超过32认为是已加密过的密文
+        int minPwdLen = 4;
+        int maxPwdLen = 32;
+        if (StringUtils.isEmpty(password) || password.length() < minPwdLen
+                || password.length() >= maxPwdLen) {
+            throw new AccountException("invalid password");
+        }
+
+        // 加密格式: "$password{$salt}"
+        String cipher = format.replace(Const.ENCRY_PARAM_PASSWORD, password);
+        cipher = cipher.replace(Const.ENCRY_PARAM_SALT, salt == null ? "" : salt);
+        return MD5.toMD5(cipher);
+    }
+
+    /**
+     * 获取所有应用的有效用户信息更新接口.
+     *
+     * @param appList 应用列表
+     * @return 用户更新接口链接列表
+     */
+    public static List<String> getUserBackUrlsFromApps(List<App> appList) {
+        if (CollectionUtils.isEmpty(appList)) {
+            return Collections.emptyList();
+        }
+
+        List<String> backUserUrls = new ArrayList<>();
+        for (App app : appList) {
+            if (app != null && StringUtils.isEmpty(app.getUserControl())
+                    && !StringUtils.isEmpty(app.getBackUserUrl())) {
+                backUserUrls.add(app.getUid() + ":" + app.getBackUserUrl());
+            }
+        }
+        return backUserUrls;
+    }
+
+    /**
+     * 同步用户信息到各个应用
+     *
+     * @param backUserUrls  同步接口URL
+     * @param userView  用户信息视图
+     * @param msg   同步信息描述,用户区分同步类型
+     */
+    public static void syncUserInfo(final List<String> backUserUrls, final UserView userView,
+            final String msg) {
+        if (CollectionUtils.isEmpty(backUserUrls)) {
+            logger.warn("用户更新接口URL列表为空列表");
+            return;
+        }
+        Assert.notNull(userView, "用户信息不能为空");
+        Assert.isTrue(!org.springframework.util.StringUtils.isEmpty(msg), "同步信息描述不能为空");
+
+        ExecuteUtils.execute(new ICallable<Void, String>() {
+
+            @Override
+            public Void call(String url) {
+                String[] split = url.split(":");
+                String appId = split[0];
+                try {
+                    url = split[1];
+                    JSONObject formData = JSON.parseObject(JSON.toJSONString(userView));
+
+                    HttpUtil.ResponseWrap res = HttpUtil.doPost(url, formData, 30000);
+                    if (!res.isSuccess()) {
+                        logger.error(String.format("%s:同步用户信息失败, %s, %s, %s", msg, appId,
+                                JSON.toJSONString(userView), res.getContent()));
+                    } else {
+                        logger.info(String.format("%s:同步用户信息成功, %s, %s", msg, appId,
+                                JSON.toJSONString(userView)));
+                    }
+                } catch (Exception e) {
+                    logger.error(String.format("%s:同步用户信息失败, %s, %s, %s", msg, appId,
+                            JSON.toJSONString(userView), e.getMessage()));
+                }
+                return null;
+            }
+        }, backUserUrls);
+    }
+
+}