Merge remote-tracking branch 'origin/master'

pull/47/head
shao1121353141 2023-09-11 22:04:59 +08:00
commit f55fbb3a16
13 changed files with 324 additions and 53 deletions

View File

@ -59,9 +59,19 @@ public abstract class AbstractApplicationService implements ApplicationService {
return account; return account;
} }
/**
*
*
* @param name {@link String}
* @param icon {@link String}
* @param remark {@link String}
* @param initLoginType {@link InitLoginType}
* @param authorizationType {@link AuthorizationType}
* @return {@link AppEntity}
*/
@Override @Override
public AppEntity createApp(String name, String icon, String remark, Long[] groupId, public AppEntity createApp(String name, String icon, String remark, InitLoginType initLoginType,
InitLoginType initLoginType, AuthorizationType authorizationType) { AuthorizationType authorizationType) {
AppEntity appEntity = new AppEntity(); AppEntity appEntity = new AppEntity();
appEntity.setName(name); appEntity.setName(name);
appEntity.setIcon(icon); appEntity.setIcon(icon);
@ -75,11 +85,18 @@ public abstract class AbstractApplicationService implements ApplicationService {
appEntity.setInitLoginType(initLoginType); appEntity.setInitLoginType(initLoginType);
appEntity.setAuthorizationType(authorizationType); appEntity.setAuthorizationType(authorizationType);
appEntity.setRemark(remark); appEntity.setRemark(remark);
appRepository.save(appEntity); return appRepository.save(appEntity);
}
@Override
public AppEntity createApp(String name, String icon, String remark, List<String> groupIds,
InitLoginType initLoginType, AuthorizationType authorizationType) {
AppEntity appEntity = createApp(name, icon, remark, initLoginType, authorizationType);
List<AppGroupAssociationEntity> list = new ArrayList<>(); List<AppGroupAssociationEntity> list = new ArrayList<>();
for (Long id : groupId) { for (String id : groupIds) {
AppGroupAssociationEntity appGroupAssociationEntity = new AppGroupAssociationEntity(); AppGroupAssociationEntity appGroupAssociationEntity = new AppGroupAssociationEntity();
appGroupAssociationEntity.setGroupId(id); appGroupAssociationEntity.setGroupId(Long.valueOf(id));
appGroupAssociationEntity.setAppId(appEntity.getId()); appGroupAssociationEntity.setAppId(appEntity.getId());
list.add(appGroupAssociationEntity); list.add(appGroupAssociationEntity);
} }

View File

@ -92,11 +92,11 @@ public interface ApplicationService {
* @param name {@link String} * @param name {@link String}
* @param icon {@link String} * @param icon {@link String}
* @param remark {@link String} * @param remark {@link String}
* @param groupId {@link String} id * @param groupIds {@link String} id
* @return {@link Long} ID * @return {@link Long} ID
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
String create(String name, String icon, String remark, Long[] groupId); String create(String name, String icon, String remark, List<String> groupIds);
/** /**
* *
@ -137,11 +137,24 @@ public interface ApplicationService {
* @param name {@link String} * @param name {@link String}
* @param icon {@link String} * @param icon {@link String}
* @param remark {@link String} * @param remark {@link String}
* @param groupId {@link Long} id
* @param initLoginType {@link InitLoginType} * @param initLoginType {@link InitLoginType}
* @param authorizationType {@link AuthorizationType} * @param authorizationType {@link AuthorizationType}
* @return {@link AppEntity} * @return {@link AppEntity}
*/ */
AppEntity createApp(String name, String icon, String remark, Long[] groupId, AppEntity createApp(String name, String icon, String remark, InitLoginType initLoginType,
AuthorizationType authorizationType);
/**
*
*
* @param name {@link String}
* @param icon {@link String}
* @param remark {@link String}
* @param groupIds {@link Long} id
* @param initLoginType {@link InitLoginType}
* @param authorizationType {@link AuthorizationType}
* @return {@link AppEntity}
*/
AppEntity createApp(String name, String icon, String remark, List<String> groupIds,
InitLoginType initLoginType, AuthorizationType authorizationType); InitLoginType initLoginType, AuthorizationType authorizationType);
} }

View File

@ -197,12 +197,12 @@ public class FormStandardApplicationServiceImpl extends AbstractFormApplicationS
* @param name {@link String} * @param name {@link String}
* @param icon {@link String} * @param icon {@link String}
* @param remark {@link String} * @param remark {@link String}
* @param groupId {@link Long} id * @param groupIds {@link Long} id
*/ */
@Override @Override
public String create(String name, String icon, String remark, Long[] groupId) { public String create(String name, String icon, String remark, List<String> groupIds) {
//1、创建应用 //1、创建应用
AppEntity appEntity = createApp(name, icon, remark, groupId, InitLoginType.PORTAL_OR_APP, AppEntity appEntity = createApp(name, icon, remark, groupIds, InitLoginType.PORTAL_OR_APP,
AuthorizationType.AUTHORIZATION); AuthorizationType.AUTHORIZATION);
AppFormConfigEntity appFormConfig = new AppFormConfigEntity(); AppFormConfigEntity appFormConfig = new AppFormConfigEntity();
appFormConfig.setAppId(appEntity.getId()); appFormConfig.setAppId(appEntity.getId());

View File

@ -201,12 +201,12 @@ public class JwtStandardCertificateApplicationServiceImpl extends
* @param name {@link String} * @param name {@link String}
* @param icon {@link String} * @param icon {@link String}
* @param remark {@link String} * @param remark {@link String}
* @param groupId {@link Long} id * @param groupIds {@link Long} id
*/ */
@Override @Override
public String create(String name, String icon, String remark, Long[] groupId) { public String create(String name, String icon, String remark, List<String> groupIds) {
//1、创建应用 //1、创建应用
AppEntity appEntity = createApp(name, icon, remark, groupId, InitLoginType.PORTAL_OR_APP, AppEntity appEntity = createApp(name, icon, remark, groupIds, InitLoginType.PORTAL_OR_APP,
AuthorizationType.AUTHORIZATION); AuthorizationType.AUTHORIZATION);
//jwt配置 //jwt配置
AppJwtConfigEntity jwtConfigEntity = new AppJwtConfigEntity(); AppJwtConfigEntity jwtConfigEntity = new AppJwtConfigEntity();

View File

@ -75,12 +75,12 @@ public class OidcStandardCertificateApplicationServiceImpl extends
* @param name {@link String} * @param name {@link String}
* @param icon {@link String} * @param icon {@link String}
* @param remark {@link String} * @param remark {@link String}
* @param groupId {@link Long} id * @param groupIds {@link Long} id
*/ */
@Override @Override
public String create(String name, String icon, String remark, Long[] groupId) { public String create(String name, String icon, String remark, List<String> groupIds) {
//1、创建应用 //1、创建应用
AppEntity appEntity = createApp(name, icon, remark, groupId, InitLoginType.APP, AppEntity appEntity = createApp(name, icon, remark, groupIds, InitLoginType.APP,
AuthorizationType.AUTHORIZATION); AuthorizationType.AUTHORIZATION);
//2、创建证书 //2、创建证书
createCertificate(appEntity.getId(), appEntity.getCode(), AppCertUsingType.OIDC_JWK); createCertificate(appEntity.getId(), appEntity.getCode(), AppCertUsingType.OIDC_JWK);

View File

@ -0,0 +1,67 @@
/*
* eiam-common - 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.common.enums.app;
import cn.topiam.employee.support.enums.BaseEnum;
import cn.topiam.employee.support.web.converter.EnumConvert;
/**
*
*
* @author TopIAM
* Created by support@topiam.cn on 2023/9/9 16:22
*/
public enum AppDefaultGroup implements BaseEnum {
DEVELOPMENT("development", "开发类"), OFFICE("office",
"办公类");
private final String code;
private final String desc;
AppDefaultGroup(String code, String desc) {
this.code = code;
this.desc = desc;
}
/**
*
*
* @param code {@link String}
* @return {@link AppPolicyEffect}
*/
@EnumConvert
public static AppDefaultGroup getType(String code) {
AppDefaultGroup[] values = values();
for (AppDefaultGroup status : values) {
if (String.valueOf(status.getCode()).equals(code)) {
return status;
}
}
return null;
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@ -0,0 +1,67 @@
/*
* eiam-common - 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.common.enums.app.converter;
import java.util.Objects;
import cn.topiam.employee.common.enums.app.AppDefaultGroup;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
/**
* @author TopIAM
* Created by support@topiam.cn on 2023/9/9 16:23
*/
@Converter(autoApply = true)
public class AppGroupConverter implements AttributeConverter<AppDefaultGroup, String> {
/**
* Converts the value stored in the entity attribute into the
* data representation to be stored in the database.
*
* @param attribute the entity attribute value to be converted
* @return the converted data to be stored in the database
* column
*/
@Override
public String convertToDatabaseColumn(AppDefaultGroup attribute) {
if (Objects.isNull(attribute)) {
return null;
}
return attribute.getCode();
}
/**
* Converts the data stored in the database column into the
* value to be stored in the entity attribute.
* Note that it is the responsibility of the converter writer to
* specify the correct <code>dbData</code> type for the corresponding
* column for use by the JDBC driver: i.e., persistence providers are
* not expected to do such type conversion.
*
* @param dbData the data from the database column to be
* converted
* @return the converted value to be stored in the entity
* attribute
*/
@Override
public AppDefaultGroup convertToEntityAttribute(String dbData) {
return AppDefaultGroup.getType(dbData);
}
}

View File

@ -17,6 +17,7 @@
*/ */
package cn.topiam.employee.common.repository.app; package cn.topiam.employee.common.repository.app;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -81,10 +82,30 @@ public interface AppGroupRepository extends LogicDeleteRepository<AppGroupEntity
*/ */
@NotNull @NotNull
@Cacheable @Cacheable
@Query(value = "SELECT * FROM app_group WHERE id_ = :id", nativeQuery = true) @Query(value = "FROM AppGroupEntity WHERE id = :id")
Optional<AppGroupEntity> findByIdContainsDeleted(@NotNull @Param(value = "id") Long id); Optional<AppGroupEntity> findByIdContainsDeleted(@NotNull @Param(value = "id") Long id);
@Query(value = "SELECT * FROM app_group WHERE is_deleted = 0", nativeQuery = true) /**
*
*
* @return {@link List}
*/
@Query(value = "FROM AppGroupEntity WHERE deleted = false ")
List<AppGroupEntity> getAppGroupList(); List<AppGroupEntity> getAppGroupList();
/**
* code
*
* @param codes {@link List}
* @return {@link List}
*/
List<AppGroupEntity> findAllByCodeIn(@Param("codes") Collection<String> codes);
/**
* code
*
* @param code {@link String}
* @return {@link AppGroupEntity}
*/
Optional<AppGroupEntity> findByCode(@Param("code") String code);
} }

View File

@ -54,35 +54,19 @@ public class AppGroupRepositoryCustomizedImpl implements AppGroupRepositoryCusto
@Override @Override
public Page<AppGroupPO> getAppGroupList(AppGroupQuery query, Pageable pageable) { public Page<AppGroupPO> getAppGroupList(AppGroupQuery query, Pageable pageable) {
//@formatter:off //@formatter:off
StringBuilder builder = new StringBuilder(""" StringBuilder builder = new StringBuilder("SELECT `group`.id_, `group`.name_, `group`.code_, `group`.type_, `group`.create_time, `group`.remark_, IFNULL( ass.app_count, 0) AS app_count FROM app_group `group` LEFT JOIN(SELECT aga.group_id, COUNT(*) AS `app_count` FROM app_group_association aga INNER JOIN app ON aga.app_id = app.id_ AND app.is_deleted = 0 GROUP BY aga.group_id ) ass ON `group`.id_ = ass.group_id WHERE is_deleted = '0'");
SELECT
`group`.id_,
`group`.name_,
`group`.code_,
`group`.type_,
`group`.create_time,
`group`.remark_,
IFNULL( ass.app_count, 0 ) AS app_count
FROM
app_group `group`
LEFT JOIN ( SELECT group_id, count(*) AS `app_count` FROM app_group_association GROUP BY group_id ) ass ON `group`.id_ = ass.group_id
WHERE is_deleted = '0'
""");
//分组名称 //分组名称
if (StringUtils.isNoneBlank(query.getName())) { if (StringUtils.isNoneBlank(query.getName())) {
builder.append(" AND `group`.name_ like '%").append(query.getName()).append("%'"); builder.append(" AND `group`.name_ like '%").append(query.getName()).append("%'");
} }
//分组编码 //分组编码
if (StringUtils.isNoneBlank(query.getCode())) { if (StringUtils.isNoneBlank(query.getCode())) {
builder.append(" AND `group`.code_ like '%").append(query.getCode()).append("%'"); builder.append(" AND `group`.code_ like '%").append(query.getCode()).append("%'");
} }
//分组类型 //分组类型
if (ObjectUtils.isNotEmpty(query.getType())) { if (ObjectUtils.isNotEmpty(query.getType())) {
builder.append(" AND `group`.type_ like '%").append(query.getType().getCode()).append("%'"); builder.append(" AND `group`.type_ like '%").append(query.getType().getCode()).append("%'");
} }
builder.append(" ORDER BY `group`.create_time DESC"); builder.append(" ORDER BY `group`.create_time DESC");
//@formatter:on //@formatter:on
String sql = builder.toString(); String sql = builder.toString();

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package cn.topiam.employee.console.listener; package cn.topiam.employee.console.initialize;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
@ -47,18 +47,17 @@ import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
import static cn.topiam.employee.support.util.CreateFileUtil.createFile; import static cn.topiam.employee.support.util.CreateFileUtil.createFile;
/** /**
* ConsoleAdminPasswordInitializeListener * DefaultAdministratorInitialize
* *
* @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) @Order(2)
@Component @Component
public class ConsoleAdminPasswordInitializeListener implements public class DefaultAdministratorInitialize implements ApplicationListener<ContextRefreshedEvent> {
ApplicationListener<ContextRefreshedEvent> {
private final Logger logger = LoggerFactory private final Logger logger = LoggerFactory
.getLogger(ConsoleAdminPasswordInitializeListener.class); .getLogger(DefaultAdministratorInitialize.class);
private static final String DIR_NAME = ".topiam"; private static final String DIR_NAME = ".topiam";
private static final String USER_HOME = "user.home"; private static final String USER_HOME = "user.home";
@ -159,9 +158,9 @@ public class ConsoleAdminPasswordInitializeListener implements
private final RedissonClient redissonClient; private final RedissonClient redissonClient;
public ConsoleAdminPasswordInitializeListener(AdministratorRepository administratorRepository, public DefaultAdministratorInitialize(AdministratorRepository administratorRepository,
PasswordEncoder passwordEncoder, PasswordEncoder passwordEncoder,
RedissonClient redissonClient) { RedissonClient redissonClient) {
this.administratorRepository = administratorRepository; this.administratorRepository = administratorRepository;
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.redissonClient = redissonClient; this.redissonClient = redissonClient;

View File

@ -0,0 +1,103 @@
/*
* 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.initialize;
import java.util.Arrays;
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.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.AlternativeJdkIdGenerator;
import cn.topiam.employee.common.entity.app.AppGroupEntity;
import cn.topiam.employee.common.enums.app.AppDefaultGroup;
import cn.topiam.employee.common.enums.app.AppGroupType;
import cn.topiam.employee.common.repository.app.AppGroupRepository;
import cn.topiam.employee.support.trace.TraceUtils;
import static cn.topiam.employee.support.lock.LockAspect.getTopiamLockKeyPrefix;
/**
* DefaultAppGroupInitialize
*
* @author TopIAM
* Created by support@topiam.cn on 2023/9/11 21:44
*/
@Order(2)
@Component
public class DefaultAppGroupInitialize implements ApplicationListener<ContextRefreshedEvent> {
@Override
@Transactional(rollbackFor = Exception.class)
public void onApplicationEvent(@NonNull ContextRefreshedEvent contextRefreshedEvent) {
//@formatter:off
String traceId = idGenerator.generateId().toString();
TraceUtils.put(traceId);
RLock lock = redissonClient.getLock(getTopiamLockKeyPrefix());
boolean tryLock = false;
try {
tryLock = lock.tryLock(1, TimeUnit.SECONDS);
if (tryLock) {
Arrays.stream(AppDefaultGroup.values()).toList().forEach(i -> {
Optional<AppGroupEntity> optional = appGroupRepository.findByCode(i.getCode());
if (optional.isEmpty()) {
AppGroupEntity appGroup = new AppGroupEntity();
appGroup.setCode(i.getCode());
appGroup.setName(i.getDesc());
appGroup.setType(AppGroupType.DEFAULT);
appGroup.setRemark(
"This app group is automatically created during system initialization.");
appGroupRepository.save(appGroup);
}
});
}
} catch (Exception exception) {
int exitCode = SpringApplication.exit(contextRefreshedEvent.getApplicationContext(),
() -> 0);
System.exit(exitCode);
} finally {
if (tryLock && lock.isLocked()) {
lock.unlock();
}
TraceUtils.remove();
}
//@formatter:on
}
private final AlternativeJdkIdGenerator idGenerator = new AlternativeJdkIdGenerator();
private final AppGroupRepository appGroupRepository;
private final RedissonClient redissonClient;
public DefaultAppGroupInitialize(AppGroupRepository appGroupRepository,
RedissonClient redissonClient) {
this.appGroupRepository = appGroupRepository;
this.redissonClient = redissonClient;
}
}

View File

@ -18,6 +18,7 @@
package cn.topiam.employee.console.pojo.save.app; package cn.topiam.employee.console.pojo.save.app;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import lombok.Data; import lombok.Data;
@ -40,30 +41,30 @@ public class AppCreateParam implements Serializable {
*/ */
@NotBlank(message = "应用名称不能为空") @NotBlank(message = "应用名称不能为空")
@Schema(description = "应用名称") @Schema(description = "应用名称")
private String name; private String name;
/** /**
* *
*/ */
@NotNull(message = "应用模版不能为空") @NotNull(message = "应用模版不能为空")
@Schema(description = "应用模版") @Schema(description = "应用模版")
private String template; private String template;
/** /**
* *
*/ */
@Schema(description = "应用图标") @Schema(description = "应用图标")
private String icon; private String icon;
/** /**
* *
*/ */
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;
/** /**
* id * id
*/ */
@Schema(description = "应用分组ID") @Schema(description = "应用分组")
private Long[] groupId; private List<String> groupIds;
} }

View File

@ -97,11 +97,10 @@ public class AppServiceImpl implements AppService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public AppCreateResult createApp(AppCreateParam param) { public AppCreateResult createApp(AppCreateParam param) {
// TODO 创建后没有数据权限
ApplicationService applicationService = applicationServiceLoader ApplicationService applicationService = applicationServiceLoader
.getApplicationService(param.getTemplate()); .getApplicationService(param.getTemplate());
String appId = applicationService.create(param.getName(), param.getIcon(), String appId = applicationService.create(param.getName(), param.getIcon(),
param.getRemark(), param.getGroupId()); param.getRemark(), param.getGroupIds());
AuditContext.setTarget(Target.builder().id(appId).type(TargetType.APPLICATION).build()); AuditContext.setTarget(Target.builder().id(appId).type(TargetType.APPLICATION).build());
return new AppCreateResult(appId); return new AppCreateResult(appId);
} }