mirror of https://gitee.com/topiam/eiam
Merge remote-tracking branch 'origin/master'
# Conflicts: # eiam-console/src/main/java/cn/topiam/employee/console/service/analysis/impl/AnalysisServiceImpl.javapull/65/head
commit
9ff1c96f05
|
@ -187,7 +187,7 @@ public class UserEntity extends LogicDeleteEntity<Long> {
|
||||||
*/
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private String plaintext;
|
private String passwordPlainText;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class UserRepositoryCustomizedImpl implements UserRepositoryCustomized {
|
||||||
@Override
|
@Override
|
||||||
public Page<UserPO> getUserList(UserListQuery query, Pageable pageable) {
|
public Page<UserPO> getUserList(UserListQuery query, Pageable pageable) {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
StringBuilder builder = new StringBuilder("SELECT `user`.id_, `user`.username_,`user`.password_, `user`.email_, `user`.phone_,`user`.phone_area_code, `user`.full_name ,`user`.nick_name, `user`.avatar_ , `user`.status_, `user`.data_origin, `user`.email_verified, `user`.phone_verified, `user`.auth_total, `user`.last_auth_ip, `user`.last_auth_time, `user`.expand_, `user`.external_id , `user`.expire_date,`user`.create_by, `user`.create_time, `user`.update_by , `user`.update_time, `user`.remark_, group_concat( IF(organization_member.primary_ = 1, null, organization_.display_path ) ) AS primary_org_display_path, group_concat( IF(organization_member.primary_ IS NULL, null, organization_.display_path ) ) AS org_display_path FROM `user` INNER JOIN `organization_member` ON (`user`.id_ = organization_member.user_id) INNER JOIN `organization` organization_ ON (organization_.id_ = organization_member.org_id) WHERE `user`.is_deleted = 0");
|
StringBuilder builder = new StringBuilder("SELECT `user`.id_, `user`.username_, `user`.password_, `user`.email_, `user`.phone_, `user`.phone_area_code, `user`.full_name, `user`.nick_name, `user`.avatar_, `user`.status_, `user`.data_origin, `user`.email_verified, `user`.phone_verified, `user`.auth_total, `user`.last_auth_ip, `user`.last_auth_time, `user`.expand_, `user`.external_id, `user`.expire_date, `user`.create_by, `user`.create_time, `user`.update_by, `user`.update_time, `user`.remark_, group_concat( IF( organization_member.primary_ = TRUE, organization_.display_path, NULL) ) AS primary_org_display_path, group_concat( IF ( organization_member.primary_ IS NULL, organization_.display_path, NULL ) ) AS org_display_path FROM `user` INNER JOIN `organization_member` ON ( `user`.id_ = organization_member.user_id ) INNER JOIN `organization` organization_ ON ( organization_.id_ = organization_member.org_id ) WHERE `user`.is_deleted = 0 AND organization_member.is_deleted = 0 ");
|
||||||
//组织条件
|
//组织条件
|
||||||
if (StringUtils.isNotBlank(query.getOrganizationId())) {
|
if (StringUtils.isNotBlank(query.getOrganizationId())) {
|
||||||
if (Boolean.TRUE.equals(query.getInclSubOrganization())) {
|
if (Boolean.TRUE.equals(query.getInclSubOrganization())) {
|
||||||
|
|
|
@ -88,6 +88,10 @@
|
||||||
<constraints nullable="true"/>
|
<constraints nullable="true"/>
|
||||||
</column>
|
</column>
|
||||||
</addColumn>
|
</addColumn>
|
||||||
|
<addColumn tableName="administrator">
|
||||||
|
<column name="full_name" remarks="姓名" type="VARCHAR(100)"/>
|
||||||
|
<column name="nick_name" remarks="昵称" type="VARCHAR(50)"/>
|
||||||
|
</addColumn>
|
||||||
<!--创建索引-->
|
<!--创建索引-->
|
||||||
<createIndex tableName="app_group_association" indexName="uk_app_group_association" unique="true">
|
<createIndex tableName="app_group_association" indexName="uk_app_group_association" unique="true">
|
||||||
<column name="group_id"/>
|
<column name="group_id"/>
|
||||||
|
|
|
@ -39,7 +39,6 @@ import {
|
||||||
Table,
|
Table,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
Tag,
|
|
||||||
Popover,
|
Popover,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
|
@ -184,44 +183,41 @@ export default (props: UserListProps) => {
|
||||||
dataIndex: 'orgDisplayPath',
|
dataIndex: 'orgDisplayPath',
|
||||||
search: false,
|
search: false,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, record) => [
|
render: (_, record) => {
|
||||||
<Popover
|
return (
|
||||||
key="pop"
|
<Popover
|
||||||
title={
|
key="pop"
|
||||||
<Tag color={'geekblue'} key={record.orgDisplayPath}>
|
title={intl.formatMessage({
|
||||||
{record.primaryOrgDisplayPath}
|
id: 'pages.account.user_list.user.columns.org_display_path',
|
||||||
</Tag>
|
|
||||||
}
|
|
||||||
content={
|
|
||||||
<Space direction="vertical" size="small" style={{ display: 'flex' }}>
|
|
||||||
{record.orgDisplayPath.split(',')?.map((p: string) => {
|
|
||||||
return (
|
|
||||||
<Tag color={'green'} key={p}>
|
|
||||||
{p}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Space key="primary_path">
|
|
||||||
{
|
|
||||||
<Tag color={'geekblue'} key={record.primaryOrgDisplayPath}>
|
|
||||||
{record.primaryOrgDisplayPath}
|
|
||||||
</Tag>
|
|
||||||
}
|
|
||||||
</Space>
|
|
||||||
<Space key="path" direction="vertical" size="small" style={{ display: 'flex' }}>
|
|
||||||
{record.orgDisplayPath.split(',')?.map((p: string) => {
|
|
||||||
return (
|
|
||||||
<Tag color={'green'} key={p}>
|
|
||||||
{p}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
})}
|
})}
|
||||||
</Space>
|
content={
|
||||||
</Popover>,
|
<>
|
||||||
],
|
{record.primaryOrgDisplayPath && (
|
||||||
|
<Space key="primary_path">{record.primaryOrgDisplayPath}</Space>
|
||||||
|
)}
|
||||||
|
{record.orgDisplayPath && (
|
||||||
|
<Space key="path" direction="vertical" size="small" style={{ display: 'flex' }}>
|
||||||
|
{record.orgDisplayPath?.split(',')?.map((p: string) => {
|
||||||
|
return p;
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{record.primaryOrgDisplayPath && (
|
||||||
|
<Space key="primary_path">{record.primaryOrgDisplayPath}</Space>
|
||||||
|
)}
|
||||||
|
{record.orgDisplayPath && (
|
||||||
|
<Space key="path" direction="vertical" size="small" style={{ display: 'flex' }}>
|
||||||
|
{record.orgDisplayPath?.split(',')?.map((p: string) => {
|
||||||
|
return p;
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'pages.account.user_list.user.columns.status' }),
|
title: intl.formatMessage({ id: 'pages.account.user_list.user.columns.status' }),
|
||||||
|
|
|
@ -181,6 +181,7 @@ declare namespace AccountAPI {
|
||||||
dataOrigin: string;
|
dataOrigin: string;
|
||||||
authTotal: string;
|
authTotal: string;
|
||||||
lastAuthTime: string;
|
lastAuthTime: string;
|
||||||
|
primaryOrgDisplayPath: string;
|
||||||
orgDisplayPath: string;
|
orgDisplayPath: string;
|
||||||
remark: string;
|
remark: string;
|
||||||
custom?: Record<string, any>;
|
custom?: Record<string, any>;
|
||||||
|
|
|
@ -117,11 +117,17 @@ public class UserListResult implements Serializable {
|
||||||
private LocalDateTime lastAuthTime;
|
private LocalDateTime lastAuthTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目录
|
* 从组织机构目录
|
||||||
*/
|
*/
|
||||||
@Parameter(description = "组织机构目录")
|
@Parameter(description = "从组织机构目录")
|
||||||
private String orgDisplayPath;
|
private String orgDisplayPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主组织目录
|
||||||
|
*/
|
||||||
|
@Parameter(description = "主组织机构目录")
|
||||||
|
private String primaryOrgDisplayPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最后修改密码时间
|
* 最后修改密码时间
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,8 +18,11 @@
|
||||||
package cn.topiam.employee.console.service.analysis.impl;
|
package cn.topiam.employee.console.service.analysis.impl;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.data.elasticsearch.client.elc.*;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@ -35,10 +38,18 @@ import cn.topiam.employee.common.repository.authentication.IdentityProviderRepos
|
||||||
import cn.topiam.employee.console.pojo.query.analysis.AnalysisQuery;
|
import cn.topiam.employee.console.pojo.query.analysis.AnalysisQuery;
|
||||||
import cn.topiam.employee.console.pojo.result.analysis.*;
|
import cn.topiam.employee.console.pojo.result.analysis.*;
|
||||||
import cn.topiam.employee.console.service.analysis.AnalysisService;
|
import cn.topiam.employee.console.service.analysis.AnalysisService;
|
||||||
|
import cn.topiam.employee.support.autoconfiguration.SupportProperties;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
|
||||||
|
import co.elastic.clients.json.JsonData;
|
||||||
|
import static cn.topiam.employee.audit.entity.Event.*;
|
||||||
import static cn.topiam.employee.console.converter.authn.IdentityProviderConverter.getIdentityProviderType;
|
import static cn.topiam.employee.console.converter.authn.IdentityProviderConverter.getIdentityProviderType;
|
||||||
|
import static cn.topiam.employee.support.constant.EiamConstants.DEFAULT_DATE_TIME_FORMATTER_PATTERN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TopIAM
|
* @author TopIAM
|
||||||
|
@ -49,6 +60,8 @@ import static cn.topiam.employee.console.converter.authn.IdentityProviderConvert
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AnalysisServiceImpl implements AnalysisService {
|
public class AnalysisServiceImpl implements AnalysisService {
|
||||||
|
|
||||||
|
public static final String COUNT = "count";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 概述
|
* 概述
|
||||||
*
|
*
|
||||||
|
@ -100,6 +113,22 @@ public class AnalysisServiceImpl implements AnalysisService {
|
||||||
return applicationVisitList;
|
return applicationVisitList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间查询条件
|
||||||
|
*
|
||||||
|
* @param params {@link AnalysisQuery}
|
||||||
|
* @return {@link Query}
|
||||||
|
*/
|
||||||
|
private Query getRangeQueryBuilder(AnalysisQuery params) {
|
||||||
|
String min = params.getStartTime()
|
||||||
|
.format(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMATTER_PATTERN));
|
||||||
|
String max = params.getEndTime()
|
||||||
|
.format(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMATTER_PATTERN));
|
||||||
|
// 查询条件
|
||||||
|
return QueryBuilders.range(range -> range.field(EVENT_TIME).timeZone(ZONE_ID)
|
||||||
|
.format(DEFAULT_DATE_TIME_FORMATTER_PATTERN).gt(JsonData.of(min)).lt(JsonData.of(max)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 热门认证方式
|
* 热门认证方式
|
||||||
* @param params {@link AnalysisQuery}
|
* @param params {@link AnalysisQuery}
|
||||||
|
@ -124,7 +153,7 @@ public class AnalysisServiceImpl implements AnalysisService {
|
||||||
* 登录区域统计
|
* 登录区域统计
|
||||||
*
|
*
|
||||||
* @param params {@link AnalysisQuery}
|
* @param params {@link AnalysisQuery}
|
||||||
* @return {@link List<AuthnZoneResult>}
|
* @return {@link AuthnZoneResult}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<AuthnZoneResult> authnZone(AnalysisQuery params) {
|
public List<AuthnZoneResult> authnZone(AnalysisQuery params) {
|
||||||
|
@ -150,6 +179,42 @@ public class AnalysisServiceImpl implements AnalysisService {
|
||||||
return app.getName();
|
return app.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼装查询条件
|
||||||
|
*
|
||||||
|
* @param query {@link Query}
|
||||||
|
* @param eventType {@link EventType}
|
||||||
|
* @return {@link BoolQuery.Builder}
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private BoolQuery.Builder getQueryBuilder(Query query, EventType eventType) {
|
||||||
|
// 查询条件
|
||||||
|
BoolQuery.Builder queryBuilder = QueryBuilders.bool();
|
||||||
|
// 事件类型
|
||||||
|
queryBuilder.must(Queries.termQueryAsQuery(EVENT_TYPE, eventType.getCode()));
|
||||||
|
// 日期条件
|
||||||
|
queryBuilder.filter(query);
|
||||||
|
return queryBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拼装查询条件
|
||||||
|
*
|
||||||
|
* @param query {@link Query}
|
||||||
|
* @param eventType {@link EventType}
|
||||||
|
* @return {@link Query}
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private Query getQuery(Query query, EventType eventType) {
|
||||||
|
return getQueryBuilder(query, eventType).build()._toQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String ZONE_ID = ZoneId.systemDefault().getId();
|
||||||
|
|
||||||
|
private final SupportProperties supportProperties;
|
||||||
|
|
||||||
|
// private final ElasticsearchTemplate elasticsearchTemplate;
|
||||||
|
|
||||||
private final AuditRepository auditRepository;
|
private final AuditRepository auditRepository;
|
||||||
|
|
||||||
private final AppRepository appRepository;
|
private final AppRepository appRepository;
|
||||||
|
|
|
@ -178,7 +178,7 @@ public class AbstractIdentitySourcePostProcessor {
|
||||||
entity.setDataOrigin(dataOrigin);
|
entity.setDataOrigin(dataOrigin);
|
||||||
entity.setIdentitySourceId(identitySource.getId());
|
entity.setIdentitySourceId(identitySource.getId());
|
||||||
entity.setPassword(passwordEncoder.encode(defaultPassword));
|
entity.setPassword(passwordEncoder.encode(defaultPassword));
|
||||||
entity.setPlaintext(defaultPassword);
|
entity.setPasswordPlainText(defaultPassword);
|
||||||
|
|
||||||
//必须字段
|
//必须字段
|
||||||
entity.setCreateBy(SYSTEM_DEFAULT_USER_NAME);
|
entity.setCreateBy(SYSTEM_DEFAULT_USER_NAME);
|
||||||
|
@ -302,14 +302,14 @@ public class AbstractIdentitySourcePostProcessor {
|
||||||
thirdPartyUser.getEmail(), thirdPartyUser.getPhone());
|
thirdPartyUser.getEmail(), thirdPartyUser.getPhone());
|
||||||
if (StringUtils.isNotEmpty(thirdPartyUser.getEmail())) {
|
if (StringUtils.isNotEmpty(thirdPartyUser.getEmail())) {
|
||||||
Map<String, Object> parameter = new HashMap<>(16);
|
Map<String, Object> parameter = new HashMap<>(16);
|
||||||
parameter.put(MsgVariable.PASSWORD, thirdPartyUser.getPlaintext());
|
parameter.put(MsgVariable.PASSWORD, thirdPartyUser.getPasswordPlainText());
|
||||||
mailMsgEventPublish.publish(MailType.RESET_PASSWORD_CONFIRM,
|
mailMsgEventPublish.publish(MailType.RESET_PASSWORD_CONFIRM,
|
||||||
thirdPartyUser.getEmail(), parameter);
|
thirdPartyUser.getEmail(), parameter);
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(thirdPartyUser.getPhone())) {
|
if (StringUtils.isNotEmpty(thirdPartyUser.getPhone())) {
|
||||||
LinkedHashMap<String, String> parameter = new LinkedHashMap<>();
|
LinkedHashMap<String, String> parameter = new LinkedHashMap<>();
|
||||||
parameter.put(USERNAME, thirdPartyUser.getUsername());
|
parameter.put(USERNAME, thirdPartyUser.getUsername());
|
||||||
parameter.put(MsgVariable.PASSWORD, thirdPartyUser.getPlaintext());
|
parameter.put(MsgVariable.PASSWORD, thirdPartyUser.getPasswordPlainText());
|
||||||
smsMsgEventPublish.publish(SmsType.RESET_PASSWORD_SUCCESS,
|
smsMsgEventPublish.publish(SmsType.RESET_PASSWORD_SUCCESS,
|
||||||
thirdPartyUser.getPhone(), parameter);
|
thirdPartyUser.getPhone(), parameter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public interface AccountConverter {
|
||||||
* @param param {@link UpdateUserInfoRequest} 更新参数
|
* @param param {@link UpdateUserInfoRequest} 更新参数
|
||||||
* @return {@link UserEntity} 用户实体
|
* @return {@link UserEntity} 用户实体
|
||||||
*/
|
*/
|
||||||
@Mapping(target = "plaintext", ignore = true)
|
@Mapping(target = "passwordPlainText", ignore = true)
|
||||||
@Mapping(target = "deleted", ignore = true)
|
@Mapping(target = "deleted", ignore = true)
|
||||||
@Mapping(target = "identitySourceId", ignore = true)
|
@Mapping(target = "identitySourceId", ignore = true)
|
||||||
@Mapping(target = "phoneVerified", ignore = true)
|
@Mapping(target = "phoneVerified", ignore = true)
|
||||||
|
@ -124,8 +124,8 @@ public interface AccountConverter {
|
||||||
* 账号绑定entity转result
|
* 账号绑定entity转result
|
||||||
*
|
*
|
||||||
* @param identityProviderList {@link List<IdentityProviderEntity>}
|
* @param identityProviderList {@link List<IdentityProviderEntity>}
|
||||||
* @param userIdpBindList {@link Iterable< UserIdpBindPO >}
|
* @param userIdpBindList {@link Iterable<UserIdpBindPO>}
|
||||||
* @return {@link List< BoundIdpListResult >}
|
* @return {@link List<BoundIdpListResult>}
|
||||||
*/
|
*/
|
||||||
default List<BoundIdpListResult> entityConverterToBoundIdpListResult(List<IdentityProviderEntity> identityProviderList,
|
default List<BoundIdpListResult> entityConverterToBoundIdpListResult(List<IdentityProviderEntity> identityProviderList,
|
||||||
Iterable<UserIdpBindPO> userIdpBindList) {
|
Iterable<UserIdpBindPO> userIdpBindList) {
|
||||||
|
|
|
@ -48,12 +48,6 @@ public class UpdateUserInfoRequest implements Serializable {
|
||||||
@Schema(description = "昵称")
|
@Schema(description = "昵称")
|
||||||
private String nickName;
|
private String nickName;
|
||||||
|
|
||||||
/**
|
|
||||||
* 个人简介
|
|
||||||
*/
|
|
||||||
@Schema(description = "个人简介")
|
|
||||||
private String personalProfile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 头像
|
* 头像
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -284,11 +284,6 @@ const BaseView = () => {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<ProFormTextArea
|
|
||||||
width="md"
|
|
||||||
name="personalProfile"
|
|
||||||
label={intl.formatMessage({ id: 'page.account.base.form.personal_profile' })}
|
|
||||||
/>
|
|
||||||
</ProForm>
|
</ProForm>
|
||||||
</div>
|
</div>
|
||||||
<div className={classnames(`${prefixCls}-right`, hashId)}>
|
<div className={classnames(`${prefixCls}-right`, hashId)}>
|
||||||
|
|
|
@ -27,7 +27,6 @@ export default {
|
||||||
'page.account.base.form.full_name': '姓名',
|
'page.account.base.form.full_name': '姓名',
|
||||||
'page.account.base.form.nick_name': '昵称',
|
'page.account.base.form.nick_name': '昵称',
|
||||||
'page.account.base.form.nick_name.rule.0': '请输入您的昵称',
|
'page.account.base.form.nick_name.rule.0': '请输入您的昵称',
|
||||||
'page.account.base.form.personal_profile': '个人简介',
|
|
||||||
'page.account.common.form.password': '密码',
|
'page.account.common.form.password': '密码',
|
||||||
'page.account.common.form.password.placeholder': '请输入密码',
|
'page.account.common.form.password.placeholder': '请输入密码',
|
||||||
'page.account.common.form.password.rule.0': '请输入密码',
|
'page.account.common.form.password.rule.0': '请输入密码',
|
||||||
|
|
Loading…
Reference in New Issue