diff --git a/.deps/taobao-sdk-java-auto_1479188381469-20210716.jar b/.deps/taobao-sdk-java-auto_1479188381469-20210716.jar new file mode 100644 index 000000000..86b363dae Binary files /dev/null and b/.deps/taobao-sdk-java-auto_1479188381469-20210716.jar differ diff --git a/@rbv b/@rbv index 276e88e13..1536f8a9f 160000 --- a/@rbv +++ b/@rbv @@ -1 +1 @@ -Subproject commit 276e88e1327caf8f6dcc9b08c16ba7b67010e396 +Subproject commit 1536f8a9f00c61b7868bb16b898b980a61218c5f diff --git a/pom.xml b/pom.xml index 9d9ab14a8..e7799c130 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.4.2 + 2.5.2 com.rebuild @@ -42,7 +42,7 @@ com.github.eirslett frontend-maven-plugin - 1.11.0 + 1.12.0 install node and npm @@ -223,10 +223,11 @@ true --> + org.springframework spring-context-support - 5.3.3 + 5.3.9 @@ -282,17 +283,17 @@ com.alibaba druid - 1.2.2 + 1.2.6 mysql mysql-connector-java - 8.0.23 + 8.0.25 net.sf.ehcache ehcache - 2.10.6 + 2.10.9.2 redis.clients @@ -302,7 +303,7 @@ com.qiniu qiniu-java-sdk - 7.4.0 + 7.8.0 com.github.whvcse @@ -317,12 +318,12 @@ org.jsoup jsoup - 1.13.1 + 1.14.1 com.hankcs hanlp - portable-1.7.8 + portable-1.8.2 com.vladsch.flexmark @@ -342,7 +343,7 @@ com.alibaba easyexcel - 2.2.8 + 2.2.10 ehcache @@ -388,17 +389,17 @@ com.googlecode.aviator aviator - 5.2.3 + 5.2.6 net.coobird thumbnailator - 0.4.13 + 0.4.14 es.moki.ratelimitj ratelimitj-inmemory - 0.6.0 + 0.7.0 com.google.zxing @@ -408,7 +409,7 @@ org.redisson redisson - 3.15.0 + 3.16.0 org.apache.commons @@ -418,7 +419,17 @@ com.github.oshi oshi-core - 5.7.0 + 5.8.0 + + + + local + dingtalk-sdk + 20210719 + system + ${basedir}/.deps/taobao-sdk-java-auto_1479188381469-20210716.jar + + diff --git a/src/main/java/com/rebuild/api/user/AuthTokenManager.java b/src/main/java/com/rebuild/api/user/AuthTokenManager.java index 28e5598c4..4d9d98046 100644 --- a/src/main/java/com/rebuild/api/user/AuthTokenManager.java +++ b/src/main/java/com/rebuild/api/user/AuthTokenManager.java @@ -40,7 +40,7 @@ public class AuthTokenManager { public static String generateToken(ID user, int expires) { String token = String.format("%s,%d,%s,v1", user, System.currentTimeMillis(), CodecUtils.randomCode(10)); - token = CodecUtils.base64UrlEncode(token); + token = CodecUtils.base64UrlEncode(token); // 64bit Application.getCommonsCache().putx(TOKEN_PREFIX + token, user, expires); return token; } diff --git a/src/main/java/com/rebuild/api/user/LoginToken.java b/src/main/java/com/rebuild/api/user/LoginToken.java index 00d96cbcf..ccff6d272 100644 --- a/src/main/java/com/rebuild/api/user/LoginToken.java +++ b/src/main/java/com/rebuild/api/user/LoginToken.java @@ -58,7 +58,7 @@ public class LoginToken extends BaseApi { * * @param user * @param password - * @return + * @return 返回 null 表示成功 */ public static String checkUser(String user, String password) { if (!Application.getUserStore().existsUser(user)) { diff --git a/src/main/java/com/rebuild/core/BootEnvironmentPostProcessor.java b/src/main/java/com/rebuild/core/BootEnvironmentPostProcessor.java index 144ad0229..7c0ed0101 100644 --- a/src/main/java/com/rebuild/core/BootEnvironmentPostProcessor.java +++ b/src/main/java/com/rebuild/core/BootEnvironmentPostProcessor.java @@ -155,9 +155,11 @@ public class BootEnvironmentPostProcessor implements EnvironmentPostProcessor, I */ public static String getProperty(String name, String defaultValue) { String value = null; - if (ConfigurationItem.DataDirectory.name().equalsIgnoreCase(name)) { + if (ConfigurationItem.DataDirectory.name().equalsIgnoreCase(name) + || ConfigurationItem.MobileUrl.name().equalsIgnoreCase(name)) { value = StringUtils.defaultIfBlank( - System.getProperty("DataDirectory"), System.getProperty(V2_PREFIX + "DataDirectory")); + System.getProperty(name), System.getProperty(V2_PREFIX + name)); + } else if (ENV_HOLD != null) { if (!(name.startsWith(V2_PREFIX) || name.contains("."))) { name = V2_PREFIX + name; diff --git a/src/main/java/com/rebuild/core/configuration/general/ClassificationService.java b/src/main/java/com/rebuild/core/configuration/general/ClassificationService.java index 0b7bef0a1..bb130464a 100644 --- a/src/main/java/com/rebuild/core/configuration/general/ClassificationService.java +++ b/src/main/java/com/rebuild/core/configuration/general/ClassificationService.java @@ -20,6 +20,7 @@ import com.rebuild.core.privileges.UserService; import com.rebuild.core.service.DataSpecificationException; import com.rebuild.core.service.general.QuickCodeReindexTask; import com.rebuild.core.support.i18n.Language; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; @@ -29,6 +30,7 @@ import org.springframework.stereotype.Service; * @author devezhao zhaofang123@gmail.com * @since 2019/04/10 */ +@Slf4j @Service public class ClassificationService extends BaseConfigurationService implements AdminGuard { @@ -87,7 +89,7 @@ public class ClassificationService extends BaseConfigurationService implements A } finally { long cost = System.currentTimeMillis() - start; if (cost > 2000 || Application.devMode()) { - LOG.info("Reindex FullName [ " + itemId + " ] in " + cost + " ms"); + log.info("Reindex FullName [ {} ] in {} ms", itemId, cost); } } }); diff --git a/src/main/java/com/rebuild/core/metadata/EntityHelper.java b/src/main/java/com/rebuild/core/metadata/EntityHelper.java index 7e967feb0..8f3807120 100644 --- a/src/main/java/com/rebuild/core/metadata/EntityHelper.java +++ b/src/main/java/com/rebuild/core/metadata/EntityHelper.java @@ -177,6 +177,7 @@ public class EntityHelper { public static final int RoleMember = 5; public static final int Team = 6; public static final int TeamMember = 7; + public static final int ExternalUser = 8; // 配置 diff --git a/src/main/java/com/rebuild/core/metadata/impl/MetaEntityService.java b/src/main/java/com/rebuild/core/metadata/impl/MetaEntityService.java index 0ad3bb6c4..1975a7eb6 100644 --- a/src/main/java/com/rebuild/core/metadata/impl/MetaEntityService.java +++ b/src/main/java/com/rebuild/core/metadata/impl/MetaEntityService.java @@ -17,6 +17,7 @@ import com.rebuild.core.metadata.MetadataHelper; import com.rebuild.core.privileges.AdminGuard; import com.rebuild.core.service.BaseService; import com.rebuild.core.service.ServiceSpec; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** @@ -25,6 +26,7 @@ import org.springframework.stereotype.Service; * @author zhaofang123@gmail.com * @since 08/03/2018 */ +@Slf4j @Service public class MetaEntityService extends BaseService implements AdminGuard { @@ -76,7 +78,8 @@ public class MetaEntityService extends BaseService implements AdminGuard { } if (usedArray.length > 0) { - LOG.warn("deleted configuration of entity [ " + delEntity.getName() + " ] in [ " + conf + " ] : " + usedArray.length); + log.warn("Deleted configuration of entity [ {} ] in [ {} ] : {}", + delEntity.getName(), conf, usedArray.length); } } diff --git a/src/main/java/com/rebuild/core/metadata/impl/MetaFieldService.java b/src/main/java/com/rebuild/core/metadata/impl/MetaFieldService.java index 9a29651b8..b7ebe81fb 100644 --- a/src/main/java/com/rebuild/core/metadata/impl/MetaFieldService.java +++ b/src/main/java/com/rebuild/core/metadata/impl/MetaFieldService.java @@ -19,6 +19,7 @@ import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.metadata.MetadataHelper; import com.rebuild.core.privileges.AdminGuard; import com.rebuild.core.service.BaseService; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** @@ -27,6 +28,7 @@ import org.springframework.stereotype.Service; * @author zhaofang123@gmail.com * @since 08/03/2018 */ +@Slf4j @Service public class MetaFieldService extends BaseService implements AdminGuard { @@ -70,7 +72,8 @@ public class MetaFieldService extends BaseService implements AdminGuard { } if (usedArray.length > 0) { - LOG.warn("deleted configuration of field [ " + field.getOwnEntity().getName() + "." + field.getName() + " ] in [ " + who + " ] : " + usedArray.length); + log.warn("Deleted configuration of field [ {}.{} ] in [ {} ] : {}", + field.getOwnEntity().getName(), field.getName(), who, usedArray.length); if ("PickList".equals(who)) { PickListManager.instance.clean(field); diff --git a/src/main/java/com/rebuild/core/privileges/UserService.java b/src/main/java/com/rebuild/core/privileges/UserService.java index 7a9f5e85c..1c1d78a5e 100644 --- a/src/main/java/com/rebuild/core/privileges/UserService.java +++ b/src/main/java/com/rebuild/core/privileges/UserService.java @@ -34,6 +34,7 @@ import com.rebuild.core.support.task.TaskExecutors; import com.rebuild.utils.AppUtils; import com.rebuild.utils.BlockList; import com.rebuild.utils.CommonsUtils; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; @@ -46,6 +47,7 @@ import java.util.Map; * @author zhaofang123@gmail.com * @since 07/25/2018 */ +@Slf4j @Service public class UserService extends BaseServiceImpl { @@ -155,7 +157,7 @@ public class UserService extends BaseServiceImpl { try { UserHelper.generateAvatar(record.getString("fullName"), true); } catch (Exception ex) { - LOG.error(null, ex); + log.error(null, ex); } } } @@ -381,7 +383,7 @@ public class UserService extends BaseServiceImpl { newUserId); content += String.format("[%s](%s)", Language.L("点击开始激活"), viewUrl); - Message message = MessageBuilder.createMessage(ADMIN_USER, content, newUserId); + Message message = MessageBuilder.createMessage(ADMIN_USER, content, Message.TYPE_DEFAULT, newUserId); Application.getNotifications().send(message); return newUserId; diff --git a/src/main/java/com/rebuild/core/service/BaseService.java b/src/main/java/com/rebuild/core/service/BaseService.java index c0654bca5..9580f8a85 100644 --- a/src/main/java/com/rebuild/core/service/BaseService.java +++ b/src/main/java/com/rebuild/core/service/BaseService.java @@ -11,8 +11,6 @@ import cn.devezhao.persist4j.PersistManagerFactory; import cn.devezhao.persist4j.Record; import cn.devezhao.persist4j.engine.ID; import com.rebuild.core.Application; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * 基础服务类 @@ -22,8 +20,6 @@ import org.slf4j.LoggerFactory; */ public abstract class BaseService implements ServiceSpec { - protected final Logger LOG = LoggerFactory.getLogger(getClass()); - private final PersistManagerFactory aPMFactory; protected BaseService(PersistManagerFactory aPMFactory) { diff --git a/src/main/java/com/rebuild/core/service/notification/MessageBuilder.java b/src/main/java/com/rebuild/core/service/notification/MessageBuilder.java index d29c076da..6d0b186e8 100644 --- a/src/main/java/com/rebuild/core/service/notification/MessageBuilder.java +++ b/src/main/java/com/rebuild/core/service/notification/MessageBuilder.java @@ -30,11 +30,10 @@ public class MessageBuilder { /** * @param toUser * @param message - * @param recordId * @return */ - public static Message createMessage(ID toUser, String message, ID recordId) { - return new Message(null, toUser, message, recordId, Message.TYPE_DEFAULT); + public static Message createMessage(ID toUser, String message) { + return new Message(null, toUser, message, null, Message.TYPE_DEFAULT); } /** @@ -50,22 +49,22 @@ public class MessageBuilder { /** * @param toUser * @param message - * @param type - * @param recordId + * @param relatedRecord * @return */ - public static Message createMessage(ID toUser, String message, int type, ID recordId) { - return new Message(null, toUser, message, recordId, type); + public static Message createApproval(ID toUser, String message, ID relatedRecord) { + return new Message(null, toUser, message, relatedRecord, Message.TYPE_APPROVAL); } /** * @param toUser * @param message - * @param recordId + * @param type + * @param relatedRecord * @return */ - public static Message createApproval(ID toUser, String message, ID recordId) { - return new Message(null, toUser, message, recordId, Message.TYPE_APPROVAL); + public static Message createMessage(ID toUser, String message, int type, ID relatedRecord) { + return new Message(null, toUser, message, relatedRecord, type); } // -- diff --git a/src/main/java/com/rebuild/core/service/notification/MessageDistributor.java b/src/main/java/com/rebuild/core/service/notification/MessageDistributor.java new file mode 100644 index 000000000..7e80a34af --- /dev/null +++ b/src/main/java/com/rebuild/core/service/notification/MessageDistributor.java @@ -0,0 +1,26 @@ +/* +Copyright (c) REBUILD and/or its owners. All rights reserved. + +rebuild is dual-licensed under commercial and open source licenses (GPLv3). +See LICENSE and COMMERCIAL in the project root for license information. +*/ + +package com.rebuild.core.service.notification; + +import cn.devezhao.persist4j.engine.ID; + +/** + * 消息分发 + * + * @author devezhao + * @since 2021/7/20 + */ +public interface MessageDistributor { + + /** + * @param message + * @param messageId + * @return + */ + boolean send(Message message, ID messageId); +} diff --git a/src/main/java/com/rebuild/core/service/notification/NotificationService.java b/src/main/java/com/rebuild/core/service/notification/NotificationService.java index f8ed18205..cb54d91e8 100644 --- a/src/main/java/com/rebuild/core/service/notification/NotificationService.java +++ b/src/main/java/com/rebuild/core/service/notification/NotificationService.java @@ -8,12 +8,15 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.core.service.notification; import cn.devezhao.commons.ObjectUtils; +import cn.devezhao.commons.ThreadPool; import cn.devezhao.persist4j.PersistManagerFactory; import cn.devezhao.persist4j.Record; import cn.devezhao.persist4j.engine.ID; import com.rebuild.core.Application; +import com.rebuild.core.UserContextHolder; import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.service.BaseService; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** @@ -22,6 +25,7 @@ import org.springframework.stereotype.Service; * @author devezhao * @since 10/17/2018 */ +@Slf4j @Service public class NotificationService extends BaseService { @@ -66,6 +70,8 @@ public class NotificationService extends BaseService { } } + // -- + /** * 发送消息 * @@ -82,10 +88,27 @@ public class NotificationService extends BaseService { if (message.getRelatedRecord() != null) { record.setID("relatedRecord", message.getRelatedRecord()); } - this.create(record); + + record = this.create(record); + + // 分发消息 + final ID messageId = record.getPrimary(); + ThreadPool.exec(() -> { + String[] mdNames = Application.getContext().getBeanNamesForType(MessageDistributor.class); + for (String md : mdNames) { + try { + boolean s = ((MessageDistributor) Application.getContext().getBean(md)).send(message, messageId); + log.info("Distribute message : {} >> {}", messageId, s); + } catch (Exception ex) { + log.error("Distribute message failed : {}", messageId, ex); + } + } + }); } /** + * 获取未读消息数 + * * @param user * @return */ @@ -104,4 +127,15 @@ public class NotificationService extends BaseService { Application.getCommonsCache().putx(ckey, count); return count; } + + /** + * 设为已读 + * + * @param messageId + */ + public void makeRead(ID messageId) { + Record record = EntityHelper.forUpdate(messageId, UserContextHolder.getUser()); + record.setBoolean("unread", false); + this.update(record); + } } diff --git a/src/main/java/com/rebuild/core/service/trigger/impl/SendNotification.java b/src/main/java/com/rebuild/core/service/trigger/impl/SendNotification.java index 38533cffb..066322905 100644 --- a/src/main/java/com/rebuild/core/service/trigger/impl/SendNotification.java +++ b/src/main/java/com/rebuild/core/service/trigger/impl/SendNotification.java @@ -20,6 +20,7 @@ import com.rebuild.core.service.trigger.ActionContext; import com.rebuild.core.service.trigger.ActionType; import com.rebuild.core.service.trigger.TriggerAction; import com.rebuild.core.support.general.ContentWithFieldVars; +import com.rebuild.core.support.i18n.Language; import com.rebuild.core.support.integration.SMSender; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; @@ -85,7 +86,8 @@ public class SendNotification implements TriggerAction { String message = content.getString("content"); message = ContentWithFieldVars.replaceWithRecord(message, context.getSourceRecord()); - String emailSubject = StringUtils.defaultIfBlank(content.getString("title"), "你有一条新通知"); + String emailSubject = content.getString("title"); + if (StringUtils.isBlank(emailSubject)) emailSubject = Language.L("你有一条新通知"); for (ID user : toUsers) { if (type == TYPE_MAIL) { @@ -101,7 +103,7 @@ public class SendNotification implements TriggerAction { } } else { // TYPE_NOTIFICATION - Message m = MessageBuilder.createMessage(user, message, context.getSourceRecord()); + Message m = MessageBuilder.createMessage(user, message, Message.TYPE_DEFAULT, context.getSourceRecord()); Application.getNotifications().send(m); } } diff --git a/src/main/java/com/rebuild/core/support/ConfigurationItem.java b/src/main/java/com/rebuild/core/support/ConfigurationItem.java index 2880a3c0a..5382fc5dd 100644 --- a/src/main/java/com/rebuild/core/support/ConfigurationItem.java +++ b/src/main/java/com/rebuild/core/support/ConfigurationItem.java @@ -17,10 +17,12 @@ import com.rebuild.core.support.i18n.LanguageBundle; */ public enum ConfigurationItem { + // 仅命令行指定 + DataDirectory, // 数据目录 + MobileUrl, // 移动端地址 + // 系统指定 SN, DBVer, AppBuild, - // 数据目录(命令行指定) - DataDirectory, // 缓存服务(安装/配置文件指定) CacheHost, CachePort, CacheUser, CachePassword, @@ -89,6 +91,12 @@ public enum ConfigurationItem { // 登录密码过期时间 PasswordExpiredDays(0), + // DingTalk + DingtalkAgentid, DingtalkAppkey, DingtalkAppsecret, DingtalkCorpid, + DingtalkPushAeskey, DingtalkPushToken, + // WxWork + WxworkCorpid, WxworkAgentid, WxworkSecret + ; private Object defaultVal; diff --git a/src/main/java/com/rebuild/core/support/DataMasking.java b/src/main/java/com/rebuild/core/support/DataMasking.java index 5ba7dfda7..613cdd11a 100644 --- a/src/main/java/com/rebuild/core/support/DataMasking.java +++ b/src/main/java/com/rebuild/core/support/DataMasking.java @@ -36,7 +36,7 @@ public class DataMasking { int starLen = textLen - len3 * 2; return text.substring(0, len3) + StringUtils.repeat("*", Math.min(starLen, 20)) - + text.substring(len3 * 2); + + text.substring(textLen - len3 * 2); } } diff --git a/src/main/java/com/rebuild/core/support/RebuildConfiguration.java b/src/main/java/com/rebuild/core/support/RebuildConfiguration.java index 09f57a717..56c52b2df 100644 --- a/src/main/java/com/rebuild/core/support/RebuildConfiguration.java +++ b/src/main/java/com/rebuild/core/support/RebuildConfiguration.java @@ -7,6 +7,7 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.core.support; +import com.rebuild.core.BootEnvironmentPostProcessor; import com.rebuild.core.RebuildException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; @@ -145,17 +146,33 @@ public class RebuildConfiguration extends KVStorage { */ public static String getHomeUrl(String path) { String homeUrl = get(ConfigurationItem.HomeURL); - if (!homeUrl.endsWith("/")) { - homeUrl += "/"; + if (path != null) homeUrl = joinPath(homeUrl, path); + else if (!homeUrl.endsWith("/")) homeUrl += "/"; + return homeUrl; + } + + /** + * 获取绝对 URL H5 + * + * @param path + * @return + * @see #getHomeUrl(String) + */ + public static String getMobileUrl(String path) { + String mobileUrl = BootEnvironmentPostProcessor.getProperty(ConfigurationItem.MobileUrl.name()); + if (mobileUrl != null) { + return path == null ? mobileUrl : joinPath(mobileUrl, path); } - if (path != null) { - if (path.startsWith("/")) { - path = path.substring(1); - } - return homeUrl + path; - } - return homeUrl; + mobileUrl = "/h5app/"; + if (path != null) mobileUrl = joinPath(mobileUrl, path); + return getHomeUrl(mobileUrl); + } + + static String joinPath(String path1, String path2) { + if (path1.endsWith("/")) path1 = path1.substring(0, path1.length() - 1); + if (path2.startsWith("/")) path2 = path2.substring(1); + return path1 + "/" + path2; } /** @@ -203,6 +220,15 @@ public class RebuildConfiguration extends KVStorage { return s == null ? (Integer) name.getDefaultValue() : NumberUtils.toInt(s); } + /** + * @param name + * @return + */ + public static long getLong(ConfigurationItem name) { + String s = get(name); + return s == null ? (Long) name.getDefaultValue() : NumberUtils.toLong(s); + } + /** * @param name * @return diff --git a/src/main/java/com/rebuild/utils/AppUtils.java b/src/main/java/com/rebuild/utils/AppUtils.java index 27482bb87..9fbe7f306 100644 --- a/src/main/java/com/rebuild/utils/AppUtils.java +++ b/src/main/java/com/rebuild/utils/AppUtils.java @@ -11,6 +11,8 @@ import cn.devezhao.commons.ThrowableUtils; import cn.devezhao.commons.web.ServletUtils; import cn.devezhao.commons.web.WebUtils; import cn.devezhao.persist4j.engine.ID; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; import com.rebuild.api.user.AuthTokenManager; import com.rebuild.core.Application; import com.rebuild.core.BootApplication; @@ -222,4 +224,15 @@ public class AppUtils { String ua = request.getHeader("user-agent"); return ua != null && ua.contains("Trident/") && ua.contains("rv:11."); } + + /** + * 是否移动端 + * + * @param request + * @return + */ + public static boolean isMobile(HttpServletRequest request) { + UserAgent ua = UserAgentUtil.parse(request.getHeader("user-agent")); + return ua != null && ua.isMobile(); + } } diff --git a/src/main/java/com/rebuild/utils/HttpUtils.java b/src/main/java/com/rebuild/utils/HttpUtils.java index 5d2f04566..d39063b13 100644 --- a/src/main/java/com/rebuild/utils/HttpUtils.java +++ b/src/main/java/com/rebuild/utils/HttpUtils.java @@ -7,13 +7,11 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.utils; +import com.alibaba.fastjson.JSON; import com.rebuild.core.Application; import com.rebuild.core.support.RebuildConfiguration; import lombok.extern.slf4j.Slf4j; -import okhttp3.FormBody; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; +import okhttp3.*; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.springframework.http.HttpHeaders; @@ -95,35 +93,47 @@ public class HttpUtils { * POST * * @param url - * @param formData + * @param reqData * @return * @throws IOException */ - public static String post(String url, Map formData) throws IOException { - return post(url, formData, null); + public static String post(String url, Object reqData) throws IOException { + return post(url, reqData, null); } /** * POST with Headers * * @param url - * @param formData + * @param reqData * @param headers * @return * @throws IOException */ - public static String post(String url, Map formData, Map headers) throws IOException { - FormBody.Builder formBuilder = new FormBody.Builder(); - if (formData != null && !formData.isEmpty()) { - for (Map.Entry e : formData.entrySet()) { + public static String post(String url, Object reqData, Map headers) throws IOException { + RequestBody requestBody; + + // JSON + if (reqData instanceof JSON) { + requestBody = RequestBody.create(((JSON) reqData).toJSONString(), MediaType.parse("application/json")); + } + // Map + else if (reqData instanceof Map) { + FormBody.Builder formBuilder = new FormBody.Builder(); + for (Map.Entry e : ((Map) reqData).entrySet()) { Object v = e.getValue(); - formBuilder.add(e.getKey(), v == null ? StringUtils.EMPTY : v.toString()); + formBuilder.add(e.getKey().toString(), v == null ? StringUtils.EMPTY : v.toString()); } + requestBody = formBuilder.build(); + } + // Text + else { + requestBody = RequestBody.create(reqData.toString(), MediaType.parse("text/plain")); } Request.Builder builder = new Request.Builder().url(url); Request request = useHeaders(builder, headers) - .post(formBuilder.build()) + .post(requestBody) .build(); long ms = System.currentTimeMillis(); diff --git a/src/main/java/com/rebuild/web/admin/ConfigurationController.java b/src/main/java/com/rebuild/web/admin/ConfigurationController.java index 015c8f15c..63f4fd938 100644 --- a/src/main/java/com/rebuild/web/admin/ConfigurationController.java +++ b/src/main/java/com/rebuild/web/admin/ConfigurationController.java @@ -25,6 +25,7 @@ import com.rebuild.core.support.i18n.Language; import com.rebuild.core.support.integration.QiniuCloud; import com.rebuild.core.support.integration.SMSender; import com.rebuild.utils.JSONUtils; +import com.rebuild.utils.RbAssert; import com.rebuild.web.BaseController; import com.rebuild.web.RebuildWebConfigurer; import lombok.extern.slf4j.Slf4j; @@ -275,4 +276,69 @@ public class ConfigurationController extends BaseController { } } } + + // DingTalk + + @GetMapping("integration/dingtalk") + public ModelAndView pageIntegrationDingtalk() { + RbAssert.isCommercial( + Language.L("免费版不支持钉钉集成 [(查看详情)](https://getrebuild.com/docs/rbv-features)")); + + ModelAndView mv = createModelAndView("/admin/integration/dingtalk"); + for (ConfigurationItem item : ConfigurationItem.values()) { + String name = item.name(); + if (name.startsWith("Dingtalk")) { + String value = RebuildConfiguration.get(item); + + if (value != null && item == ConfigurationItem.DingtalkAppsecret) { + value = DataMasking.masking(value); + } + mv.getModel().put(name, value); + } + } + + String homeUrl = RebuildConfiguration.getHomeUrl("/user/dingtalk"); + mv.getModel().put("_DingtalkHomeUrl", homeUrl); + + return mv; + } + + @PostMapping("integration/dingtalk") + public RespBody postIntegrationDingtalk(@RequestBody JSONObject data) { + setValues(data); + return RespBody.ok(); + } + + // WxWork + + @GetMapping("integration/wxwork") + public ModelAndView pageIntegrationWxwork() { + RbAssert.isCommercial( + Language.L("免费版不支持企业微信集成 [(查看详情)](https://getrebuild.com/docs/rbv-features)")); + + ModelAndView mv = createModelAndView("/admin/integration/wxwork"); + for (ConfigurationItem item : ConfigurationItem.values()) { + String name = item.name(); + if (name.startsWith("Wxwork")) { + String value = RebuildConfiguration.get(item); + + if (value != null && item == ConfigurationItem.WxworkSecret) { + value = DataMasking.masking(value); + } + mv.getModel().put(name, value); + } + } + + String homeUrl = RebuildConfiguration.getHomeUrl("/user/wxwork"); + mv.getModel().put("_WxworkHomeUrl", homeUrl); + mv.getModel().put("_WxworkAuthCallUrl", homeUrl.split("//")[1].split("/")[0]); + + return mv; + } + + @PostMapping("integration/wxwork") + public RespBody postIntegrationWxwork(@RequestBody JSONObject data) { + setValues(data); + return RespBody.ok(); + } } diff --git a/src/main/java/com/rebuild/web/commons/CommonPageView.java b/src/main/java/com/rebuild/web/commons/CommonPageView.java index 76df81c89..75be1e995 100644 --- a/src/main/java/com/rebuild/web/commons/CommonPageView.java +++ b/src/main/java/com/rebuild/web/commons/CommonPageView.java @@ -8,8 +8,12 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.web.commons; import cn.devezhao.commons.web.ServletUtils; +import com.rebuild.core.support.License; +import com.rebuild.core.support.RebuildConfiguration; +import com.rebuild.utils.AppUtils; import com.rebuild.utils.CommonsUtils; import com.rebuild.web.BaseController; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.servlet.ModelAndView; @@ -27,8 +31,12 @@ import java.io.IOException; public class CommonPageView extends BaseController { @GetMapping("/") - public void index(HttpServletResponse response) throws IOException { - response.sendRedirect("user/login"); + public void index(HttpServletRequest request, HttpServletResponse response) throws IOException { + if (AppUtils.isMobile(request) && License.isRbvAttached()) { + response.sendRedirect(RebuildConfiguration.getMobileUrl("/")); + } else { + response.sendRedirect("user/login"); + } } @GetMapping("/*.txt") @@ -39,7 +47,7 @@ public class CommonPageView extends BaseController { String content = CommonsUtils.getStringOfRes("web/" + url); if (content == null) { - response.sendError(404); + response.sendError(HttpStatus.NOT_FOUND.value()); } else { ServletUtils.setContentType(response, ServletUtils.CT_PLAIN); ServletUtils.write(response, content); diff --git a/src/main/java/com/rebuild/web/commons/RbvMissingController.java b/src/main/java/com/rebuild/web/commons/RbvMissingController.java index 0652f14c9..4ecefb33b 100644 --- a/src/main/java/com/rebuild/web/commons/RbvMissingController.java +++ b/src/main/java/com/rebuild/web/commons/RbvMissingController.java @@ -9,6 +9,7 @@ package com.rebuild.web.commons; import com.rebuild.core.support.i18n.Language; import com.rebuild.web.BaseController; +import com.rebuild.web.WebConstants; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -24,7 +25,9 @@ public class RbvMissingController extends BaseController { @GetMapping({"/h5app/**"}) public ModelAndView pageH5app() { - return ErrorPageView.createErrorPage( + ModelAndView mv = ErrorPageView.createErrorPage( Language.L("免费版不支持手机访问功能 [(查看详情)](https://getrebuild.com/docs/rbv-features)")); + mv.getModelMap().put(WebConstants.$BUNDLE, Language.getCurrentBundle()); + return mv; } } diff --git a/src/main/java/com/rebuild/web/general/ListAndViewRedirection.java b/src/main/java/com/rebuild/web/general/ListAndViewRedirection.java index 6fc4979cc..a55675a00 100644 --- a/src/main/java/com/rebuild/web/general/ListAndViewRedirection.java +++ b/src/main/java/com/rebuild/web/general/ListAndViewRedirection.java @@ -31,7 +31,8 @@ import java.text.MessageFormat; @Controller public class ListAndViewRedirection extends BaseController { - @GetMapping("/app/list-and-view") + // H5: "/app/redirect" + @GetMapping({ "/app/list-and-view", "/app/redirect" }) public void redirect(@IdParam ID anyId, HttpServletResponse response) throws IOException { String url = null; diff --git a/src/main/java/com/rebuild/web/notification/NotificationController.java b/src/main/java/com/rebuild/web/notification/NotificationController.java index 8dc1bc054..22fb83323 100644 --- a/src/main/java/com/rebuild/web/notification/NotificationController.java +++ b/src/main/java/com/rebuild/web/notification/NotificationController.java @@ -7,16 +7,15 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.web.notification; -import cn.devezhao.persist4j.Record; import cn.devezhao.persist4j.engine.ID; import com.alibaba.fastjson.JSON; import com.rebuild.api.RespBody; import com.rebuild.core.Application; -import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.privileges.UserHelper; import com.rebuild.core.service.approval.ApprovalState; import com.rebuild.core.service.notification.MessageBuilder; import com.rebuild.core.support.i18n.I18nUtils; +import com.rebuild.core.support.i18n.Language; import com.rebuild.utils.JSONUtils; import com.rebuild.web.BaseController; import org.springframework.web.bind.annotation.GetMapping; @@ -25,6 +24,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; import java.util.Date; /** @@ -60,8 +60,9 @@ public class NotificationController extends BaseController { if ("ALL".equalsIgnoreCase(ids)) { Object[][] unreads = Application.createQueryNoFilter( - "select messageId from Notification where toUser = ?") + "select messageId from Notification where toUser = ? and unread = ?") .setParameter(1, user) + .setParameter(2, true) .array(); StringBuilder sb = new StringBuilder(); @@ -71,13 +72,9 @@ public class NotificationController extends BaseController { ids = sb.toString(); } - for (String id : ids.split(",")) { - if (!ID.isId(id)) continue; - - Record record = EntityHelper.forUpdate(ID.valueOf(id), user); - record.setBoolean("unread", false); - Application.getNotifications().update(record); - } + Arrays.stream(ids.split(",")) + .filter(ID::isId) + .forEach(id -> Application.getNotifications().makeRead(ID.valueOf(id))); return RespBody.ok(); } @@ -141,19 +138,20 @@ public class NotificationController extends BaseController { .setParameter(1, approvalStep) .unique(); if (stepState == null) { - m[3] = new Object[]{0}; + m[3] = new Object[] { 0 }; } else { - boolean canceled = (Boolean) stepState[0]; ApprovalState state = (ApprovalState) ApprovalState.valueOf((Integer) stepState[1]); if (state == ApprovalState.DRAFT) { - m[3] = canceled ? new Object[]{2, "已处理"} : new Object[]{1, "待处理"}; + boolean canceled = (Boolean) stepState[0]; + m[3] = canceled + ? new Object[] { 2, Language.L("已处理") } + : new Object[] { 1, Language.L("待处理") }; } else if (state == ApprovalState.APPROVED) { - m[3] = new Object[]{10, "已同意"}; + m[3] = new Object[] { 10, Language.L("已同意") }; } else if (state == ApprovalState.REJECTED) { - m[3] = new Object[]{11, "已驳回"}; + m[3] = new Object[] { 11, Language.L("已驳回") }; } } - array[i] = m; } diff --git a/src/main/java/com/rebuild/web/user/UserSettings.java b/src/main/java/com/rebuild/web/user/UserSettings.java index 414779b6e..965bac4f9 100644 --- a/src/main/java/com/rebuild/web/user/UserSettings.java +++ b/src/main/java/com/rebuild/web/user/UserSettings.java @@ -15,7 +15,10 @@ import com.rebuild.api.RespBody; import com.rebuild.core.Application; import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.privileges.UserService; +import com.rebuild.core.privileges.bizz.User; import com.rebuild.core.service.DataSpecificationException; +import com.rebuild.core.support.ConfigurationItem; +import com.rebuild.core.support.RebuildConfiguration; import com.rebuild.core.support.VerfiyCode; import com.rebuild.core.support.i18n.I18nUtils; import com.rebuild.core.support.i18n.Language; @@ -41,7 +44,25 @@ public class UserSettings extends EntityController { @GetMapping("/user") public ModelAndView pageUser(HttpServletRequest request) { ModelAndView mv = createModelAndView("/settings/user-settings"); - mv.getModelMap().put("user", Application.getUserStore().getUser(getRequestUser(request))); + + User user = Application.getUserStore().getUser(getRequestUser(request)); + mv.getModelMap().put("user", user); + + if (RebuildConfiguration.get(ConfigurationItem.DingtalkCorpid) != null) { + Object[] dingtalkUser = Application.createQueryNoFilter( + "select appUser from ExternalUser where bindUser = ? and appType = 1") + .setParameter(1, user.getId()) + .unique(); + if (dingtalkUser != null) mv.getModelMap().put("dingtalkUser", dingtalkUser[0]); + } + if (RebuildConfiguration.get(ConfigurationItem.WxworkCorpid) != null) { + Object[] wxworkUser = Application.createQueryNoFilter( + "select appUser from ExternalUser where bindUser = ? and appType = 2") + .setParameter(1, user.getId()) + .unique(); + if (wxworkUser != null) mv.getModelMap().put("wxworkUser", wxworkUser[0]); + } + return mv; } @@ -146,4 +167,19 @@ public class UserSettings extends EntityController { } return RespBody.ok(); } + + @PostMapping("/cancel-external-user") + public RespBody cancelExternalUser(HttpServletRequest request) { + int appType = getIntParameter(request, "type", 0); + Object[] externalUser = Application.createQueryNoFilter( + "select userId from ExternalUser where bindUser = ? and appType = ?") + .setParameter(1, getRequestUser(request)) + .setParameter(2, appType) + .unique(); + if (externalUser != null) { + Application.getCommonsService().delete((ID) externalUser[0]); + } + + return RespBody.ok(); + } } diff --git a/src/main/java/com/rebuild/web/user/signup/LoginController.java b/src/main/java/com/rebuild/web/user/signup/LoginController.java index c144ca285..e29672c35 100644 --- a/src/main/java/com/rebuild/web/user/signup/LoginController.java +++ b/src/main/java/com/rebuild/web/user/signup/LoginController.java @@ -62,17 +62,14 @@ import java.util.Map; public class LoginController extends BaseController { public static final String CK_AUTOLOGIN = "rb.alt"; - - private static final String SK_NEED_VCODE = "needLoginVCode"; - public static final String SK_USER_THEME = "currentUseTheme"; - - private static final String DEFAULT_HOME = "../dashboard/home"; + private static final String SK_NEED_VCODE = "needLoginVCode"; @GetMapping("login") public ModelAndView checkLogin(HttpServletRequest request, HttpServletResponse response) throws IOException { + final String homeUrl = "../dashboard/home"; if (AppUtils.getRequestUser(request) != null) { - response.sendRedirect(DEFAULT_HOME); + response.sendRedirect(homeUrl); return null; } @@ -83,7 +80,7 @@ public class LoginController extends BaseController { if (tokenUser != null) { loginSuccessed(request, response, tokenUser, false); - String nexturl = StringUtils.defaultIfBlank(request.getParameter("nexturl"), DEFAULT_HOME); + String nexturl = getParameter(request, "nexturl", homeUrl); response.sendRedirect(CodecUtils.urlDecode(nexturl)); return null; } else { @@ -116,7 +113,7 @@ public class LoginController extends BaseController { if (altUser != null && Application.getUserStore().existsUser(altUser)) { loginSuccessed(request, response, altUser, true); - String nexturl = StringUtils.defaultIfBlank(request.getParameter("nexturl"), DEFAULT_HOME); + String nexturl = getParameter(request, "nexturl", homeUrl); response.sendRedirect(CodecUtils.urlDecode(nexturl)); return null; } else { @@ -136,9 +133,10 @@ public class LoginController extends BaseController { ServletUtils.setSessionAttribute(request, SK_NEED_VCODE, true); } - // H5 QR - String mobileQrUrl = RebuildConfiguration.getHomeUrl("/h5app/"); - mobileQrUrl = AppUtils.getContextPath() + "/commons/barcode/render-qr?t=" + CodecUtils.urlEncode(mobileQrUrl); + // H5 + String mobileUrl = RebuildConfiguration.getMobileUrl("/"); + String mobileQrUrl = AppUtils.getContextPath() + "/commons/barcode/render-qr?t=" + CodecUtils.urlEncode(mobileUrl); + mv.getModel().put("mobileUrl", mobileUrl); mv.getModel().put("mobileQrUrl", mobileQrUrl); mv.getModelMap().put("UsersMsg", CheckDangers.getUsersDanger()); @@ -190,35 +188,22 @@ public class LoginController extends BaseController { return RespBody.ok(resMap); } - /** - * @param user - * @param state - * @return - */ private int getLoginRetryTimes(String user, int state) { - String key = "LoginRetry-" + user; + final String ckey = "LoginRetry-" + user; if (state == -1) { - Application.getCommonsCache().evict(key); + Application.getCommonsCache().evict(ckey); return 0; } - Integer retry = (Integer) Application.getCommonsCache().getx(key); + Integer retry = (Integer) Application.getCommonsCache().getx(ckey); retry = retry == null ? 0 : retry; if (state == 1) { retry += 1; - Application.getCommonsCache().putx(key, retry, CommonsCache.TS_HOUR); + Application.getCommonsCache().putx(ckey, retry, CommonsCache.TS_HOUR); } return retry; } - /** - * 登录成功 - * - * @param request - * @param response - * @param user - * @param autoLogin - */ private void loginSuccessed(HttpServletRequest request, HttpServletResponse response, ID user, boolean autoLogin) { // 自动登录 if (autoLogin) { @@ -237,16 +222,8 @@ public class LoginController extends BaseController { Application.getSessionStore().storeLoginSuccessed(request); } - /** - * 创建登陆日志 - * - * @param request - * @param user - */ - protected void createLoginLog(HttpServletRequest request, ID user) { - String ipAddr = ServletUtils.getRemoteAddr(request); + private void createLoginLog(HttpServletRequest request, ID user) { String UA = request.getHeader("user-agent"); - try { UserAgent uas = UserAgentUtil.parse(UA); UA = String.format("%s-%s (%s)", @@ -260,7 +237,7 @@ public class LoginController extends BaseController { Record record = EntityHelper.forNew(EntityHelper.LoginLog, UserService.SYSTEM_USER); record.setID("user", user); - record.setString("ipAddr", ipAddr); + record.setString("ipAddr", ServletUtils.getRemoteAddr(request)); record.setString("userAgent", UA.toUpperCase()); record.setDate("loginTime", CalendarUtils.now()); Application.getCommonsService().create(record); diff --git a/src/main/resources/i18n/lang.zh_CN.json b/src/main/resources/i18n/lang.zh_CN.json index 3b4fa345b..768b79198 100644 --- a/src/main/resources/i18n/lang.zh_CN.json +++ b/src/main/resources/i18n/lang.zh_CN.json @@ -1260,7 +1260,7 @@ "短信签名":"短信签名", "短信账户未配置或配置错误":"短信账户未配置或配置错误", "确定":"确定", - "确定要禁用此用户吗?":"确定要禁用此用户吗?", + "确认要禁用此用户吗?":"确认要禁用此用户吗?", "确认删除当前记录吗?":"确认删除当前记录吗?", "确认删除此仪表盘?":"确认删除此仪表盘?", "确认删除此任务?":"确认删除此任务?", diff --git a/src/main/resources/metadata-conf.xml b/src/main/resources/metadata-conf.xml index 85ddcf39c..6e875ddb4 100644 --- a/src/main/resources/metadata-conf.xml +++ b/src/main/resources/metadata-conf.xml @@ -75,6 +75,14 @@ + + + + + + + + diff --git a/src/main/resources/scripts/db-init.sql b/src/main/resources/scripts/db-init.sql index 15abc3384..991455a7b 100644 --- a/src/main/resources/scripts/db-init.sql +++ b/src/main/resources/scripts/db-init.sql @@ -112,6 +112,16 @@ create table if not exists `team_member` ( unique index UIX0_team_member (`TEAM_ID`, `USER_ID`) )Engine=InnoDB; +-- ************ Entity [ExternalUser] DDL ************ +create table if not exists `external_user` ( + `USER_ID` char(20) not null, + `APP_USER` varchar(100) not null, + `APP_TYPE` smallint(6) not null comment '1=DingTalk,2=WxWork', + `BIND_USER` char(20) not null, + primary key (`USER_ID`), + unique index UIX0_external_user (`APP_TYPE`, `APP_USER`) +)Engine=InnoDB; + -- ************ Entity [MetaEntity] DDL ************ create table if not exists `meta_entity` ( `ENTITY_ID` char(20) not null, @@ -790,4 +800,4 @@ insert into `project_plan_config` (`CONFIG_ID`, `PROJECT_ID`, `PLAN_NAME`, `SEQ` -- DB Version (see `db-upgrade.sql`) insert into `system_config` (`CONFIG_ID`, `ITEM`, `VALUE`) - values ('021-9000000000000001', 'DBVer', 36); + values ('021-9000000000000001', 'DBVer', 37); diff --git a/src/main/resources/scripts/db-upgrade.sql b/src/main/resources/scripts/db-upgrade.sql index e428e286a..22aaad5a9 100644 --- a/src/main/resources/scripts/db-upgrade.sql +++ b/src/main/resources/scripts/db-upgrade.sql @@ -1,6 +1,17 @@ -- Database upgrade scripts for rebuild 1.x and 2.x -- Each upgraded starts with `-- #VERSION` +-- #37 (v2.5) +-- ************ Entity [ExternalUser] DDL ************ +create table if not exists `external_user` ( + `USER_ID` char(20) not null, + `APP_USER` varchar(100) not null, + `APP_TYPE` smallint(6) not null comment '1=DingTalk,2=WxWork', + `BIND_USER` char(20) not null, + primary key (`USER_ID`), + unique index UIX0_external_user (`APP_TYPE`, `APP_USER`) +)Engine=InnoDB; + -- #36 (v2.4) -- ************ Entity [FrontjsCode] DDL ************ create table if not exists `frontjs_code` ( diff --git a/src/main/resources/web/_include/nav-left-admin.html b/src/main/resources/web/_include/nav-left-admin.html index 16c1cb18a..bc9975dee 100644 --- a/src/main/resources/web/_include/nav-left-admin.html +++ b/src/main/resources/web/_include/nav-left-admin.html @@ -8,18 +8,28 @@ diff --git a/src/main/resources/web/admin/admin-verify.html b/src/main/resources/web/admin/admin-verify.html index 06b70b6ae..bc86444a8 100644 --- a/src/main/resources/web/admin/admin-verify.html +++ b/src/main/resources/web/admin/admin-verify.html @@ -6,7 +6,7 @@ diff --git a/src/main/resources/web/admin/integration/dingtalk.html b/src/main/resources/web/admin/integration/dingtalk.html new file mode 100644 index 000000000..468b43262 --- /dev/null +++ b/src/main/resources/web/admin/integration/dingtalk.html @@ -0,0 +1,67 @@ + + + + + + [[${bundle.L('钉钉')}]] + + + + + + + diff --git a/src/main/resources/web/admin/integration/storage-qiniu.html b/src/main/resources/web/admin/integration/storage-qiniu.html index 6a52319e5..57a80706c 100644 --- a/src/main/resources/web/admin/integration/storage-qiniu.html +++ b/src/main/resources/web/admin/integration/storage-qiniu.html @@ -24,22 +24,30 @@ [[${bundle.L('访问域名')}]] - [[${storageAccount == null ? bundle.L('未设置') : storageAccount[3]}]] + + [[${storageAccount == null ? bundle.L('未设置') : storageAccount[3]}]] + [[${bundle.L('存储空间')}]]

[[${bundle.L('存储空间变更需你自行迁移原有数据')}]]

- [[${storageAccount == null ? bundle.L('未设置') : storageAccount[2]}]] + + [[${storageAccount == null ? bundle.L('未设置') : storageAccount[2]}]] + [[${bundle.L('秘钥 AK')}]] - [[${storageAccount == null ? bundle.L('未设置') : storageAccount[0]}]] + + [[${storageAccount == null ? bundle.L('未设置') : storageAccount[0]}]] + [[${bundle.L('秘钥 SK')}]] - [[${storageAccount == null ? bundle.L('未设置') : storageAccount[1]}]] + + [[${storageAccount == null ? bundle.L('未设置') : storageAccount[1]}]] + diff --git a/src/main/resources/web/admin/integration/submail.html b/src/main/resources/web/admin/integration/submail.html index 274d9b313..b6d9b0e6c 100644 --- a/src/main/resources/web/admin/integration/submail.html +++ b/src/main/resources/web/admin/integration/submail.html @@ -54,25 +54,33 @@ APPID [[${bundle.L('SMTP 用户名')}]] - [[${mailAccount == null ? bundle.L('未设置') : mailAccount[0]}]] + + [[${mailAccount == null ? bundle.L('未设置') : mailAccount[0]}]] + APPKEY [[${bundle.L('SMTP 密码')}]] - [[${mailAccount == null ? bundle.L('未设置') : mailAccount[1]}]] + + [[${mailAccount == null ? bundle.L('未设置') : mailAccount[1]}]] + [[${bundle.L('发件人地址')}]]

[[${bundle.L('地址域名需与 SUBMAIL 中配置的域名匹配')}]]

- [[${mailAccount == null ? bundle.L('未设置') : mailAccount[2]}]] + + [[${mailAccount == null ? bundle.L('未设置') : mailAccount[2]}]] + [[${bundle.L('发件人名称')}]] - [[${mailAccount == null ? bundle.L('未设置') : mailAccount[3]}]] + + [[${mailAccount == null ? bundle.L('未设置') : mailAccount[3]}]] + @@ -93,15 +101,21 @@ APPID - [[${smsAccount == null ? bundle.L('未设置') : smsAccount[0]}]] + + [[${smsAccount == null ? bundle.L('未设置') : smsAccount[0]}]] + APPKEY - [[${smsAccount == null ? bundle.L('未设置') : smsAccount[1]}]] + + [[${smsAccount == null ? bundle.L('未设置') : smsAccount[1]}]] + [[${bundle.L('短信签名')}]] - [[${smsAccount == null ? bundle.L('未设置') : smsAccount[2]}]] + + [[${smsAccount == null ? bundle.L('未设置') : smsAccount[2]}]] + diff --git a/src/main/resources/web/admin/integration/wxwork.html b/src/main/resources/web/admin/integration/wxwork.html new file mode 100644 index 000000000..b643d79db --- /dev/null +++ b/src/main/resources/web/admin/integration/wxwork.html @@ -0,0 +1,67 @@ + + + + + + [[${bundle.L('企业微信')}]] + + + + + + + diff --git a/src/main/resources/web/assets/css/rb-base.css b/src/main/resources/web/assets/css/rb-base.css index 57329d144..0054e1c78 100644 --- a/src/main/resources/web/assets/css/rb-base.css +++ b/src/main/resources/web/assets/css/rb-base.css @@ -11542,7 +11542,7 @@ canvas { .rb-offcanvas-menu .rb-top-header .rb-navbar-header { display: block; width: auto; - background-color: #4285f4; + /*background-color: #4285f4;*/ } } diff --git a/src/main/resources/web/assets/css/rb-page.css b/src/main/resources/web/assets/css/rb-page.css index 97acae86a..90696a692 100644 --- a/src/main/resources/web/assets/css/rb-page.css +++ b/src/main/resources/web/assets/css/rb-page.css @@ -4100,4 +4100,43 @@ body.fullscreen .rb-wrapper > .rb-content { .card-header { font-weight: normal; -} \ No newline at end of file +} + +html.external-auth, +html.external-auth body { + height: auto; + background-color: #fff; +} + +html.external-auth .auth-body { + max-width: 421px; + margin: 0 auto; +} + +html.external-auth .auth-body .alogo { + margin-top: 61px; + margin-bottom: 51px; +} + +html.external-auth .auth-body .alogo img { + display: inline-block; + width: 64px; + height: 64px; + border-radius: 14px; +} + +html.external-auth .auth-body .alogo .zmdi { + font-size: 3rem; + margin-top: 12px; +} + +html.external-auth .auth-body .card { + margin-left: 20px; + margin-right: 20px; + padding-left: 20px; + padding-right: 20px; +} + +html.external-auth .auth-body.must-center .card { + display: none; +} diff --git a/src/main/resources/web/assets/img/dingtalk256.png b/src/main/resources/web/assets/img/dingtalk256.png new file mode 100644 index 000000000..b6bc1da82 Binary files /dev/null and b/src/main/resources/web/assets/img/dingtalk256.png differ diff --git a/src/main/resources/web/assets/img/rebuild256.png b/src/main/resources/web/assets/img/rebuild256.png new file mode 100644 index 000000000..e6be7882b Binary files /dev/null and b/src/main/resources/web/assets/img/rebuild256.png differ diff --git a/src/main/resources/web/assets/img/wxwork256.png b/src/main/resources/web/assets/img/wxwork256.png new file mode 100644 index 000000000..e222973fd Binary files /dev/null and b/src/main/resources/web/assets/img/wxwork256.png differ diff --git a/src/main/resources/web/assets/js/bizuser/user-view.js b/src/main/resources/web/assets/js/bizuser/user-view.js index f4cc235f1..e181af833 100644 --- a/src/main/resources/web/assets/js/bizuser/user-view.js +++ b/src/main/resources/web/assets/js/bizuser/user-view.js @@ -35,7 +35,7 @@ $(document).ready(function () { }) $('.J_disable').click(() => { - RbAlert.create($L('确定要禁用此用户吗?'), { + RbAlert.create($L('确认要禁用此用户吗?'), { confirmText: $L('禁用'), confirm: function () { toggleDisabled(true, this) diff --git a/src/main/resources/web/assets/js/user-settings.js b/src/main/resources/web/assets/js/user-settings.js index 904a90e13..857337d12 100644 --- a/src/main/resources/web/assets/js/user-settings.js +++ b/src/main/resources/web/assets/js/user-settings.js @@ -50,6 +50,22 @@ $(document).ready(function () { }) }) + const $unauth = $('.J_unauth-dingtalk, .J_unauth-wxwork').on('click', () => { + RbAlert.create($L('确认要取消授权吗?'), { + confirm: function () { + this.hide() + $.post(`/settings/cancel-external-user?type=${$unauth.data('type')}`, (res) => { + if (res.error_code === 0) { + location.hash = 'secure' + location.reload() + } else { + RbHighbar.create(res.error_msg) + } + }) + }, + }) + }) + // load log $('a.nav-link[href="#logs"]').click(() => { diff --git a/src/main/resources/web/error/error.html b/src/main/resources/web/error/error.html index 62a8752a3..b27a82ce8 100644 --- a/src/main/resources/web/error/error.html +++ b/src/main/resources/web/error/error.html @@ -28,6 +28,11 @@ .error-container a[target='_blank']:hover { text-decoration: underline; } + @media (max-width: 576px) { + .rb-error .error-container { + max-width: 100%; + } + } diff --git a/src/main/resources/web/settings/user-settings.html b/src/main/resources/web/settings/user-settings.html index 19e79546d..2dfdf424e 100644 --- a/src/main/resources/web/settings/user-settings.html +++ b/src/main/resources/web/settings/user-settings.html @@ -99,20 +99,20 @@
- -
+ +
- -
+ +
- -
+ +
@@ -122,14 +122,20 @@
- -
- + +
+
- -
+ +
-
+
@@ -152,23 +158,41 @@
- -
+ +
-
+
- -
+ +
[[${bundle.L('建议 90 天更改一次密码')}]]
-
+
+
+ +
+
[[${dingtalkUser}]]
+
+
+ +
+
+
+ +
+
[[${wxworkUser}]]
+
+
+ +
+
diff --git a/src/main/resources/web/signup/login.html b/src/main/resources/web/signup/login.html index ca519f4b6..e2b316ae1 100644 --- a/src/main/resources/web/signup/login.html +++ b/src/main/resources/web/signup/login.html @@ -42,7 +42,7 @@ z-index: 1; background: rgba(0, 0, 0, 0.1); } - .o-platform a > i.zmdi { + .o-platform a > .icon { background-color: #fc9a00; color: #fff; border-radius: 50%; @@ -50,7 +50,7 @@ height: 25px; line-height: 26px; font-size: 1.2rem; - padding-left: 9px; + text-align: center; } .o-platform a > span { color: #666; @@ -62,6 +62,10 @@ width: 160px; padding: 6px; } + .o-platform:hover .dropdown-menu { + display: block; + margin-top: 0; /* remove the gap so it doesn't close */ + } @@ -112,7 +116,7 @@
- + [[${bundle.L('手机版')}]]