mirror of
https://github.com/PlayEdu/PlayEdu
synced 2025-07-28 21:39:32 +08:00
Compare commits
4 Commits
ff9e212366
...
afc82856f6
Author | SHA1 | Date | |
---|---|---|---|
|
afc82856f6 | ||
|
e215fbb59c | ||
|
1e92f19923 | ||
|
8d03678e71 |
34
playedu-api/src/main/java/xyz/playedu/api/bus/UserBus.java
Normal file
34
playedu-api/src/main/java/xyz/playedu/api/bus/UserBus.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.bus;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import xyz.playedu.common.constant.ConfigConstant;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserBus {
|
||||||
|
|
||||||
|
public String getUserDefaultAvatar(Map<String, String> configData) {
|
||||||
|
String memberDefaultAvatar = configData.get(ConfigConstant.MEMBER_DEFAULT_AVATAR);
|
||||||
|
if (memberDefaultAvatar == null || memberDefaultAvatar.trim().isEmpty()) {
|
||||||
|
return configData.get(ConfigConstant.SYSTEM_API_URL) + "/images/default_avatar.png";
|
||||||
|
}
|
||||||
|
return memberDefaultAvatar;
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import xyz.playedu.api.bus.UserBus;
|
||||||
import xyz.playedu.common.annotation.Log;
|
import xyz.playedu.common.annotation.Log;
|
||||||
import xyz.playedu.common.constant.BusinessTypeConstant;
|
import xyz.playedu.common.constant.BusinessTypeConstant;
|
||||||
import xyz.playedu.common.constant.ConfigConstant;
|
import xyz.playedu.common.constant.ConfigConstant;
|
||||||
@ -45,6 +46,8 @@ public class SystemController {
|
|||||||
|
|
||||||
@Autowired private CategoryService categoryService;
|
@Autowired private CategoryService categoryService;
|
||||||
|
|
||||||
|
@Autowired private UserBus userBus;
|
||||||
|
|
||||||
@GetMapping("/config")
|
@GetMapping("/config")
|
||||||
@Log(title = "其它-系统配置", businessType = BusinessTypeConstant.GET)
|
@Log(title = "其它-系统配置", businessType = BusinessTypeConstant.GET)
|
||||||
public JsonResponse config() {
|
public JsonResponse config() {
|
||||||
@ -68,12 +71,7 @@ public class SystemController {
|
|||||||
data.put(ConfigConstant.SYSTEM_H5_URL, configData.get(ConfigConstant.SYSTEM_H5_URL));
|
data.put(ConfigConstant.SYSTEM_H5_URL, configData.get(ConfigConstant.SYSTEM_H5_URL));
|
||||||
|
|
||||||
// 学员的默认头像
|
// 学员的默认头像
|
||||||
String memberDefaultAvatar = configData.get(ConfigConstant.MEMBER_DEFAULT_AVATAR);
|
data.put(ConfigConstant.MEMBER_DEFAULT_AVATAR, userBus.getUserDefaultAvatar(configData));
|
||||||
if (memberDefaultAvatar == null || memberDefaultAvatar.trim().isEmpty()) {
|
|
||||||
data.put(ConfigConstant.MEMBER_DEFAULT_AVATAR, apiUrl + "/images/default_avatar.png");
|
|
||||||
} else {
|
|
||||||
data.put(ConfigConstant.MEMBER_DEFAULT_AVATAR, memberDefaultAvatar);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 内置的三个线上课封面
|
// 内置的三个线上课封面
|
||||||
List<String> defaultCourseThumbs = new ArrayList<>();
|
List<String> defaultCourseThumbs = new ArrayList<>();
|
||||||
|
@ -28,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import xyz.playedu.api.bus.UserBus;
|
||||||
import xyz.playedu.api.event.UserCourseHourRecordDestroyEvent;
|
import xyz.playedu.api.event.UserCourseHourRecordDestroyEvent;
|
||||||
import xyz.playedu.api.event.UserCourseRecordDestroyEvent;
|
import xyz.playedu.api.event.UserCourseRecordDestroyEvent;
|
||||||
import xyz.playedu.api.event.UserDestroyEvent;
|
import xyz.playedu.api.event.UserDestroyEvent;
|
||||||
@ -37,7 +38,6 @@ import xyz.playedu.common.annotation.BackendPermission;
|
|||||||
import xyz.playedu.common.annotation.Log;
|
import xyz.playedu.common.annotation.Log;
|
||||||
import xyz.playedu.common.constant.BPermissionConstant;
|
import xyz.playedu.common.constant.BPermissionConstant;
|
||||||
import xyz.playedu.common.constant.BusinessTypeConstant;
|
import xyz.playedu.common.constant.BusinessTypeConstant;
|
||||||
import xyz.playedu.common.constant.ConfigConstant;
|
|
||||||
import xyz.playedu.common.constant.SystemConstant;
|
import xyz.playedu.common.constant.SystemConstant;
|
||||||
import xyz.playedu.common.context.BCtx;
|
import xyz.playedu.common.context.BCtx;
|
||||||
import xyz.playedu.common.domain.*;
|
import xyz.playedu.common.domain.*;
|
||||||
@ -232,7 +232,7 @@ public class UserController {
|
|||||||
@PostMapping("/store-batch")
|
@PostMapping("/store-batch")
|
||||||
@Transactional
|
@Transactional
|
||||||
@Log(title = "学员-批量导入", businessType = BusinessTypeConstant.INSERT)
|
@Log(title = "学员-批量导入", businessType = BusinessTypeConstant.INSERT)
|
||||||
public JsonResponse batchStore(@RequestBody @Validated UserImportRequest req) {
|
public JsonResponse batchStore(@RequestBody @Validated UserImportRequest req, UserBus userBus) {
|
||||||
List<UserImportRequest.UserItem> users = req.getUsers();
|
List<UserImportRequest.UserItem> users = req.getUsers();
|
||||||
if (users.isEmpty()) {
|
if (users.isEmpty()) {
|
||||||
return JsonResponse.error("数据为空");
|
return JsonResponse.error("数据为空");
|
||||||
@ -245,7 +245,7 @@ public class UserController {
|
|||||||
Integer startLine = req.getStartLine();
|
Integer startLine = req.getStartLine();
|
||||||
|
|
||||||
// 默认的学员头像
|
// 默认的学员头像
|
||||||
String defaultAvatar = BCtx.getConfig().get(ConfigConstant.MEMBER_DEFAULT_AVATAR);
|
String defaultAvatar = userBus.getUserDefaultAvatar(BCtx.getConfig());
|
||||||
|
|
||||||
List<String[]> errorLines = new ArrayList<>();
|
List<String[]> errorLines = new ArrayList<>();
|
||||||
errorLines.add(new String[] {"错误行", "错误信息"}); // 错误表-表头
|
errorLines.add(new String[] {"错误行", "错误信息"}); // 错误表-表头
|
||||||
|
@ -33,6 +33,7 @@ import xyz.playedu.common.util.ldap.LdapTransformDepartment;
|
|||||||
import xyz.playedu.common.util.ldap.LdapTransformUser;
|
import xyz.playedu.common.util.ldap.LdapTransformUser;
|
||||||
import xyz.playedu.common.util.ldap.LdapUtil;
|
import xyz.playedu.common.util.ldap.LdapUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -162,7 +163,7 @@ public class LDAPBus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void userSync() throws NamingException {
|
public void userSync() throws NamingException, IOException {
|
||||||
LdapConfig ldapConfig = appConfigService.ldapConfig();
|
LdapConfig ldapConfig = appConfigService.ldapConfig();
|
||||||
|
|
||||||
List<LdapTransformUser> userList =
|
List<LdapTransformUser> userList =
|
||||||
@ -179,6 +180,9 @@ public class LDAPBus {
|
|||||||
String defaultAvatar = appConfigService.defaultAvatar();
|
String defaultAvatar = appConfigService.defaultAvatar();
|
||||||
|
|
||||||
for (LdapTransformUser ldapTransformUser : userList) {
|
for (LdapTransformUser ldapTransformUser : userList) {
|
||||||
|
if (ldapTransformUser.isBan()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
singleUserSync(ldapTransformUser, defaultAvatar);
|
singleUserSync(ldapTransformUser, defaultAvatar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,5 @@ public class BPermissionConstant {
|
|||||||
|
|
||||||
public static final String DATA_USER_NAME = "data-user-name";
|
public static final String DATA_USER_NAME = "data-user-name";
|
||||||
public static final String DATA_USER_EMAIL = "data-user-email";
|
public static final String DATA_USER_EMAIL = "data-user-email";
|
||||||
public static final String DATA_USER_ID_CARD = "data-user-id-card";
|
|
||||||
public static final String DATA_ADMIN_EMAIL = "data-admin-email";
|
public static final String DATA_ADMIN_EMAIL = "data-admin-email";
|
||||||
}
|
}
|
||||||
|
@ -121,14 +121,6 @@ public class User implements Serializable {
|
|||||||
getEmail());
|
getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonGetter("id_card")
|
|
||||||
public String transformIdCard() {
|
|
||||||
return BackendBus.valueHidden(
|
|
||||||
BPermissionConstant.DATA_USER_ID_CARD,
|
|
||||||
BackendConstant.PRIVACY_FIELD_TYPE_ID_CARD,
|
|
||||||
getIdCard());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object that) {
|
public boolean equals(Object that) {
|
||||||
if (this == that) {
|
if (this == that) {
|
||||||
|
@ -32,4 +32,6 @@ public class LdapTransformUser {
|
|||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
private String uid;
|
private String uid;
|
||||||
|
|
||||||
|
private boolean ban;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import xyz.playedu.common.exception.ServiceException;
|
import xyz.playedu.common.exception.ServiceException;
|
||||||
import xyz.playedu.common.util.StringUtil;
|
import xyz.playedu.common.util.StringUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
@ -29,8 +30,7 @@ import javax.naming.directory.Attribute;
|
|||||||
import javax.naming.directory.Attributes;
|
import javax.naming.directory.Attributes;
|
||||||
import javax.naming.directory.SearchControls;
|
import javax.naming.directory.SearchControls;
|
||||||
import javax.naming.directory.SearchResult;
|
import javax.naming.directory.SearchResult;
|
||||||
import javax.naming.ldap.InitialLdapContext;
|
import javax.naming.ldap.*;
|
||||||
import javax.naming.ldap.LdapContext;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LdapUtil {
|
public class LdapUtil {
|
||||||
@ -55,12 +55,21 @@ public class LdapUtil {
|
|||||||
"sAMAccountName",
|
"sAMAccountName",
|
||||||
"displayName",
|
"displayName",
|
||||||
"uSNCreated", // AD域的唯一属性
|
"uSNCreated", // AD域的唯一属性
|
||||||
|
"userAccountControl",
|
||||||
|
|
||||||
// 公用属性
|
// 公用属性
|
||||||
"mail",
|
"mail",
|
||||||
};
|
};
|
||||||
private static final String[] OU_RETURN_ATTRS = new String[] {"ou", "usncreated"};
|
private static final String[] OU_RETURN_ATTRS = new String[] {"ou", "usncreated"};
|
||||||
|
|
||||||
|
// 514 - 禁用账户
|
||||||
|
// 546 - 禁用账户 不需密码
|
||||||
|
// 66050 - 禁用账户 密码未过期
|
||||||
|
// 66080 - 禁用账户 密码未过期且不需密码
|
||||||
|
// 66082 - 禁用账户 密码未过期且不需密码
|
||||||
|
private static final String[] DISABLE_USER_ACCOUNT_CONTROL =
|
||||||
|
new String[] {"514", "546", "66050", "66080", "66082"};
|
||||||
|
|
||||||
public static LdapContext initContext(String url, String adminUser, String adminPass)
|
public static LdapContext initContext(String url, String adminUser, String adminPass)
|
||||||
throws NamingException {
|
throws NamingException {
|
||||||
Hashtable<String, String> context = new Hashtable<>();
|
Hashtable<String, String> context = new Hashtable<>();
|
||||||
@ -75,41 +84,75 @@ public class LdapUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<LdapTransformUser> users(
|
public static List<LdapTransformUser> users(
|
||||||
String url, String adminUser, String adminPass, String baseDN) throws NamingException {
|
String url, String adminUser, String adminPass, String baseDN)
|
||||||
|
throws NamingException, IOException {
|
||||||
LdapContext ldapContext = initContext(url, adminUser, adminPass);
|
LdapContext ldapContext = initContext(url, adminUser, adminPass);
|
||||||
|
|
||||||
|
int pageSize = 1000;
|
||||||
|
List<LdapTransformUser> users = new ArrayList<>();
|
||||||
|
|
||||||
SearchControls controls = new SearchControls();
|
SearchControls controls = new SearchControls();
|
||||||
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||||
controls.setReturningAttributes(USER_RETURN_ATTRS);
|
controls.setReturningAttributes(USER_RETURN_ATTRS);
|
||||||
controls.setReturningObjFlag(true);
|
controls.setReturningObjFlag(true);
|
||||||
|
|
||||||
NamingEnumeration<SearchResult> result = null;
|
byte[] cookie = null;
|
||||||
try {
|
|
||||||
result = ldapContext.search(baseDN, USER_OBJECT_CLASS, controls);
|
while (true) {
|
||||||
} catch (NamingException e) {
|
try {
|
||||||
log.error("LDAP用户查询失败", e);
|
if (cookie != null) {
|
||||||
} finally {
|
ldapContext.setRequestControls(
|
||||||
closeContext(ldapContext);
|
new Control[] {
|
||||||
|
new PagedResultsControl(pageSize, cookie, false),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ldapContext.setRequestControls(
|
||||||
|
new Control[] {new PagedResultsControl(pageSize, false)});
|
||||||
|
}
|
||||||
|
|
||||||
|
NamingEnumeration<SearchResult> result =
|
||||||
|
ldapContext.search(baseDN, USER_OBJECT_CLASS, controls);
|
||||||
|
while (result.hasMoreElements()) {
|
||||||
|
SearchResult item = result.nextElement();
|
||||||
|
if (item != null) {
|
||||||
|
LdapTransformUser ldapTransformUser = parseTransformUser(item, baseDN);
|
||||||
|
if (ldapTransformUser != null) {
|
||||||
|
users.add(ldapTransformUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie = parseCookie(ldapContext.getResponseControls());
|
||||||
|
if (cookie == null || cookie.length == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (NamingException e) {
|
||||||
|
log.error("LDAP用户查询失败", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null || !result.hasMoreElements()) {
|
closeContext(ldapContext);
|
||||||
|
|
||||||
|
if (users.isEmpty()) {
|
||||||
log.info("LDAP服务中没有用户");
|
log.info("LDAP服务中没有用户");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<LdapTransformUser> users = new ArrayList<>();
|
|
||||||
while (result.hasMoreElements()) {
|
|
||||||
SearchResult item = result.nextElement();
|
|
||||||
if (item == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
LdapTransformUser ldapTransformUser = parseTransformUser(item, baseDN);
|
|
||||||
users.add(ldapTransformUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte[] parseCookie(Control[] controls) throws NamingException {
|
||||||
|
if (controls != null) {
|
||||||
|
for (Control control : controls) {
|
||||||
|
if (control instanceof PagedResultsResponseControl) {
|
||||||
|
return ((PagedResultsResponseControl) control).getCookie();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<LdapTransformDepartment> departments(
|
public static List<LdapTransformDepartment> departments(
|
||||||
String url, String adminUser, String adminPass, String baseDN) throws NamingException {
|
String url, String adminUser, String adminPass, String baseDN) throws NamingException {
|
||||||
LdapContext ldapContext = initContext(url, adminUser, adminPass);
|
LdapContext ldapContext = initContext(url, adminUser, adminPass);
|
||||||
@ -253,6 +296,16 @@ public class LdapUtil {
|
|||||||
LdapTransformUser ldapUser = new LdapTransformUser();
|
LdapTransformUser ldapUser = new LdapTransformUser();
|
||||||
ldapUser.setDn(item.getName());
|
ldapUser.setDn(item.getName());
|
||||||
|
|
||||||
|
if (attributes.get("userAccountControl") != null) {
|
||||||
|
String userAccountControl = (String) attributes.get("userAccountControl").get();
|
||||||
|
for (String s : DISABLE_USER_ACCOUNT_CONTROL) {
|
||||||
|
if (s.equals(userAccountControl)) {
|
||||||
|
ldapUser.setBan(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// name解析
|
// name解析
|
||||||
String displayName = getAttribute(attributes, "displayName");
|
String displayName = getAttribute(attributes, "displayName");
|
||||||
if (StringUtil.isEmpty(displayName)) {
|
if (StringUtil.isEmpty(displayName)) {
|
||||||
|
@ -275,15 +275,6 @@ public class AdminPermissionCheck implements CommandLineRunner {
|
|||||||
setSlug(BPermissionConstant.DATA_USER_NAME);
|
setSlug(BPermissionConstant.DATA_USER_NAME);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new AdminPermission() {
|
|
||||||
{
|
|
||||||
setSort(20);
|
|
||||||
setName("身份证号");
|
|
||||||
setSlug(
|
|
||||||
BPermissionConstant
|
|
||||||
.DATA_USER_ID_CARD);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -36,11 +36,12 @@ public class UpgradeCheck implements CommandLineRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) throws Exception {
|
public void run(String... args) throws Exception {
|
||||||
upgrade_v1_beta7();
|
upgrade_1_beta7();
|
||||||
upgrade_v1_4();
|
upgrade_1_4();
|
||||||
|
upgrade_1_6();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void upgrade_v1_4() {
|
private void upgrade_1_4() {
|
||||||
appConfigService.remove(
|
appConfigService.remove(
|
||||||
appConfigService
|
appConfigService
|
||||||
.query()
|
.query()
|
||||||
@ -54,7 +55,7 @@ public class UpgradeCheck implements CommandLineRunner {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void upgrade_v1_beta7() {
|
private void upgrade_1_beta7() {
|
||||||
appConfigService.update(
|
appConfigService.update(
|
||||||
new AppConfig() {
|
new AppConfig() {
|
||||||
{
|
{
|
||||||
@ -75,4 +76,18 @@ public class UpgradeCheck implements CommandLineRunner {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void upgrade_1_6() {
|
||||||
|
permissionService.remove(
|
||||||
|
permissionService
|
||||||
|
.query()
|
||||||
|
.getWrapper()
|
||||||
|
.in(
|
||||||
|
"slug",
|
||||||
|
new ArrayList<>() {
|
||||||
|
{
|
||||||
|
add("data-user-id-card");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user