From 8e5fc93d13ce33e0fe146c7765b53d40b7411eef Mon Sep 17 00:00:00 2001 From: MaxKey Date: Tue, 13 Sep 2022 11:09:18 +0800 Subject: [PATCH] new version provision --- .../maxkey/util/AuthorizationHeaderUtils.java | 8 + .../configuration/ApplicationConfig.java | 34 +- .../java/org/maxkey/entity/Connectors.java | 210 +++++++++++ .../org/maxkey/entity/HistoryConnector.java | 334 ++++++++---------- .../org/maxkey/web/HttpRequestAdapter.java | 65 +++- .../persistence/mapper/ConnectorsMapper.java | 33 ++ .../persistence/service/AccountsService.java | 6 +- .../service/ConnectorsService.java | 42 +++ .../persistence/service/UserInfoService.java | 6 +- .../maxkey/provision/ProvisionMessage.java | 11 +- .../maxkey/provision/ProvisionService.java | 4 +- .../provision/thread/ProvisioningRunner.java | 205 +++++++++++ .../thread/ProvisioningRunnerThread.java | 23 ++ .../provision/thread/ProvisioningThread.java | 23 +- .../mapper/xml/mysql/ConnectorsMapper.xml | 25 ++ .../xml/mysql/HistoryConnectorMapper.xml | 4 - .../src/app/entity/Connectors.ts | 66 ++++ .../audit-connector.component.html | 86 ++--- .../audit-connector.component.ts | 15 +- .../audit-logins/audit-logins.component.html | 72 ++-- .../audit-synchronizer.component.html | 76 ++-- .../audit-synchronizer.component.ts | 15 +- .../src/app/routes/config/config.module.ts | 17 +- .../connector-editer.component.html | 81 +++++ .../connector-editer.component.less | 0 .../connector-editer.component.spec.ts | 25 ++ .../connector-editer.component.ts | 91 +++++ .../connectors/connectors.component.html | 75 ++++ .../connectors/connectors.component.less | 0 .../connectors/connectors.component.spec.ts | 25 ++ .../config/connectors/connectors.component.ts | 203 +++++++++++ .../src/app/service/connectors.service.ts | 33 ++ .../src/app/service/synchronizers.service.ts | 7 +- .../src/assets/app-data.json | 28 +- .../src/assets/i18n/en-US.json | 13 +- .../src/assets/i18n/zh-CN.json | 13 +- .../src/assets/i18n/zh-TW.json | 13 +- .../main/java/org/maxkey/MaxKeyMvcConfig.java | 6 +- .../resources/application-http.properties | 4 +- .../org/maxkey/MaxKeyMgtListenerConfig.java | 22 ++ .../java/org/maxkey/MaxKeyMgtMvcConfig.java | 8 +- .../contorller/ConnectorsController.java | 105 ++++++ .../resources/application-http.properties | 4 +- 43 files changed, 1711 insertions(+), 425 deletions(-) create mode 100644 maxkey-core/src/main/java/org/maxkey/entity/Connectors.java create mode 100644 maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/ConnectorsMapper.java create mode 100644 maxkey-persistence/src/main/java/org/maxkey/persistence/service/ConnectorsService.java create mode 100644 maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunner.java create mode 100644 maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunnerThread.java create mode 100644 maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ConnectorsMapper.xml create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/entity/Connectors.ts create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.html create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.less create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.spec.ts create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.ts create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.html create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.less create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.spec.ts create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.ts create mode 100644 maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/connectors.service.ts create mode 100644 maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/config/contorller/ConnectorsController.java diff --git a/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java b/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java index 7bbd036f4..1fcf0d753 100644 --- a/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java +++ b/maxkey-common/src/main/java/org/maxkey/util/AuthorizationHeaderUtils.java @@ -17,6 +17,8 @@ package org.maxkey.util; +import java.util.HashMap; + import javax.servlet.http.HttpServletRequest; import org.maxkey.crypto.Base64Utils; @@ -89,5 +91,11 @@ public class AuthorizationHeaderUtils { } return null; } + + public static HashMap authorization(String authorization) { + HashMap authorizationMap = new HashMap(); + authorizationMap.put(HEADER_Authorization, authorization); + return authorizationMap; + } } diff --git a/maxkey-core/src/main/java/org/maxkey/configuration/ApplicationConfig.java b/maxkey-core/src/main/java/org/maxkey/configuration/ApplicationConfig.java index cf18c0216..9b5494fe0 100644 --- a/maxkey-core/src/main/java/org/maxkey/configuration/ApplicationConfig.java +++ b/maxkey-core/src/main/java/org/maxkey/configuration/ApplicationConfig.java @@ -67,8 +67,8 @@ public class ApplicationConfig { @Value("${server.servlet.session.timeout:1800}") private int sessionTimeout; - @Value("${maxkey.server.message.queue:none}") - private String messageQueue; + @Value("${maxkey.server.provision:false}") + private boolean provision; @Value("${maxkey.notices.visible:false}") private boolean noticesVisible; @@ -192,21 +192,21 @@ public class ApplicationConfig { this.defaultUri = defaultUri; } - public String getMessageQueue() { - return messageQueue; - } - - public boolean isMessageQueueSupport() { - if(StringUtils.isBlank(messageQueue)||messageQueue.equalsIgnoreCase("none")) { - return false; - } - return true; - } - - public void setMessageQueue(String messageQueue) { - this.messageQueue = messageQueue; + public boolean isProvision() { + return provision; } + public void setProvision(boolean provision) { + this.provision = provision; + } + + public boolean isProvisionSupport() { + if(provision) { + return true; + } + return false; + } + public String getMgtUri() { return mgtUri; } @@ -262,8 +262,8 @@ public class ApplicationConfig { builder.append(mgtUri); builder.append(", port="); builder.append(port); - builder.append(", kafkaSupport="); - builder.append(messageQueue); + builder.append(", provision="); + builder.append(provision); builder.append(", maxKeyUri="); builder.append(authzUri); builder.append("]"); diff --git a/maxkey-core/src/main/java/org/maxkey/entity/Connectors.java b/maxkey-core/src/main/java/org/maxkey/entity/Connectors.java new file mode 100644 index 000000000..e604abf32 --- /dev/null +++ b/maxkey-core/src/main/java/org/maxkey/entity/Connectors.java @@ -0,0 +1,210 @@ +/* + * Copyright [2021] [MaxKey of copyright http://www.maxkey.top] + * + * 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 org.maxkey.entity; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import org.apache.mybatis.jpa.persistence.JpaBaseEntity; +import org.maxkey.pretty.impl.JsonPretty; + +@Entity +@Table(name = "MXK_CONNECTORS") +public class Connectors extends JpaBaseEntity implements Serializable { + + private static final long serialVersionUID = 4660258495864814777L; + @Id + @Column + @GeneratedValue(strategy = GenerationType.AUTO, generator = "snowflakeid") + String id; + @Column + String connName; + @Column + String scheduler; + @Column + int justInTime; + @Column + String providerUrl; + @Column + String principal; + @Column + String credentials; + @Column + String filters; + @Column + String description; + @Column + String createdBy; + @Column + String createdDate; + @Column + String modifiedBy; + @Column + String modifiedDate; + @Column + String status; + + @Column + private String instId; + + private String instName; + + public Connectors() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getConnName() { + return connName; + } + + public void setConnName(String connName) { + this.connName = connName; + } + + public int getJustInTime() { + return justInTime; + } + + public void setJustInTime(int justInTime) { + this.justInTime = justInTime; + } + + public String getScheduler() { + return scheduler; + } + + public void setScheduler(String scheduler) { + this.scheduler = scheduler; + } + + public String getProviderUrl() { + return providerUrl; + } + + public void setProviderUrl(String providerUrl) { + this.providerUrl = providerUrl; + } + + public String getPrincipal() { + return principal; + } + + public void setPrincipal(String principal) { + this.principal = principal; + } + + public String getCredentials() { + return credentials; + } + + public void setCredentials(String credentials) { + this.credentials = credentials; + } + + public String getFilters() { + return filters; + } + + public void setFilters(String filters) { + this.filters = filters; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public String getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(String createdDate) { + this.createdDate = createdDate; + } + + public String getModifiedBy() { + return modifiedBy; + } + + public void setModifiedBy(String modifiedBy) { + this.modifiedBy = modifiedBy; + } + + public String getModifiedDate() { + return modifiedDate; + } + + public void setModifiedDate(String modifiedDate) { + this.modifiedDate = modifiedDate; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getInstId() { + return instId; + } + + public void setInstId(String instId) { + this.instId = instId; + } + + public String getInstName() { + return instName; + } + + public void setInstName(String instName) { + this.instName = instName; + } + + public Connectors(String id) { + this.id = id; + } + + @Override + public String toString() { + return new JsonPretty().format(this); + } + +} diff --git a/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java b/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java index c1207c902..58c56dd5a 100644 --- a/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java +++ b/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.maxkey.entity; @@ -29,209 +28,177 @@ import javax.persistence.Table; import org.apache.mybatis.jpa.persistence.JpaBaseEntity; @Entity -@Table(name = "MXK_HISTORY_CONNECTOR") -public class HistoryConnector extends JpaBaseEntity implements Serializable{ +@Table(name = "MXK_HISTORY_CONNECTOR") +public class HistoryConnector extends JpaBaseEntity implements Serializable { + /** + * + */ + private static final long serialVersionUID = 3465459057253994386L; + + @Id + @Column + @GeneratedValue(strategy = GenerationType.AUTO, generator = "snowflakeid") + String id; + + @Column + String conName; + + @Column + String topic; + + @Column + String actionType; + + @Column + String sourceId; + + @Column + String sourceName; + + @Column + String objectId; + + @Column + String objectName; + + @Column + String description; + + String syncTime; + + @Column + String result; + + String startDate; + + String endDate; - /** - * - */ - private static final long serialVersionUID = 3465459057253994386L; - - @Id - @Column - @GeneratedValue(strategy=GenerationType.AUTO,generator="snowflakeid") - String id; - - @Column - String conName; - - @Column - String conType; - - @Column - String conAction; - - @Column - String sourceId; - - @Column - String sourceName; - - @Column - String objectId; - - @Column - String objectName; - - @Column - String description; - - - String syncTime; - - @Column - String result; - - String startDate; - - String endDate; - @Column private String instId; private String instName; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - - public String getConName() { - return conName; - } - - - public void setConName(String conName) { - this.conName = conName; - } - - - public String getConType() { - return conType; - } - - - public void setConType(String conType) { - this.conType = conType; - } - - - public String getSourceId() { - return sourceId; - } - - - public void setSourceId(String sourceId) { - this.sourceId = sourceId; - } - - - public String getSourceName() { - return sourceName; - } - - - public void setSourceName(String sourceName) { - this.sourceName = sourceName; - } - - - public String getObjectId() { - return objectId; - } - - - public void setObjectId(String objectId) { - this.objectId = objectId; - } - - - public String getObjectName() { - return objectName; - } - - - public void setObjectName(String objectName) { - this.objectName = objectName; - } - - - public String getDescription() { - return description; - } - - - public void setDescription(String description) { - this.description = description; - } - - - public String getSyncTime() { - return syncTime; - } - - - public void setSyncTime(String syncTime) { - this.syncTime = syncTime; - } - - - public String getResult() { - return result; - } - - - public void setResult(String result) { - this.result = result; - } - - - public String getStartDate() { - return startDate; - } - - - public void setStartDate(String startDate) { - this.startDate = startDate; - } - - - public String getEndDate() { - return endDate; - } - - - public void setEndDate(String endDate) { - this.endDate = endDate; - } - - - public String getConAction() { - return conAction; + public String getId() { + return id; } - - public void setConAction(String conAction) { - this.conAction = conAction; + public void setId(String id) { + this.id = id; } + public String getConName() { + return conName; + } + + public void setConName(String conName) { + this.conName = conName; + } + + public String getSourceId() { + return sourceId; + } + + public void setSourceId(String sourceId) { + this.sourceId = sourceId; + } + + public String getSourceName() { + return sourceName; + } + + public void setSourceName(String sourceName) { + this.sourceName = sourceName; + } + + public String getObjectId() { + return objectId; + } + + public void setObjectId(String objectId) { + this.objectId = objectId; + } + + public String getObjectName() { + return objectName; + } + + public void setObjectName(String objectName) { + this.objectName = objectName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getSyncTime() { + return syncTime; + } + + public void setSyncTime(String syncTime) { + this.syncTime = syncTime; + } + + public String getResult() { + return result; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getActionType() { + return actionType; + } + + public void setActionType(String actionType) { + this.actionType = actionType; + } + + public void setResult(String result) { + this.result = result; + } + + public String getStartDate() { + return startDate; + } + + public void setStartDate(String startDate) { + this.startDate = startDate; + } + + public String getEndDate() { + return endDate; + } + + public void setEndDate(String endDate) { + this.endDate = endDate; + } public String getInstId() { return instId; } - public void setInstId(String instId) { this.instId = instId; } - public String getInstName() { return instName; } - public void setInstName(String instName) { this.instName = instName; } - @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -239,10 +206,10 @@ public class HistoryConnector extends JpaBaseEntity implements Serializable{ builder.append(id); builder.append(", conName="); builder.append(conName); - builder.append(", conType="); - builder.append(conType); - builder.append(", conAction="); - builder.append(conAction); + builder.append(", topic="); + builder.append(topic); + builder.append(", actionType="); + builder.append(actionType); builder.append(", sourceId="); builder.append(sourceId); builder.append(", sourceName="); @@ -261,9 +228,12 @@ public class HistoryConnector extends JpaBaseEntity implements Serializable{ builder.append(startDate); builder.append(", endDate="); builder.append(endDate); + builder.append(", instId="); + builder.append(instId); + builder.append(", instName="); + builder.append(instName); builder.append("]"); return builder.toString(); } - - + } diff --git a/maxkey-core/src/main/java/org/maxkey/web/HttpRequestAdapter.java b/maxkey-core/src/main/java/org/maxkey/web/HttpRequestAdapter.java index 9490db9e3..31bf75f81 100644 --- a/maxkey-core/src/main/java/org/maxkey/web/HttpRequestAdapter.java +++ b/maxkey-core/src/main/java/org/maxkey/web/HttpRequestAdapter.java @@ -156,7 +156,70 @@ public class HttpRequestAdapter { } return null; } - + + public String postJson(String url,String jsonString,HashMap headers) { + // 创建httpClient实例 + CloseableHttpClient httpClient = HttpClients.createDefault(); + CloseableHttpResponse httpResponse = null; + // 创建httpPost远程连接实例 + HttpPost httpPost = new HttpPost(url); + // 配置请求参数实例 + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 设置连接主机服务超时时间 + .setConnectionRequestTimeout(35000)// 设置连接请求超时时间 + .setSocketTimeout(60000)// 设置读取数据连接超时时间 + .build(); + // 为httpPost实例设置配置 + httpPost.setConfig(requestConfig); + // 设置请求头 + if (null != headers && headers.size() > 0) { + Set> entrySet = headers.entrySet(); + // 循环遍历,获取迭代器 + Iterator> iterator = entrySet.iterator(); + while (iterator.hasNext()) { + Entry mapEntry = iterator.next(); + _logger.trace("Name " + mapEntry.getKey() + " , Value " +mapEntry.getValue()); + httpPost.addHeader(mapEntry.getKey(), mapEntry.getValue()); + } + } + + // 封装post请求参数 + StringEntity stringEntity =new StringEntity(jsonString, "UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + + + try { + // httpClient对象执行post请求,并返回响应参数对象 + httpResponse = httpClient.execute(httpPost); + // 从响应对象中获取响应内容 + HttpEntity entity = httpResponse.getEntity(); + String content = EntityUtils.toString(entity); + _logger.debug("Http Response StatusCode {} , Content {}", + httpResponse.getStatusLine().getStatusCode(), + content + ); + return content; + } catch (Exception e) { + e.printStackTrace(); + } finally { + // 关闭资源 + if (null != httpResponse) { + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != httpClient) { + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } public String get(String url) { HashMap headers = new HashMap(); diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/ConnectorsMapper.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/ConnectorsMapper.java new file mode 100644 index 000000000..0ce73cbd0 --- /dev/null +++ b/maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/ConnectorsMapper.java @@ -0,0 +1,33 @@ +/* + * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] + * + * 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 org.maxkey.persistence.mapper; + +import org.apache.mybatis.jpa.persistence.IJpaBaseMapper; +import org.maxkey.entity.Connectors; + +/** + * @author Crystal.sea + * + */ + +public interface ConnectorsMapper extends IJpaBaseMapper { + +} diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java index 4335c0324..7a8971166 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java +++ b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/AccountsService.java @@ -71,7 +71,7 @@ public class AccountsService extends JpaBaseService{ public boolean insert(Accounts account) { if (super.insert(account)) { - if(mqPersistService.getApplicationConfig().isMessageQueueSupport()) { + if(mqPersistService.getApplicationConfig().isProvisionSupport()) { UserInfo loadUserInfo = userInfoService.findUserRelated(account.getUserId()); account.setUserInfo(loadUserInfo); OrganizationsCast cast = new OrganizationsCast(); @@ -91,7 +91,7 @@ public class AccountsService extends JpaBaseService{ public boolean update(Accounts account) { if (super.update(account)) { - if(mqPersistService.getApplicationConfig().isMessageQueueSupport()) { + if(mqPersistService.getApplicationConfig().isProvisionSupport()) { UserInfo loadUserInfo = userInfoService.findUserRelated(account.getUserId()); account.setUserInfo(loadUserInfo); OrganizationsCast cast = new OrganizationsCast(); @@ -116,7 +116,7 @@ public class AccountsService extends JpaBaseService{ Accounts account = this.get(id); if (super.remove(id)) { UserInfo loadUserInfo = null; - if(mqPersistService.getApplicationConfig().isMessageQueueSupport()) { + if(mqPersistService.getApplicationConfig().isProvisionSupport()) { loadUserInfo = userInfoService.findUserRelated(account.getUserId()); account.setUserInfo(loadUserInfo); mqPersistService.send( diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/ConnectorsService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/ConnectorsService.java new file mode 100644 index 000000000..75f42e8d0 --- /dev/null +++ b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/ConnectorsService.java @@ -0,0 +1,42 @@ +/* + * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] + * + * 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 org.maxkey.persistence.service; + +import org.apache.mybatis.jpa.persistence.JpaBaseService; +import org.maxkey.entity.Connectors; +import org.maxkey.persistence.mapper.ConnectorsMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +@Repository +public class ConnectorsService extends JpaBaseService{ + final static Logger _logger = LoggerFactory.getLogger(ConnectorsService.class); + + public ConnectorsService() { + super(ConnectorsMapper.class); + } + + /* (non-Javadoc) + * @see com.connsec.db.service.BaseService#getMapper() + */ + @Override + public ConnectorsMapper getMapper() { + return (ConnectorsMapper)super.getMapper(); + } +} diff --git a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java index dd5e09d78..6aaf531f3 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java +++ b/maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java @@ -75,7 +75,7 @@ public class UserInfoService extends JpaBaseService { public boolean insert(UserInfo userInfo) { this.passwordEncoder(userInfo); if (super.insert(userInfo)) { - if(messageQueueService.getApplicationConfig().isMessageQueueSupport()) { + if(messageQueueService.getApplicationConfig().isProvisionSupport()) { UserInfo loadUserInfo = findUserRelated(userInfo.getId()); messageQueueService.send( ProvisionTopic.USERINFO_TOPIC, @@ -92,7 +92,7 @@ public class UserInfoService extends JpaBaseService { public boolean update(UserInfo userInfo) { ChangePassword changePassword = this.passwordEncoder(userInfo); if (super.update(userInfo)) { - if(messageQueueService.getApplicationConfig().isMessageQueueSupport()) { + if(messageQueueService.getApplicationConfig().isProvisionSupport()) { UserInfo loadUserInfo = findUserRelated(userInfo.getId()); accountUpdate(loadUserInfo); messageQueueService.send( @@ -110,7 +110,7 @@ public class UserInfoService extends JpaBaseService { public boolean delete(UserInfo userInfo) { UserInfo loadUserInfo = null; - if(messageQueueService.getApplicationConfig().isMessageQueueSupport()) { + if(messageQueueService.getApplicationConfig().isProvisionSupport()) { loadUserInfo = findUserRelated(userInfo.getId()); } diff --git a/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionMessage.java b/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionMessage.java index 0ecd96dc5..12b0752af 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionMessage.java +++ b/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionMessage.java @@ -25,6 +25,7 @@ public class ProvisionMessage { String sendTime; String content; int connected; + int instId; Object sourceObject; @@ -60,7 +61,7 @@ public class ProvisionMessage { this.id = id; } - public Object getContent() { + public String getContent() { return content; } @@ -84,6 +85,14 @@ public class ProvisionMessage { this.sourceObject = sourceObject; } + public int getInstId() { + return instId; + } + + public void setInstId(int instId) { + this.instId = instId; + } + public ProvisionMessage() { } diff --git a/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionService.java b/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionService.java index d72ff09fc..70298a56d 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionService.java +++ b/maxkey-persistence/src/main/java/org/maxkey/provision/ProvisionService.java @@ -46,7 +46,7 @@ public class ProvisionService { */ public void send(String topic,Object content,String actionType) { //maxkey.server.message.queue , if not none - if(applicationConfig.isMessageQueueSupport()) { + if(applicationConfig.isProvisionSupport()) { ProvisionMessage message = new ProvisionMessage( UUID.randomUUID().toString(), //message id as uuid @@ -58,7 +58,7 @@ public class ProvisionService { ); //sand msg to provision topic Thread thread = null; - if(applicationConfig.getMessageQueue().equalsIgnoreCase("provision")) { + if(applicationConfig.isProvisionSupport()) { _logger.trace("message..."); thread = new ProvisioningThread(jdbcTemplate,message); thread.start(); diff --git a/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunner.java b/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunner.java new file mode 100644 index 000000000..2668e00c9 --- /dev/null +++ b/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunner.java @@ -0,0 +1,205 @@ +package org.maxkey.provision.thread; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; + +import org.apache.mybatis.jpa.query.Query; +import org.maxkey.crypto.password.PasswordReciprocal; +import org.maxkey.entity.ChangePassword; +import org.maxkey.entity.Connectors; +import org.maxkey.entity.Message; +import org.maxkey.entity.Organizations; +import org.maxkey.entity.UserInfo; +import org.maxkey.persistence.service.ConnectorsService; +import org.maxkey.provision.ProvisionAction; +import org.maxkey.provision.ProvisionMessage; +import org.maxkey.provision.ProvisionTopic; +import org.maxkey.util.AuthorizationHeaderUtils; +import org.maxkey.util.DateUtils; +import org.maxkey.util.JsonUtils; +import org.maxkey.util.ObjectTransformer; +import org.maxkey.web.HttpRequestAdapter; +import org.maxkey.web.WebContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; + +public class ProvisioningRunner { + private static final Logger _logger = LoggerFactory.getLogger(ProvisioningRunner.class); + + static final String PROVISION_SELECT_STATEMENT = "select * from mxk_history_provisions where connected = 0 order by sendtime asc limit 500"; + + static final String PROVISION_UPDATE_STATEMENT = "update mxk_history_provisions set connected = connected + 1 where id = ?"; + + static final String PROVISION_LOG_INSERT_STATEMENT = "insert into mxk_history_connector(id,conname,topic,actiontype,sourceid,sourcename,synctime,result,instid) values (? , ? , ? , ? , ? , ? , ? , ? , ? )"; + + + JdbcTemplate jdbcTemplate; + + ConnectorsService connectorsService; + + public ProvisioningRunner(ConnectorsService connectorsService,JdbcTemplate jdbcTemplate) { + this.connectorsService = connectorsService; + this.jdbcTemplate = jdbcTemplate; + } + + + public void provisions() { + List listConnectors = connectorsService.query(new Query().eq("status", 1).eq("justintime", 1)); + List listProvisionMessage = jdbcTemplate.query(PROVISION_SELECT_STATEMENT, new ProvisionMessageRowMapper()); + for(ProvisionMessage msg : listProvisionMessage) { + for(Connectors connector: listConnectors) { + provision(msg,connector); + } + } + } + + public void provision(ProvisionMessage provisionMessage,Connectors connector) { + if(Integer.parseInt(connector.getInstId()) == provisionMessage.getInstId()) { + String url = connector.getProviderUrl(); + if(!url.endsWith("/")) { + url = url + "/"; + } + String resultMessage = ""; + String objectId = ""; + String objectName = ""; + if(provisionMessage.getTopic().equalsIgnoreCase(ProvisionTopic.USERINFO_TOPIC)) { + UserInfo user = (UserInfo)ObjectTransformer.deserialize(provisionMessage.getContent()); + user.setPassword(null); + user.setDecipherable(null); + objectId = user.getId(); + objectName = user.getDisplayName()+"("+user.getUsername()+")"; + resultMessage = provisionUser(user,url,provisionMessage.getActionType(),connector); + provisionLog( connector.getConnName(), + "Users", + provisionMessage.getActionType(), + objectId, + objectName, + resultMessage, + provisionMessage.getInstId() + ); + }else if(provisionMessage.getTopic().equalsIgnoreCase(ProvisionTopic.PASSWORD_TOPIC)) { + ChangePassword changePassword = (ChangePassword)ObjectTransformer.deserialize(provisionMessage.getContent()); + objectId = changePassword.getUserId(); + objectName = changePassword.getDisplayName()+"("+changePassword.getUsername()+")"; + resultMessage = provisionChangePassword(changePassword,url,provisionMessage.getActionType(),connector); + provisionLog( connector.getConnName(), + "Password", + provisionMessage.getActionType(), + objectId, + objectName, + resultMessage, + provisionMessage.getInstId() + ); + }else if(provisionMessage.getTopic().equalsIgnoreCase(ProvisionTopic.ORG_TOPIC)) { + Organizations organization = (Organizations)ObjectTransformer.deserialize(provisionMessage.getContent()); + objectId = organization.getId(); + objectName = organization.getOrgName(); + resultMessage = provisionOrganization(organization,url,provisionMessage.getActionType(),connector); + provisionLog( connector.getConnName(), + "Organizations", + provisionMessage.getActionType(), + objectId, + objectName, + resultMessage, + provisionMessage.getInstId() + ); + } + + jdbcTemplate.update(PROVISION_UPDATE_STATEMENT,provisionMessage.getId()); + } + } + + public void provisionLog(String conName,String topic,String actionType,String sourceId,String sourceName,String resultMessage,int instid) { + Message resultMsg = JsonUtils.json2Object(resultMessage, Message.class); + String result = "success"; + if(resultMsg == null || resultMsg.getCode() != 0) { + result = "fail"; + } + + jdbcTemplate.update(PROVISION_LOG_INSERT_STATEMENT, + WebContext.genId(), + conName, + topic, + actionType.replace("_ACTION", "").toLowerCase(), + sourceId, + sourceName, + DateUtils.getCurrentDateTimeAsString(), + result, + instid + ); + } + + public String getActionType(String actionType) { + if(actionType.equalsIgnoreCase(ProvisionAction.CREATE_ACTION)) { + return "create"; + }else if(actionType.equalsIgnoreCase(ProvisionAction.UPDATE_ACTION)) { + return "update"; + }else if(actionType.equalsIgnoreCase(ProvisionAction.DELETE_ACTION)) { + return "delete"; + } + return ""; + } + + String provisionUser(UserInfo user,String baseUrl,String actionType,Connectors connector){ + baseUrl = baseUrl + "Users/" + getActionType(actionType); + _logger.debug("URL {} ", baseUrl); + HashMap authorizationMap = AuthorizationHeaderUtils.authorization( + AuthorizationHeaderUtils.createBasic( + connector.getPrincipal(), + PasswordReciprocal.getInstance().decoder(connector.getCredentials())) + ); + + return new HttpRequestAdapter().postJson( baseUrl, + JsonUtils.gson2Json(user), + authorizationMap + ); + } + + String provisionOrganization(Organizations organizations,String baseUrl,String actionType,Connectors connector){ + baseUrl = baseUrl + "Organizations/"+ getActionType(actionType); + _logger.debug("URL {} ", baseUrl); + HashMap authorizationMap = AuthorizationHeaderUtils.authorization( + AuthorizationHeaderUtils.createBasic( + connector.getPrincipal(), + PasswordReciprocal.getInstance().decoder(connector.getCredentials())) + ); + + return new HttpRequestAdapter().postJson( baseUrl, + JsonUtils.gson2Json(organizations), + authorizationMap + ); + } + + String provisionChangePassword(ChangePassword changePassword,String baseUrl,String actionType,Connectors connector){ + baseUrl = baseUrl + "Users/changePassword"; + _logger.debug("URL {} ", baseUrl); + HashMap authorizationMap = AuthorizationHeaderUtils.authorization( + AuthorizationHeaderUtils.createBasic( + connector.getPrincipal(), + PasswordReciprocal.getInstance().decoder(connector.getCredentials())) + ); + + return new HttpRequestAdapter().postJson( baseUrl, + JsonUtils.gson2Json(changePassword), + authorizationMap + ); + } + + public class ProvisionMessageRowMapper implements RowMapper { + @Override + public ProvisionMessage mapRow(ResultSet rs, int rowNum) throws SQLException { + ProvisionMessage msg = new ProvisionMessage(); + msg.setId(rs.getString("id")); + msg.setActionType(rs.getString("actiontype")); + msg.setTopic(rs.getString("topic")); + msg.setContent(rs.getString("content")); + msg.setConnected(rs.getInt("connected")); + msg.setInstId(rs.getInt("instid")); + return msg; + } + } +} diff --git a/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunnerThread.java b/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunnerThread.java new file mode 100644 index 000000000..f534c55f7 --- /dev/null +++ b/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningRunnerThread.java @@ -0,0 +1,23 @@ +package org.maxkey.provision.thread; + +public class ProvisioningRunnerThread extends Thread{ + + ProvisioningRunner runner; + + public ProvisioningRunnerThread(ProvisioningRunner runner) { + super(); + this.runner = runner; + } + + @Override + public void run() { + while(true) { + try { + Thread.sleep(60 * 1000); + runner.provisions(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningThread.java b/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningThread.java index 236ad392f..8cdfe0de3 100644 --- a/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningThread.java +++ b/maxkey-persistence/src/main/java/org/maxkey/provision/thread/ProvisioningThread.java @@ -21,6 +21,7 @@ import java.sql.Types; import org.maxkey.pretty.impl.JsonPretty; import org.maxkey.provision.ProvisionMessage; +import org.maxkey.util.JsonUtils; import org.maxkey.util.ObjectTransformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +34,7 @@ import org.springframework.jdbc.core.JdbcTemplate; public class ProvisioningThread extends Thread{ private static final Logger _logger = LoggerFactory.getLogger(ProvisioningThread.class); - static final String PROVISION_INSERT_STATEMENT = "insert into mxk_history_provisions(`id`,`topic`,`actiontype`,`content`,`sendtime`,`connected`) values (? , ? , ? , ? , ? , ? )"; + static final String PROVISION_INSERT_STATEMENT = "insert into mxk_history_provisions(id,topic,actiontype,content,sendtime,connected,instid) values (? , ? , ? , ? , ? , ? , ? )"; JdbcTemplate jdbcTemplate; @@ -49,15 +50,31 @@ public class ProvisioningThread extends Thread{ public void run() { _logger.debug("send message \n{}" ,new JsonPretty().jacksonFormat(msg.getSourceObject())); msg.setContent(ObjectTransformer.serialize((Serializable)msg.getSourceObject())); + Inst inst = JsonUtils.gson2Object(JsonUtils.gson2Json(msg.getSourceObject()), Inst.class); jdbcTemplate.update(PROVISION_INSERT_STATEMENT, new Object[] { msg.getId(), msg.getTopic(), msg.getActionType(), msg.getContent(), - msg.getSendTime(),msg.getConnected() + msg.getSendTime(),msg.getConnected(),inst.getInstId() }, new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, - Types.TINYINT + Types.TINYINT,Types.TINYINT }); _logger.debug("send to Message Queue finished ."); } + + class Inst{ + + int instId; + + public int getInstId() { + return instId; + } + + public void setInstId(int instId) { + this.instId = instId; + } + + public Inst() {} + } } diff --git a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ConnectorsMapper.xml b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ConnectorsMapper.xml new file mode 100644 index 000000000..0e1264210 --- /dev/null +++ b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ConnectorsMapper.xml @@ -0,0 +1,25 @@ + + + + + + + and id = #{id} + + + and connname like '%${connName}%' + + + + + + + \ No newline at end of file diff --git a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryConnectorMapper.xml b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryConnectorMapper.xml index 6b2dbbd0d..b275f3773 100644 --- a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryConnectorMapper.xml +++ b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryConnectorMapper.xml @@ -11,10 +11,6 @@ and conName = #{conName} - - and conType = #{conType} - - and sourceId = #{sourceId} diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/entity/Connectors.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/entity/Connectors.ts new file mode 100644 index 000000000..81b4b08b0 --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/entity/Connectors.ts @@ -0,0 +1,66 @@ +/* + * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] + * + * 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. + */ + +import format from 'date-fns/format'; + +import { BaseEntity } from './BaseEntity'; + +export class Connectors extends BaseEntity { + connName!: String; + justInTime!: Number; + filters!: String; + scheduler!: String; + providerUrl!: String; + principal!: String; + credentials!: String; + + switch_justInTime: boolean = true; + + constructor() { + super(); + this.status = 1; + this.justInTime = 1; + } + + override init(data: any): void { + Object.assign(this, data); + if (this.status == 1) { + this.switch_status = true; + } else { + this.switch_status = false; + } + + if (this.justInTime == 1) { + this.switch_justInTime = true; + } else { + this.switch_justInTime = false; + } + } + + override trans(): void { + if (this.switch_status) { + this.status = 1; + } else { + this.status = 0; + } + + if (this.switch_justInTime) { + this.justInTime = 1; + } else { + this.justInTime = 0; + } + } +} diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.html b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.html index 4b455e939..75633241f 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.html +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.html @@ -5,23 +5,19 @@
- {{ 'mxk.users.username' | i18n }} + {{ 'mxk.history.connector.conName' | i18n }} - +
- {{ 'mxk.users.displayName' | i18n }} + {{ 'mxk.history.connector.sourceName' | i18n }} - +
@@ -29,13 +25,8 @@ {{ 'mxk.users.employeeNumber' | i18n }} - +
@@ -43,14 +34,9 @@ {{ 'mxk.text.startDate' | i18n }} - + + @@ -58,54 +44,37 @@ {{ 'mxk.text.endDate' | i18n }} - + +
- + + {{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}
- + {{ 'mxk.history.connector.id' | i18n }} {{ 'mxk.history.connector.conName' | i18n }} - {{ 'mxk.history.connector.conType' | i18n }} + {{ 'mxk.history.connector.topic' | i18n }} + {{ 'mxk.history.connector.actionType' | i18n }} {{ 'mxk.history.connector.sourceId' | i18n }} {{ 'mxk.history.connector.sourceName' | i18n }} - {{ 'mxk.history.connector.objectId' | i18n }} - {{ 'mxk.history.connector.objectName' | i18n }} {{ 'mxk.history.connector.syncTime' | i18n }} {{ 'mxk.history.connector.result' | i18n }} @@ -116,14 +85,13 @@ {{ data.id }} {{ data.conName }} - {{ data.conType }} + {{ data.topic }} + {{ data.actionType }} {{ data.sourceId }} - {{ data.syncName }} {{ data.sourceName }} - {{ data.objectName }} {{ data.syncTime }} {{ data.result }} - + \ No newline at end of file diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.ts index c351f88b7..5272969aa 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.ts +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-connector/audit-connector.component.ts @@ -1,19 +1,18 @@ /* * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] - * + * * 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. */ - import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @@ -33,8 +32,8 @@ import { HistoryService } from '../../../service/history.service'; export class AuditConnectorComponent implements OnInit { query: { params: { - username: String; - displayName: String; + conName: String; + sourceName: String; employeeNumber: String; startDate: String; endDate: String; @@ -53,8 +52,8 @@ export class AuditConnectorComponent implements OnInit { tableLoading: boolean; } = { params: { - username: '', - displayName: '', + conName: '', + sourceName: '', employeeNumber: '', startDate: '', endDate: '', diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-logins/audit-logins.component.html b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-logins/audit-logins.component.html index 1f788d85a..ff8e6858b 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-logins/audit-logins.component.html +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-logins/audit-logins.component.html @@ -7,7 +7,8 @@ {{ 'mxk.users.username' | i18n }} - + @@ -15,13 +16,8 @@ {{ 'mxk.users.displayName' | i18n }} - + @@ -29,13 +25,8 @@ {{ 'mxk.users.employeeNumber' | i18n }} - + @@ -43,14 +34,9 @@ {{ 'mxk.text.startDate' | i18n }} - + + @@ -58,45 +44,29 @@ {{ 'mxk.text.endDate' | i18n }} - + +
- + + {{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}
- + {{ 'mxk.history.login.sessionId' | i18n }} @@ -128,4 +98,4 @@ - + \ No newline at end of file diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.html b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.html index 349f5f9fe..f5bb1763c 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.html +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.html @@ -5,23 +5,19 @@
- {{ 'mxk.users.username' | i18n }} + {{ 'mxk.history.synchronizer.syncName' | i18n }} - +
- {{ 'mxk.users.displayName' | i18n }} + {{ 'mxk.history.synchronizer.objectName' | i18n }} - +
@@ -29,13 +25,8 @@ {{ 'mxk.users.employeeNumber' | i18n }} - +
@@ -43,14 +34,9 @@ {{ 'mxk.text.startDate' | i18n }} - + + @@ -58,45 +44,29 @@ {{ 'mxk.text.endDate' | i18n }} - + +
- + + {{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}
- + {{ 'mxk.history.synchronizer.syncId' | i18n }} @@ -122,4 +92,4 @@ - + \ No newline at end of file diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.ts index 8a7aa7c5b..88a477d84 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.ts +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/audit/audit-synchronizer/audit-synchronizer.component.ts @@ -1,19 +1,18 @@ /* * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] - * + * * 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. */ - import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @@ -33,8 +32,8 @@ import { HistoryService } from '../../../service/history.service'; export class AuditSynchronizerComponent implements OnInit { query: { params: { - username: String; - displayName: String; + syncName: String; + objectName: String; employeeNumber: String; startDate: String; endDate: String; @@ -53,8 +52,8 @@ export class AuditSynchronizerComponent implements OnInit { tableLoading: boolean; } = { params: { - username: '', - displayName: '', + syncName: '', + objectName: '', employeeNumber: '', startDate: '', endDate: '', diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/config.module.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/config.module.ts index 079eef0fb..bb0c1db3e 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/config.module.ts +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/config.module.ts @@ -1,19 +1,18 @@ /* * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] - * + * * 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. */ - import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -34,6 +33,8 @@ import { SelectAccountsStrategyComponent } from './accounts-strategy/select-acco import { AdapterEditerComponent } from './adapters/adapter-editer/adapter-editer.component'; import { AdaptersComponent } from './adapters/adapters.component'; import { SelectAdaptersComponent } from './adapters/select-adapters/select-adapters.component'; +import { ConnectorEditerComponent } from './connectors/connector-editer/connector-editer.component'; +import { ConnectorsComponent } from './connectors/connectors.component'; import { EmailSendersComponent } from './email-senders/email-senders.component'; import { InstitutionsComponent } from './institutions/institutions.component'; import { LdapContextComponent } from './ldap-context/ldap-context.component'; @@ -74,6 +75,10 @@ const routes: Routes = [ path: 'synchronizers', component: SynchronizersComponent }, + { + path: 'connectors', + component: ConnectorsComponent + }, { path: 'accountsstrategys', component: AccountsStrategyComponent @@ -108,7 +113,9 @@ const COMPONENTS = [PasswordPolicyComponent, EmailSendersComponent, LdapContextC InstitutionsComponent, NoticesComponent, SelectAccountsStrategyComponent, - SelectAdaptersComponent + SelectAdaptersComponent, + ConnectorsComponent, + ConnectorEditerComponent ], imports: [SharedModule, CommonModule, RouterModule.forChild(routes)], exports: [RouterModule] diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.html b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.html new file mode 100644 index 000000000..d8bfde75b --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.html @@ -0,0 +1,81 @@ +
{{ isEdit ? ('mxk.text.edit' | i18n) : ('mxk.text.add' | i18n) }}
+
+
+ + {{ 'mxk.text.id' | i18n }} + + + + + + {{ 'mxk.connectors.connName' | i18n }} + + + + + + {{ 'mxk.connectors.justInTime' | i18n }} + + + + + + + + + + {{ 'mxk.connectors.scheduler' | i18n }} + + + + + + + {{ 'mxk.connectors.providerUrl' | i18n + }} + + + + + + {{ 'mxk.connectors.principal' | i18n }} + + + + + + + {{ 'mxk.connectors.credentials' | i18n + }} + + + + + + {{ 'mxk.text.status' | i18n }} + + + + + + + +
+
+ +
+ + +
\ No newline at end of file diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.less b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.less new file mode 100644 index 000000000..e69de29bb diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.spec.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.spec.ts new file mode 100644 index 000000000..c67f5bdde --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConnectorEditerComponent } from './connector-editer.component'; + +describe('ConnectorEditerComponent', () => { + let component: ConnectorEditerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConnectorEditerComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConnectorEditerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.ts new file mode 100644 index 000000000..974572a6d --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connector-editer/connector-editer.component.ts @@ -0,0 +1,91 @@ +/* + * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] + * + * 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. + */ + +import { Component, ChangeDetectorRef, Input, OnInit, Inject } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { I18NService } from '@core'; +import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme'; +import format from 'date-fns/format'; +import { NzMessageService } from 'ng-zorro-antd/message'; +import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'; + +import { Connectors } from '../../../../entity/Connectors'; +import { ConnectorsService } from '../../../../service/connectors.service'; + +@Component({ + selector: 'app-connector-editer', + templateUrl: './connector-editer.component.html', + styleUrls: ['./connector-editer.component.less'], + styles: [ + ` + nz-form-item { + width: 100%; + } + ` + ] +}) +export class ConnectorEditerComponent implements OnInit { + @Input() id?: String; + @Input() isEdit?: boolean; + form: { + submitting: boolean; + model: Connectors; + } = { + submitting: false, + model: new Connectors() + }; + + formGroup: FormGroup = new FormGroup({}); + + constructor( + private modalRef: NzModalRef, + private connectorsService: ConnectorsService, + private fb: FormBuilder, + private msg: NzMessageService, + @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + if (this.isEdit) { + this.connectorsService.get(`${this.id}`).subscribe(res => { + this.form.model.init(res.data); + this.cdr.detectChanges(); + }); + } + } + + onClose(e: MouseEvent): void { + e.preventDefault(); + this.modalRef.destroy({ refresh: false }); + } + + onSubmit(e: MouseEvent): void { + e.preventDefault(); + this.form.submitting = true; + this.form.model.trans(); + (this.isEdit ? this.connectorsService.update(this.form.model) : this.connectorsService.add(this.form.model)).subscribe(res => { + if (res.code == 0) { + this.msg.success(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.success' : 'mxk.alert.add.success')); + } else { + this.msg.error(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.error' : 'mxk.alert.add.error')); + } + this.form.submitting = false; + this.modalRef.destroy({ refresh: true }); + this.cdr.detectChanges(); + }); + } +} diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.html b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.html new file mode 100644 index 000000000..01bea2b2b --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.html @@ -0,0 +1,75 @@ + + + +
+
+
+ + {{ 'mxk.connectors.connName' | i18n }} + + + + +
+ +
+ + + +
+
+
+
+ +
+ + +
+ + + + + Id + {{ 'mxk.connectors.connName' | i18n }} + {{ 'mxk.connectors.justInTime' | i18n }} + {{ 'mxk.text.status' | i18n }} + {{ 'mxk.text.action' | i18n }} + + + + + + + {{ data.id }} + + + {{ data.connName }} + {{ 'mxk.text.yes' | i18n }} + {{ 'mxk.text.no' | i18n }} + + +
+ + +
+ + + +
+
\ No newline at end of file diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.less b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.less new file mode 100644 index 000000000..e69de29bb diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.spec.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.spec.ts new file mode 100644 index 000000000..2ea027045 --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConnectorsComponent } from './connectors.component'; + +describe('ConnectorsComponent', () => { + let component: ConnectorsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConnectorsComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConnectorsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.ts new file mode 100644 index 000000000..b4e5e3502 --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/config/connectors/connectors.component.ts @@ -0,0 +1,203 @@ +import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit, Inject } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { I18NService } from '@core'; +import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme'; +import { format, addDays } from 'date-fns'; +import { NzSafeAny } from 'ng-zorro-antd/core/types'; +import { NzMessageService } from 'ng-zorro-antd/message'; +import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'; +import { NzTableQueryParams } from 'ng-zorro-antd/table'; + +import { ConnectorsService } from '../../../service/connectors.service'; +import { set2String } from '../../../shared/index'; +import { ConnectorEditerComponent } from './connector-editer/connector-editer.component'; + +@Component({ + selector: 'app-connectors', + templateUrl: './connectors.component.html', + styleUrls: ['./connectors.component.less'] +}) +export class ConnectorsComponent implements OnInit { + query: { + params: { + connName: String; + displayName: String; + protocol: String; + startDate: String; + endDate: String; + startDatePicker: Date; + endDatePicker: Date; + pageSize: number; + pageNumber: number; + pageSizeOptions: number[]; + }; + results: { + records: number; + rows: NzSafeAny[]; + }; + expandForm: Boolean; + submitLoading: boolean; + tableLoading: boolean; + tableCheckedId: Set; + indeterminate: boolean; + checked: boolean; + } = { + params: { + connName: '', + displayName: '', + protocol: '', + startDate: '', + endDate: '', + startDatePicker: addDays(new Date(), -30), + endDatePicker: new Date(), + pageSize: 10, + pageNumber: 1, + pageSizeOptions: [10, 20, 50] + }, + results: { + records: 0, + rows: [] + }, + expandForm: false, + submitLoading: false, + tableLoading: false, + tableCheckedId: new Set(), + indeterminate: false, + checked: false + }; + + constructor( + private modalService: NzModalService, + private connectorsService: ConnectorsService, + private viewContainerRef: ViewContainerRef, + private fb: FormBuilder, + private msg: NzMessageService, + @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.fetch(); + } + + onQueryParamsChange(tableQueryParams: NzTableQueryParams): void { + this.query.params.pageNumber = tableQueryParams.pageIndex; + this.query.params.pageSize = tableQueryParams.pageSize; + this.fetch(); + } + + onSearch(): void { + this.fetch(); + } + + onReset(): void { } + + onBatchDelete(e: MouseEvent): void { + e.preventDefault(); + this.connectorsService.delete(set2String(this.query.tableCheckedId)).subscribe(res => { + if (res.code == 0) { + this.msg.success(this.i18n.fanyi('mxk.alert.delete.success')); + this.fetch(); + } else { + this.msg.error(this.i18n.fanyi('mxk.alert.delete.error')); + } + this.cdr.detectChanges(); + }); + } + + onAdd(e: MouseEvent): void { + e.preventDefault(); + const modal = this.modalService.create({ + nzContent: ConnectorEditerComponent, + nzViewContainerRef: this.viewContainerRef, + nzComponentParams: { + isEdit: false, + id: '' + }, + nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000)) + }); + // Return a result when closed + modal.afterClose.subscribe(result => { + if (result.refresh) { + this.fetch(); + } + }); + } + + onEdit(e: MouseEvent, editId: String): void { + e.preventDefault(); + const modal = this.modalService.create({ + nzContent: ConnectorEditerComponent, + nzViewContainerRef: this.viewContainerRef, + nzComponentParams: { + isEdit: true, + id: editId + }, + nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000)) + }); + // Return a result when closed + modal.afterClose.subscribe(result => { + if (result.refresh) { + this.fetch(); + } + }); + } + + onDelete(e: MouseEvent, deleteId: String): void { + e.preventDefault(); + this.connectorsService.delete(deleteId).subscribe(res => { + if (res.code == 0) { + this.msg.success(this.i18n.fanyi('mxk.alert.delete.success')); + this.fetch(); + } else { + this.msg.error(this.i18n.fanyi('mxk.alert.delete.error')); + } + this.cdr.detectChanges(); + }); + } + + fetch(): void { + this.query.submitLoading = true; + this.query.tableLoading = true; + this.query.indeterminate = false; + this.query.checked = false; + this.query.tableCheckedId.clear(); + if (this.query.expandForm) { + this.query.params.endDate = format(this.query.params.endDatePicker, 'yyyy-MM-dd HH:mm:ss'); + this.query.params.startDate = format(this.query.params.startDatePicker, 'yyyy-MM-dd HH:mm:ss'); + } else { + this.query.params.endDate = ''; + this.query.params.startDate = ''; + } + this.connectorsService.fetch(this.query.params).subscribe(res => { + this.query.results = res.data; + this.query.submitLoading = false; + this.query.tableLoading = false; + this.cdr.detectChanges(); + }); + } + + updateTableCheckedSet(id: String, checked: boolean): void { + if (checked) { + this.query.tableCheckedId.add(id); + } else { + this.query.tableCheckedId.delete(id); + } + } + + refreshTableCheckedStatus(): void { + const listOfEnabledData = this.query.results.rows.filter(({ disabled }) => !disabled); + this.query.checked = listOfEnabledData.every(({ id }) => this.query.tableCheckedId.has(id)); + this.query.indeterminate = listOfEnabledData.some(({ id }) => this.query.tableCheckedId.has(id)) && !this.query.checked; + } + + onTableItemChecked(id: String, checked: boolean): void { + this.updateTableCheckedSet(id, checked); + this.refreshTableCheckedStatus(); + } + + onTableAllChecked(checked: boolean): void { + this.query.results.rows.filter(({ disabled }) => !disabled).forEach(({ id }) => this.updateTableCheckedSet(id, checked)); + this.refreshTableCheckedStatus(); + } +} diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/connectors.service.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/connectors.service.ts new file mode 100644 index 000000000..54efef875 --- /dev/null +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/connectors.service.ts @@ -0,0 +1,33 @@ +/* + * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] + * + * 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. + */ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { NzSafeAny } from 'ng-zorro-antd/core/types'; +import { Observable } from 'rxjs'; + +import { Connectors } from '../entity/Connectors'; +import { Message } from '../entity/Message'; +import { BaseService } from './base.service'; + +@Injectable({ + providedIn: 'root' +}) +export class ConnectorsService extends BaseService { + constructor(private _httpClient: HttpClient) { + super(_httpClient, '/config/connectors'); + } +} diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/synchronizers.service.ts b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/synchronizers.service.ts index dd2c77308..b66a5c35d 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/synchronizers.service.ts +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/app/service/synchronizers.service.ts @@ -1,19 +1,18 @@ /* * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] - * + * * 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. */ - import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/app-data.json b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/app-data.json index 656e65cda..1abb3a3b4 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/app-data.json +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/app-data.json @@ -117,13 +117,6 @@ "icon": "anticon-idcard", "children": [] }, - { - "text": "社交服务", - "i18n": "mxk.menu.config.socialsproviders", - "link": "/config/socialsproviders", - "icon": "anticon-comment", - "children": [] - }, { "text": "同步器管理", "i18n": "mxk.menu.config.synchronizers", @@ -131,6 +124,20 @@ "icon": "anticon-partition", "children": [] }, + { + "text": "连接器管理", + "i18n": "mxk.menu.config.connectors", + "link": "/config/connectors", + "icon": "anticon-api", + "children": [] + }, + { + "text": "社交服务", + "i18n": "mxk.menu.config.socialsproviders", + "link": "/config/socialsproviders", + "icon": "anticon-comment", + "children": [] + }, { "text": "LDAP配置", "i18n": "mxk.menu.config.ldapcontext", @@ -188,6 +195,13 @@ "icon": "anticon-audit", "children": [] }, + { + "text": "连接器日志", + "i18n": "mxk.menu.audit.connector", + "link": "/audit/audit-connector", + "icon": "anticon-audit", + "children": [] + }, { "text": "管理日志", "i18n": "mxk.menu.audit.operate", diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/en-US.json b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/en-US.json index 0ed95b5a7..4e966a709 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/en-US.json +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/en-US.json @@ -45,6 +45,7 @@ "accountsstrategys": "Strategys", "socialsproviders": "Socials", "synchronizers": "Synchronizers", + "connectors":"Connectors", "adapters": "Adapters", "notices": "Notices", "ldapcontext": "LDAP", @@ -537,6 +538,15 @@ "resumeTime": "Join Time", "suspendTime": "Suspend Time" }, + "connectors": { + "connName": "Name", + "scheduler": "Scheduler", + "justInTime":"JustInTime", + "providerUrl": "ProviderUrl", + "principal": "Principal", + "credentials": "Credentials", + "filters": "Filters" + }, "password": { "id": "Id", "displayName": "DisplayName", @@ -610,7 +620,8 @@ "connector.id": "Id", "connector.conName": "Connector", - "connector.conType": "Type", + "connector.topic": "Topic", + "connector.actionType": "ActionType", "connector.sourceId": "SourceId", "connector.sourceName": "SourceName", "connector.objectId": "ObjectId", diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-CN.json b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-CN.json index 5b05ffbca..f53afe64f 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-CN.json +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-CN.json @@ -45,6 +45,7 @@ "accountsstrategys": "账号策略", "socialsproviders": "社交服务", "synchronizers": "同步器管理", + "connectors":"连接器管理", "adapters": "适配器注册", "notices": "通知公告", "ldapcontext": "LDAP配置", @@ -535,6 +536,15 @@ "resumeTime": "执行时间", "suspendTime": "挂起时间" }, + "connectors": { + "connName": "名称", + "scheduler": "定时任务", + "justInTime":"实时同步", + "providerUrl": "地址", + "principal": "账号", + "credentials": "凭证", + "filters": "过滤条件" + }, "password": { "id": "用户编码", "displayName": "姓名", @@ -608,7 +618,8 @@ "connector.id": "编号", "connector.conName": "连接器", - "connector.conType": "类型", + "connector.topic": "主题", + "connector.actionType": "操作", "connector.sourceId": "源编码", "connector.sourceName": "源名称", "connector.objectId": "对象编号", diff --git a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-TW.json b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-TW.json index 3623f467d..bbef89fa6 100644 --- a/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-TW.json +++ b/maxkey-web-frontend/maxkey-web-mgt-app/src/assets/i18n/zh-TW.json @@ -46,6 +46,7 @@ "accountsstrategys": "賬號策略", "socialsproviders": "社交服務", "synchronizers": "同步器管理", + "connectors":"連接器管理", "adapters": "適配器註冊", "notices": "通知公告", "ldapcontext": "LDAP配置", @@ -536,6 +537,15 @@ "resumeTime": "執行時間", "suspendTime": "掛起時間" }, + "connectors": { + "connName": "名稱", + "scheduler": "定時任務", + "justInTime":"實时同步", + "providerUrl": "地址", + "principal": "賬號", + "credentials": "憑證", + "filters": "過濾條件" + }, "password": { "id": "用戶編碼", "displayName": "姓名", @@ -609,7 +619,8 @@ "connector.id": "編號", "connector.conName": "連接器", - "connector.conType": "類型", + "connector.topic": "主題", + "connector.actionType": "操作", "connector.sourceId": "源編碼", "connector.sourceName": "源名稱", "connector.objectId": "對象編號", diff --git a/maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyMvcConfig.java b/maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyMvcConfig.java index cd1df0a3d..d7f02d8d2 100644 --- a/maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyMvcConfig.java +++ b/maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyMvcConfig.java @@ -106,7 +106,7 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer { //addPathPatterns 用于添加拦截规则 , 先把所有路径都加入拦截, 再一个个排除 //excludePathPatterns 表示改路径不用拦截 - _logger.debug("add HttpKerberosEntryPoint"); + _logger.debug("add Http Kerberos Entry Point"); registry.addInterceptor(new HttpKerberosEntryPoint( authenticationProvider,kerberosService,applicationConfig,true)) .addPathPatterns("/login"); @@ -115,13 +115,13 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer { if(httpHeaderEnable) { registry.addInterceptor(new HttpHeaderEntryPoint(httpHeaderName,httpHeaderEnable)) .addPathPatterns("/*"); - _logger.debug("add HttpHeaderEntryPoint"); + _logger.debug("add Http Header Entry Point"); } if(basicEnable) { registry.addInterceptor(new BasicEntryPoint(basicEnable)) .addPathPatterns("/*"); - _logger.debug("add BasicEntryPoint"); + _logger.debug("add Basic Entry Point"); } //for frontend diff --git a/maxkey-webs/maxkey-web-maxkey/src/main/resources/application-http.properties b/maxkey-webs/maxkey-web-maxkey/src/main/resources/application-http.properties index 8a45c5d5a..ec64b0938 100644 --- a/maxkey-webs/maxkey-web-maxkey/src/main/resources/application-http.properties +++ b/maxkey-webs/maxkey-web-maxkey/src/main/resources/application-http.properties @@ -44,8 +44,8 @@ maxkey.server.authz.uri =${maxkey.server.name}:${server. maxkey.server.frontend.uri =/maxkey #InMemory 0 , Redis 2 maxkey.server.persistence =${SERVER_PERSISTENCE:0} -#identity none, provision -maxkey.server.message.queue =${SERVER_MESSAGE_QUEUE:none} +#identity true,false +maxkey.server.provision =${SERVER_PROVISION:false} #issuer name maxkey.app.issuer =CN=ConSec,CN=COM,CN=SH #must > jwt expire * 2 diff --git a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtListenerConfig.java b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtListenerConfig.java index 6d7937ae8..8449d3e5a 100644 --- a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtListenerConfig.java +++ b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtListenerConfig.java @@ -18,11 +18,15 @@ package org.maxkey; import org.maxkey.authn.session.SessionManager; +import org.maxkey.configuration.ApplicationConfig; import org.maxkey.listener.DynamicRolesListenerAdapter; import org.maxkey.listener.ListenerAdapter; import org.maxkey.listener.ListenerParameter; import org.maxkey.listener.SessionListenerAdapter; +import org.maxkey.persistence.service.ConnectorsService; import org.maxkey.persistence.service.RolesService; +import org.maxkey.provision.thread.ProvisioningRunner; +import org.maxkey.provision.thread.ProvisioningRunnerThread; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.slf4j.Logger; @@ -31,6 +35,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; @Configuration public class MaxKeyMgtListenerConfig implements InitializingBean { @@ -69,6 +74,23 @@ public class MaxKeyMgtListenerConfig implements InitializingBean { return "dynamicRolesListenerAdapter"; } + @Bean + public String provisioningRunnerThread( + ConnectorsService connectorsService, + JdbcTemplate jdbcTemplate, + ApplicationConfig applicationConfig + ) throws SchedulerException { + if(applicationConfig.isProvisionSupport()) { + ProvisioningRunner runner = new ProvisioningRunner(connectorsService,jdbcTemplate); + ProvisioningRunnerThread runnerThread = new ProvisioningRunnerThread(runner); + runnerThread.start(); + _logger.debug("provisioning Runner Thread ."); + }else { + _logger.debug("not need init provisioning Runner Thread ."); + } + return "provisioningRunnerThread"; + } + @Override public void afterPropertiesSet() throws Exception { diff --git a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java index 4cb72da38..4fbdeb4f9 100644 --- a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java +++ b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java @@ -84,7 +84,7 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { //addPathPatterns 用于添加拦截规则 , 先把所有路径都加入拦截, 再一个个排除 //excludePathPatterns 表示改路径不用拦截 - _logger.debug("add HttpJwtEntryPoint"); + _logger.debug("add Interceptors"); permissionInterceptor.setMgmt(true); @@ -118,7 +118,7 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer { .addPathPatterns("/logout/**") ; - _logger.debug("add PermissionAdapter"); + _logger.debug("add Permission Adapter"); registry.addInterceptor(historyLogsAdapter) .addPathPatterns("/userinfo/**") @@ -131,7 +131,7 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer { .addPathPatterns("/apps/**") .addPathPatterns("/approles/**") ; - _logger.debug("add HistoryLogsAdapter"); + _logger.debug("add History Logs Adapter"); /* * api @@ -144,7 +144,7 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer { .addPathPatterns("/api/idm/scim/**") ; - _logger.debug("add RestApiPermissionAdapter"); + _logger.debug("add Rest Api Permission Adapter"); } diff --git a/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/config/contorller/ConnectorsController.java b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/config/contorller/ConnectorsController.java new file mode 100644 index 000000000..3a02a1ef5 --- /dev/null +++ b/maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/config/contorller/ConnectorsController.java @@ -0,0 +1,105 @@ +/* + * Copyright [2022] [MaxKey of copyright http://www.maxkey.top] + * + * 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 org.maxkey.web.config.contorller; + +import org.apache.commons.lang3.StringUtils; +import org.apache.mybatis.jpa.persistence.JpaPageResults; +import org.maxkey.authn.annotation.CurrentUser; +import org.maxkey.crypto.password.PasswordReciprocal; +import org.maxkey.entity.Connectors; +import org.maxkey.entity.Message; +import org.maxkey.entity.UserInfo; +import org.maxkey.persistence.service.ConnectorsService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping(value={"/config/connectors"}) +public class ConnectorsController { + final static Logger _logger = LoggerFactory.getLogger(ConnectorsController.class); + + @Autowired + ConnectorsService connectorsService; + + @RequestMapping(value = { "/fetch" }, produces = {MediaType.APPLICATION_JSON_VALUE}) + @ResponseBody + public ResponseEntity fetch(Connectors connector,@CurrentUser UserInfo currentUser) { + _logger.debug(""+connector); + connector.setInstId(currentUser.getInstId()); + return new Message>( + connectorsService.queryPageResults(connector)).buildResponse(); + } + + @RequestMapping(value = { "/get/{id}" }, produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity get(@PathVariable("id") String id) { + Connectors connector = connectorsService.get(id); + if(StringUtils.isNotBlank(connector.getCredentials())) { + connector.setCredentials(PasswordReciprocal.getInstance().decoder(connector.getCredentials())); + } + return new Message(connector).buildResponse(); + } + + @ResponseBody + @RequestMapping(value={"/add"}, produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity insert(@RequestBody Connectors connector,@CurrentUser UserInfo currentUser) { + _logger.debug("-Add :" + connector); + connector.setInstId(currentUser.getInstId()); + if(StringUtils.isNotBlank(connector.getCredentials())) { + connector.setCredentials(PasswordReciprocal.getInstance().encode(connector.getCredentials())); + } + if (connectorsService.insert(connector)) { + return new Message(Message.SUCCESS).buildResponse(); + } else { + return new Message(Message.FAIL).buildResponse(); + } + } + + @ResponseBody + @RequestMapping(value={"/update"}, produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity update(@RequestBody Connectors connector,@CurrentUser UserInfo currentUser) { + _logger.debug("-update :" + connector); + connector.setInstId(currentUser.getInstId()); + connector.setCredentials(PasswordReciprocal.getInstance().encode(connector.getCredentials())); + if (connectorsService.update(connector)) { + return new Message(Message.SUCCESS).buildResponse(); + } else { + return new Message(Message.FAIL).buildResponse(); + } + } + + @ResponseBody + @RequestMapping(value={"/delete"}, produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity delete(@RequestParam("ids") String ids,@CurrentUser UserInfo currentUser) { + _logger.debug("-delete ids : {} " , ids); + if (connectorsService.deleteBatch(ids)) { + return new Message(Message.SUCCESS).buildResponse(); + } else { + return new Message(Message.FAIL).buildResponse(); + } + } + +} diff --git a/maxkey-webs/maxkey-web-mgt/src/main/resources/application-http.properties b/maxkey-webs/maxkey-web-mgt/src/main/resources/application-http.properties index 53556ec52..1199e6da2 100644 --- a/maxkey-webs/maxkey-web-mgt/src/main/resources/application-http.properties +++ b/maxkey-webs/maxkey-web-mgt/src/main/resources/application-http.properties @@ -33,8 +33,8 @@ maxkey.server.mgt.uri =${maxkey.server.uri} maxkey.server.authz.uri =https://${maxkey.server.domain}/maxkey #InMemory 0 , Redis 2 maxkey.server.persistence =0 -#identity none, provision -maxkey.server.message.queue =${SERVER_MESSAGE_QUEUE:none} +#identity true,false +maxkey.server.provision =${SERVER_PROVISION:false} maxkey.session.timeout =${SERVER_SESSION_TIMEOUT:1800}