mirror of https://gitee.com/topiam/eiam
🏗️ 初始化逻辑调整
parent
f044f4e2ad
commit
2c4a946cda
|
@ -22,31 +22,24 @@ import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.redisson.api.RLock;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.redisson.api.RedissonClient;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.util.AlternativeJdkIdGenerator;
|
import org.springframework.util.AlternativeJdkIdGenerator;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import cn.topiam.employee.common.entity.account.OrganizationMemberEntity;
|
||||||
import cn.topiam.employee.common.entity.setting.AdministratorEntity;
|
import cn.topiam.employee.common.entity.setting.AdministratorEntity;
|
||||||
import cn.topiam.employee.common.enums.UserStatus;
|
import cn.topiam.employee.common.enums.UserStatus;
|
||||||
|
import cn.topiam.employee.common.repository.account.OrganizationMemberRepository;
|
||||||
import cn.topiam.employee.common.repository.setting.AdministratorRepository;
|
import cn.topiam.employee.common.repository.setting.AdministratorRepository;
|
||||||
import cn.topiam.employee.support.init.Initializer;
|
import cn.topiam.employee.support.config.AbstractSystemInitializer;
|
||||||
import cn.topiam.employee.support.trace.TraceUtils;
|
import cn.topiam.employee.support.config.InitializationException;
|
||||||
import static cn.topiam.employee.support.constant.EiamConstants.DEFAULT_ADMIN_USERNAME;
|
import static cn.topiam.employee.support.constant.EiamConstants.DEFAULT_ADMIN_USERNAME;
|
||||||
import static cn.topiam.employee.support.constant.EiamConstants.TOPIAM_INIT_AUTHENTICATION;
|
import static cn.topiam.employee.support.constant.EiamConstants.ROOT_NODE;
|
||||||
import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
|
|
||||||
import static cn.topiam.employee.support.util.CreateFileUtil.createFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultAdministratorInitialize
|
* DefaultAdministratorInitialize
|
||||||
|
@ -54,9 +47,8 @@ import static cn.topiam.employee.support.util.CreateFileUtil.createFile;
|
||||||
* @author TopIAM
|
* @author TopIAM
|
||||||
* Created by support@topiam.cn on 2022/11/26 21:44
|
* Created by support@topiam.cn on 2022/11/26 21:44
|
||||||
*/
|
*/
|
||||||
@Order(2)
|
|
||||||
@Component
|
@Component
|
||||||
public class DefaultAdministratorInitializer implements Initializer {
|
public class DefaultAdministratorInitializer extends AbstractSystemInitializer {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory
|
private final Logger logger = LoggerFactory
|
||||||
.getLogger(DefaultAdministratorInitializer.class);
|
.getLogger(DefaultAdministratorInitializer.class);
|
||||||
|
@ -68,48 +60,43 @@ public class DefaultAdministratorInitializer implements Initializer {
|
||||||
private static final String INITIAL_PASSWORD_DEFAULT = "topiam.cn";
|
private static final String INITIAL_PASSWORD_DEFAULT = "topiam.cn";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
public void init() throws InitializationException {
|
||||||
public void execute(ApplicationContext applicationContext) {
|
|
||||||
//@formatter:off
|
|
||||||
String traceId = idGenerator.generateId().toString();
|
|
||||||
TraceUtils.put(traceId);
|
|
||||||
RLock lock = redissonClient.getLock(getTopiamLockKeyPrefix());
|
|
||||||
boolean tryLock = false;
|
|
||||||
try {
|
try {
|
||||||
SecurityContextHolder.getContext().setAuthentication(TOPIAM_INIT_AUTHENTICATION);
|
Optional<AdministratorEntity> optional = administratorRepository
|
||||||
tryLock = lock.tryLock(1, TimeUnit.SECONDS);
|
.findByUsername(DEFAULT_ADMIN_USERNAME);
|
||||||
if (tryLock){
|
|
||||||
Optional<AdministratorEntity> optional = administratorRepository.findByUsername(DEFAULT_ADMIN_USERNAME);
|
|
||||||
if (optional.isEmpty()) {
|
if (optional.isEmpty()) {
|
||||||
String initPassword;
|
String initPassword;
|
||||||
String initPasswordFileTips;
|
String initPasswordFileTips;
|
||||||
String passwordType = System.getProperty(INITIAL_PASSWORD_TYPE_NAME);
|
String passwordType = System.getProperty(INITIAL_PASSWORD_TYPE_NAME);
|
||||||
if (StringUtils.hasText(passwordType) && "generate".equals(passwordType)) {
|
if (StringUtils.hasText(passwordType) && "generate".equals(passwordType)) {
|
||||||
initPassword = idGenerator.generateId().toString().replace("-", "").toLowerCase(Locale.ENGLISH);
|
initPassword = idGenerator.generateId().toString().replace("-", "")
|
||||||
}
|
.toLowerCase(Locale.ENGLISH);
|
||||||
else {
|
} else {
|
||||||
String passwordInitial = System.getProperty(INITIAL_PASSWORD_VALUE_NAME);
|
String passwordInitial = System.getProperty(INITIAL_PASSWORD_VALUE_NAME);
|
||||||
if (StringUtils.hasText(passwordInitial)) {
|
if (StringUtils.hasText(passwordInitial)) {
|
||||||
initPassword = passwordInitial;
|
initPassword = passwordInitial;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
initPassword = INITIAL_PASSWORD_DEFAULT;
|
initPassword = INITIAL_PASSWORD_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String initialAdminPasswordFilePath = getInitialAdminPasswordFilePath();createFile(initialAdminPasswordFilePath);
|
String initialAdminPasswordFilePath = getInitialAdminPasswordFilePath();
|
||||||
BufferedWriter stream = new BufferedWriter(new FileWriter(initialAdminPasswordFilePath));
|
FileUtils.writeStringToFile(new File(initialAdminPasswordFilePath), initPassword,
|
||||||
|
"UTF-8");
|
||||||
|
BufferedWriter stream = new BufferedWriter(
|
||||||
|
new FileWriter(initialAdminPasswordFilePath));
|
||||||
initPasswordFileTips = "This may also be found at: " + initialAdminPasswordFilePath;
|
initPasswordFileTips = "This may also be found at: " + initialAdminPasswordFilePath;
|
||||||
//清空
|
//清空
|
||||||
stream.write(initPassword);
|
stream.write(initPassword);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
stream.close();
|
stream.close();
|
||||||
logger.info("""
|
logger.info(
|
||||||
|
"""
|
||||||
|
|
||||||
*************************************************************
|
*************************************************************
|
||||||
*************************************************************
|
*************************************************************
|
||||||
*************************************************************
|
*************************************************************
|
||||||
|
|
||||||
TOPIAM console initial setup is required. An admin user has been created and a initialize password.
|
TOPIAM console initial setup is required. An admin administrator has been created and a initialize password.
|
||||||
Please use the following password to proceed to installation:
|
Please use the following password to proceed to installation:
|
||||||
|
|
||||||
%s
|
%s
|
||||||
|
@ -119,42 +106,26 @@ public class DefaultAdministratorInitializer implements Initializer {
|
||||||
*************************************************************
|
*************************************************************
|
||||||
*************************************************************
|
*************************************************************
|
||||||
|
|
||||||
""".formatted(initPassword, initPasswordFileTips));
|
"""
|
||||||
|
.formatted(initPassword, initPasswordFileTips));
|
||||||
//保存管理员
|
//保存管理员
|
||||||
saveInitAdministrator(DEFAULT_ADMIN_USERNAME, initPassword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception exception) {
|
|
||||||
int exitCode = SpringApplication.exit(applicationContext,
|
|
||||||
() -> 0);
|
|
||||||
System.exit(exitCode);
|
|
||||||
} finally {
|
|
||||||
if (tryLock && lock.isLocked()) {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
TraceUtils.remove();
|
|
||||||
SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
|
|
||||||
}
|
|
||||||
//@formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存管理员
|
|
||||||
*
|
|
||||||
* @param username {@link String}
|
|
||||||
* @param password {@link String}
|
|
||||||
*/
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void saveInitAdministrator(String username, String password) {
|
|
||||||
AdministratorEntity administrator = new AdministratorEntity();
|
AdministratorEntity administrator = new AdministratorEntity();
|
||||||
administrator.setUsername(username);
|
administrator.setUsername(DEFAULT_ADMIN_USERNAME);
|
||||||
administrator.setPassword(passwordEncoder.encode(password));
|
administrator.setFullName("管理员");
|
||||||
|
administrator.setPassword(passwordEncoder.encode(initPassword));
|
||||||
administrator.setStatus(UserStatus.ENABLED);
|
administrator.setStatus(UserStatus.ENABLED);
|
||||||
administrator.setNeedChangePassword(true);
|
administrator.setNeedChangePassword(true);
|
||||||
administrator.setRemark(
|
administrator.setRemark(
|
||||||
"This administrator user is automatically created during system initialization.");
|
"This administrator is automatically created during system initialization.");
|
||||||
administratorRepository.save(administrator);
|
administratorRepository.save(administrator);
|
||||||
|
OrganizationMemberEntity member = new OrganizationMemberEntity();
|
||||||
|
member.setOrgId(ROOT_NODE);
|
||||||
|
member.setUserId(administrator.getId());
|
||||||
|
organizationMemberRepository.save(member);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InitializationException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String addSeparator(String dir) {
|
public static String addSeparator(String dir) {
|
||||||
|
@ -175,20 +146,24 @@ public class DefaultAdministratorInitializer implements Initializer {
|
||||||
return path + "initialAdminPassword";
|
return path + "initialAdminPassword";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
private final AlternativeJdkIdGenerator idGenerator = new AlternativeJdkIdGenerator();
|
private final AlternativeJdkIdGenerator idGenerator = new AlternativeJdkIdGenerator();
|
||||||
|
|
||||||
|
private final OrganizationMemberRepository organizationMemberRepository;
|
||||||
|
|
||||||
private final AdministratorRepository administratorRepository;
|
private final AdministratorRepository administratorRepository;
|
||||||
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
private final RedissonClient redissonClient;
|
public DefaultAdministratorInitializer(OrganizationMemberRepository organizationMemberRepository,
|
||||||
|
AdministratorRepository administratorRepository,
|
||||||
public DefaultAdministratorInitializer(AdministratorRepository administratorRepository,
|
PasswordEncoder passwordEncoder) {
|
||||||
PasswordEncoder passwordEncoder,
|
this.organizationMemberRepository = organizationMemberRepository;
|
||||||
RedissonClient redissonClient) {
|
|
||||||
this.administratorRepository = administratorRepository;
|
this.administratorRepository = administratorRepository;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
this.redissonClient = redissonClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,26 +19,17 @@ package cn.topiam.employee.console.initializer;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.redisson.api.RLock;
|
|
||||||
import org.redisson.api.RedissonClient;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.AlternativeJdkIdGenerator;
|
|
||||||
|
|
||||||
import cn.topiam.employee.common.entity.app.AppGroupEntity;
|
import cn.topiam.employee.common.entity.app.AppGroupEntity;
|
||||||
import cn.topiam.employee.common.enums.app.AppDefaultGroup;
|
import cn.topiam.employee.common.enums.app.AppDefaultGroup;
|
||||||
import cn.topiam.employee.common.enums.app.AppGroupType;
|
import cn.topiam.employee.common.enums.app.AppGroupType;
|
||||||
import cn.topiam.employee.common.repository.app.AppGroupRepository;
|
import cn.topiam.employee.common.repository.app.AppGroupRepository;
|
||||||
import cn.topiam.employee.support.init.Initializer;
|
import cn.topiam.employee.support.config.AbstractSystemInitializer;
|
||||||
import cn.topiam.employee.support.trace.TraceUtils;
|
import cn.topiam.employee.support.config.InitializationException;
|
||||||
import static cn.topiam.employee.support.constant.EiamConstants.TOPIAM_INIT_AUTHENTICATION;
|
|
||||||
import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultAppGroupInitialize
|
* DefaultAppGroupInitialize
|
||||||
|
@ -48,20 +39,12 @@ import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
|
||||||
*/
|
*/
|
||||||
@Order(2)
|
@Order(2)
|
||||||
@Component
|
@Component
|
||||||
public class DefaultAppGroupInitializer implements Initializer {
|
public class DefaultAppGroupInitializer extends AbstractSystemInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void execute(ApplicationContext applicationContext) {
|
public void init() throws InitializationException {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
String traceId = idGenerator.generateId().toString();
|
|
||||||
TraceUtils.put(traceId);
|
|
||||||
RLock lock = redissonClient.getLock(getTopiamLockKeyPrefix());
|
|
||||||
boolean tryLock = false;
|
|
||||||
try {
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(TOPIAM_INIT_AUTHENTICATION);
|
|
||||||
tryLock = lock.tryLock(1, TimeUnit.SECONDS);
|
|
||||||
if (tryLock) {
|
|
||||||
Arrays.stream(AppDefaultGroup.values()).toList().forEach(i -> {
|
Arrays.stream(AppDefaultGroup.values()).toList().forEach(i -> {
|
||||||
Optional<AppGroupEntity> optional = appGroupRepository.findByCode(i.getCode());
|
Optional<AppGroupEntity> optional = appGroupRepository.findByCode(i.getCode());
|
||||||
if (optional.isEmpty()) {
|
if (optional.isEmpty()) {
|
||||||
|
@ -74,33 +57,16 @@ public class DefaultAppGroupInitializer implements Initializer {
|
||||||
appGroupRepository.save(appGroup);
|
appGroupRepository.save(appGroup);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
} catch (Exception exception) {
|
public int getOrder() {
|
||||||
int exitCode = SpringApplication.exit(applicationContext,
|
return 4;
|
||||||
() -> 0);
|
|
||||||
System.exit(exitCode);
|
|
||||||
} finally {
|
|
||||||
if (tryLock && lock.isLocked()) {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
TraceUtils.remove();
|
|
||||||
SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
|
|
||||||
}
|
|
||||||
//@formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AlternativeJdkIdGenerator idGenerator = new AlternativeJdkIdGenerator();
|
|
||||||
|
|
||||||
private final AppGroupRepository appGroupRepository;
|
private final AppGroupRepository appGroupRepository;
|
||||||
|
|
||||||
private final RedissonClient redissonClient;
|
|
||||||
|
|
||||||
public DefaultAppGroupInitializer(AppGroupRepository appGroupRepository,
|
public DefaultAppGroupInitializer(AppGroupRepository appGroupRepository) {
|
||||||
RedissonClient redissonClient) {
|
|
||||||
this.appGroupRepository = appGroupRepository;
|
this.appGroupRepository = appGroupRepository;
|
||||||
this.redissonClient = redissonClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* eiam-console - Employee Identity and Access Management
|
||||||
|
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package cn.topiam.employee.console.initializer;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import cn.topiam.employee.common.entity.setting.SettingEntity;
|
||||||
|
import cn.topiam.employee.common.repository.setting.SettingRepository;
|
||||||
|
import cn.topiam.employee.support.config.AbstractSystemInitializer;
|
||||||
|
import cn.topiam.employee.support.config.InitializationException;
|
||||||
|
import cn.topiam.employee.support.util.AesUtils;
|
||||||
|
import static cn.topiam.employee.common.constant.SettingConstants.AES_SECRET;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EncryptSecretInitializer
|
||||||
|
*
|
||||||
|
* @author TopIAM
|
||||||
|
* Created by support@topiam.cn on 2024/04/04 21:24
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class EncryptSecretInitializer extends AbstractSystemInitializer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void init() throws InitializationException {
|
||||||
|
SettingEntity optional = settingRepository.findByName(AES_SECRET);
|
||||||
|
if (Objects.isNull(optional)) {
|
||||||
|
SettingEntity setting = new SettingEntity();
|
||||||
|
setting.setName(AES_SECRET);
|
||||||
|
setting.setValue(AesUtils.generateKey());
|
||||||
|
setting.setDesc("Project aes secret");
|
||||||
|
setting.setRemark(
|
||||||
|
"This aes secret is automatically created during system initialization.");
|
||||||
|
settingRepository.save(setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Integer.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SettingRepository
|
||||||
|
*/
|
||||||
|
private final SettingRepository settingRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param settingRepository {@link SettingRepository}
|
||||||
|
*/
|
||||||
|
public EncryptSecretInitializer(SettingRepository settingRepository) {
|
||||||
|
this.settingRepository = settingRepository;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* eiam-console - Employee Identity and Access Management
|
||||||
|
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package cn.topiam.employee.console.initializer;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import cn.topiam.employee.common.entity.setting.SettingEntity;
|
||||||
|
import cn.topiam.employee.common.geo.GeoLocationProviderConfig;
|
||||||
|
import cn.topiam.employee.common.jackjson.encrypt.EncryptionModule;
|
||||||
|
import cn.topiam.employee.common.repository.setting.SettingRepository;
|
||||||
|
import cn.topiam.employee.support.config.AbstractSystemInitializer;
|
||||||
|
import cn.topiam.employee.support.config.InitializationException;
|
||||||
|
import static cn.topiam.employee.common.geo.ip2region.Ip2regionGeoLocationParserImpl.IP2REGION;
|
||||||
|
import static cn.topiam.employee.core.setting.GeoIpProviderConstants.IPADDRESS_SETTING_NAME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GeoIpProviderInitializer
|
||||||
|
*
|
||||||
|
* @author TOPIAM
|
||||||
|
* Created by support@topiam.cn on 2024/11/3 18:11
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class GeoIpProviderInitializer extends AbstractSystemInitializer {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(GeoIpProviderInitializer.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void init() throws InitializationException {
|
||||||
|
//@formatter:off
|
||||||
|
try {
|
||||||
|
SettingEntity optional = settingRepository.findByName(IPADDRESS_SETTING_NAME);
|
||||||
|
if (Objects.isNull(optional)) {
|
||||||
|
logger.info("初始化系统默认IP地址提供商");
|
||||||
|
SettingEntity setting = new SettingEntity();
|
||||||
|
setting.setName(IPADDRESS_SETTING_NAME);
|
||||||
|
ObjectMapper objectMapper = EncryptionModule.deserializerDecrypt();
|
||||||
|
// 指定序列化输入的类型
|
||||||
|
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||||
|
setting.setValue(objectMapper.writeValueAsString(new GeoLocationProviderConfig(IP2REGION, null)));
|
||||||
|
setting.setDesc(IP2REGION.getName());
|
||||||
|
setting.setRemark("The system initializes the default configuration.");
|
||||||
|
settingRepository.save(setting);
|
||||||
|
}
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new InitializationException(e);
|
||||||
|
}
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SettingRepository
|
||||||
|
*/
|
||||||
|
private final SettingRepository settingRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param settingRepository {@link SettingRepository}
|
||||||
|
*/
|
||||||
|
public GeoIpProviderInitializer(SettingRepository settingRepository) {
|
||||||
|
this.settingRepository = settingRepository;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* eiam-console - Employee Identity and Access Management
|
||||||
|
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package cn.topiam.employee.console.initializer;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import cn.topiam.employee.common.entity.account.OrganizationEntity;
|
||||||
|
import cn.topiam.employee.common.enums.account.OrganizationType;
|
||||||
|
import cn.topiam.employee.common.repository.account.OrganizationRepository;
|
||||||
|
import cn.topiam.employee.support.config.AbstractSystemInitializer;
|
||||||
|
import cn.topiam.employee.support.config.InitializationException;
|
||||||
|
import cn.topiam.employee.support.security.util.SecurityUtils;
|
||||||
|
import static cn.topiam.employee.support.constant.EiamConstants.*;
|
||||||
|
import static cn.topiam.employee.support.security.userdetails.DataOrigin.INPUT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SystemInitializer
|
||||||
|
*
|
||||||
|
* @author TopIAM
|
||||||
|
* Created by support@topiam.cn on 2024/04/04 21:24
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RootOrganizationInitializer extends AbstractSystemInitializer {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(RootOrganizationInitializer.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void init() throws InitializationException {
|
||||||
|
//@formatter:off
|
||||||
|
Optional<OrganizationEntity> optional = organizationRepository.findById(ROOT_NODE);
|
||||||
|
if (optional.isEmpty()) {
|
||||||
|
logger.info("初始化父级组织");
|
||||||
|
OrganizationEntity organization = new OrganizationEntity();
|
||||||
|
organization.setId(ROOT_NODE);
|
||||||
|
organization.setName(ROOT_DEPT_NAME);
|
||||||
|
organization.setCode(ROOT_NODE);
|
||||||
|
organization.setPath(PATH_SEPARATOR+ROOT_NODE);
|
||||||
|
organization.setDisplayPath(PATH_SEPARATOR+ROOT_DEPT_NAME);
|
||||||
|
organization.setDataOrigin(INPUT.getType());
|
||||||
|
organization.setType(OrganizationType.GROUP);
|
||||||
|
organization.setLeaf(false);
|
||||||
|
organization.setEnabled(true);
|
||||||
|
organization.setOrder(0L);
|
||||||
|
organization.setCreateBy(SecurityUtils.getCurrentUserName());
|
||||||
|
organization.setCreateTime(LocalDateTime.now());
|
||||||
|
organization.setUpdateBy(SecurityUtils.getCurrentUserName());
|
||||||
|
organization.setUpdateTime(LocalDateTime.now());
|
||||||
|
organization.setRemark("Root organization");
|
||||||
|
organizationRepository.batchSave(Lists.newArrayList(organization));
|
||||||
|
}
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OrganizationRepository
|
||||||
|
*/
|
||||||
|
private final OrganizationRepository organizationRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param organizationRepository {@link OrganizationRepository}
|
||||||
|
*/
|
||||||
|
public RootOrganizationInitializer(OrganizationRepository organizationRepository) {
|
||||||
|
this.organizationRepository = organizationRepository;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,197 +0,0 @@
|
||||||
/*
|
|
||||||
* eiam-core - Employee Identity and Access Management
|
|
||||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package cn.topiam.employee.core.initializer;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.redisson.api.RLock;
|
|
||||||
import org.redisson.api.RedissonClient;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.util.AlternativeJdkIdGenerator;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
import cn.topiam.employee.common.entity.account.OrganizationEntity;
|
|
||||||
import cn.topiam.employee.common.entity.setting.SettingEntity;
|
|
||||||
import cn.topiam.employee.common.geo.GeoLocationProviderConfig;
|
|
||||||
import cn.topiam.employee.common.jackjson.encrypt.EncryptionModule;
|
|
||||||
import cn.topiam.employee.common.repository.account.OrganizationRepository;
|
|
||||||
import cn.topiam.employee.common.repository.setting.SettingRepository;
|
|
||||||
import cn.topiam.employee.support.init.Initializer;
|
|
||||||
import cn.topiam.employee.support.security.util.SecurityUtils;
|
|
||||||
import cn.topiam.employee.support.trace.TraceUtils;
|
|
||||||
import cn.topiam.employee.support.util.AesUtils;
|
|
||||||
import static cn.topiam.employee.common.constant.SettingConstants.AES_SECRET;
|
|
||||||
import static cn.topiam.employee.common.enums.account.OrganizationType.DEPARTMENT;
|
|
||||||
import static cn.topiam.employee.common.geo.ip2region.Ip2regionGeoLocationServiceImpl.IP2REGION;
|
|
||||||
import static cn.topiam.employee.core.setting.GeoIpProviderConstants.IPADDRESS_SETTING_NAME;
|
|
||||||
import static cn.topiam.employee.support.constant.EiamConstants.*;
|
|
||||||
import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
|
|
||||||
import static cn.topiam.employee.support.security.userdetails.DataOrigin.INPUT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SystemInitializer
|
|
||||||
*
|
|
||||||
* @author TopIAM
|
|
||||||
* Created by support@topiam.cn on 2024/04/04 21:24
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class SystemInitializer implements Initializer {
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(SystemInitializer.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void execute(ApplicationContext applicationContext) {
|
|
||||||
String traceId = idGenerator.generateId().toString();
|
|
||||||
TraceUtils.put(traceId);
|
|
||||||
RLock lock = redissonClient.getLock(getTopiamLockKeyPrefix() + COLON + "system_init");
|
|
||||||
boolean tryLock = false;
|
|
||||||
try {
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(TOPIAM_INIT_AUTHENTICATION);
|
|
||||||
tryLock = lock.tryLock(1, TimeUnit.SECONDS);
|
|
||||||
if (tryLock) {
|
|
||||||
//init 加密秘钥
|
|
||||||
initEncryptSecret();
|
|
||||||
//init IP 提供商
|
|
||||||
initIpProvider();
|
|
||||||
//初始化组织机构
|
|
||||||
initRootOrganization();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
int exitCode = SpringApplication.exit(applicationContext, () -> 0);
|
|
||||||
System.exit(exitCode);
|
|
||||||
} finally {
|
|
||||||
if (tryLock && lock.isLocked()) {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
TraceUtils.remove();
|
|
||||||
SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化加密秘钥
|
|
||||||
*/
|
|
||||||
private void initEncryptSecret() {
|
|
||||||
SettingEntity optional = settingRepository.findByName(AES_SECRET);
|
|
||||||
if (Objects.isNull(optional)) {
|
|
||||||
SettingEntity setting = new SettingEntity();
|
|
||||||
setting.setName(AES_SECRET);
|
|
||||||
setting.setValue(AesUtils.generateKey());
|
|
||||||
setting.setDesc("Project aes secret");
|
|
||||||
setting.setRemark(
|
|
||||||
"This aes secret is automatically created during system initialization.");
|
|
||||||
settingRepository.save(setting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化IP地址提供商
|
|
||||||
*
|
|
||||||
* @throws JsonProcessingException JsonProcessingException
|
|
||||||
*/
|
|
||||||
private void initIpProvider() throws JsonProcessingException {
|
|
||||||
//@formatter:off
|
|
||||||
SettingEntity optional = settingRepository.findByName(IPADDRESS_SETTING_NAME);
|
|
||||||
if (Objects.isNull(optional)) {
|
|
||||||
logger.info("初始化系统默认IP地址提供商");
|
|
||||||
SettingEntity setting = new SettingEntity();
|
|
||||||
setting.setName(IPADDRESS_SETTING_NAME);
|
|
||||||
ObjectMapper objectMapper = EncryptionModule.deserializerDecrypt();
|
|
||||||
// 指定序列化输入的类型
|
|
||||||
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
|
||||||
setting.setValue(objectMapper.writeValueAsString(new GeoLocationProviderConfig(IP2REGION, null)));
|
|
||||||
setting.setDesc(IP2REGION.getName());
|
|
||||||
setting.setRemark("The system initializes the default configuration.");
|
|
||||||
settingRepository.save(setting);
|
|
||||||
}
|
|
||||||
//@formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化组织机构
|
|
||||||
*/
|
|
||||||
private void initRootOrganization() {
|
|
||||||
//@formatter:off
|
|
||||||
Optional<OrganizationEntity> optional = organizationRepository.findById(ROOT_NODE);
|
|
||||||
if (optional.isEmpty()) {
|
|
||||||
logger.info("初始化父级组织");
|
|
||||||
OrganizationEntity organization = new OrganizationEntity();
|
|
||||||
organization.setId(ROOT_NODE);
|
|
||||||
organization.setName(ROOT_DEPT_NAME);
|
|
||||||
organization.setCode(ROOT_NODE);
|
|
||||||
organization.setPath(PATH_SEPARATOR+ROOT_NODE);
|
|
||||||
organization.setDisplayPath(PATH_SEPARATOR+ROOT_DEPT_NAME);
|
|
||||||
organization.setType(DEPARTMENT);
|
|
||||||
organization.setDataOrigin(INPUT.getType());
|
|
||||||
organization.setLeaf(false);
|
|
||||||
organization.setEnabled(true);
|
|
||||||
organization.setOrder(0L);
|
|
||||||
organization.setCreateBy(SecurityUtils.getCurrentUserName());
|
|
||||||
organization.setCreateTime(LocalDateTime.now());
|
|
||||||
organization.setUpdateBy(SecurityUtils.getCurrentUserName());
|
|
||||||
organization.setUpdateTime(LocalDateTime.now());
|
|
||||||
organization.setRemark("Root organization");
|
|
||||||
organizationRepository.batchSave(Lists.newArrayList(organization));
|
|
||||||
}
|
|
||||||
//@formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AlternativeJdkIdGenerator idGenerator = new AlternativeJdkIdGenerator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RedissonClient
|
|
||||||
*/
|
|
||||||
private final RedissonClient redissonClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SettingRepository
|
|
||||||
*/
|
|
||||||
private final SettingRepository settingRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OrganizationRepository
|
|
||||||
*/
|
|
||||||
private final OrganizationRepository organizationRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param redissonClient {@link RedissonClient}
|
|
||||||
* @param settingRepository {@link SettingRepository}
|
|
||||||
* @param organizationRepository {@link OrganizationRepository}
|
|
||||||
*/
|
|
||||||
public SystemInitializer(RedissonClient redissonClient, SettingRepository settingRepository,
|
|
||||||
OrganizationRepository organizationRepository) {
|
|
||||||
this.redissonClient = redissonClient;
|
|
||||||
this.settingRepository = settingRepository;
|
|
||||||
this.organizationRepository = organizationRepository;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue