localization

This commit is contained in:
MaxKey
2022-01-12 09:28:23 +08:00
parent c9870a8146
commit bd04a24bd8
29 changed files with 615 additions and 37 deletions

View File

@@ -30,6 +30,7 @@ import org.maxkey.crypto.password.PasswordReciprocal;
import org.maxkey.crypto.password.SM3PasswordEncoder;
import org.maxkey.crypto.password.StandardPasswordEncoder;
import org.maxkey.persistence.db.InstitutionService;
import org.maxkey.persistence.db.LocalizationService;
import org.maxkey.util.IdGenerator;
import org.maxkey.util.SnowFlakeId;
import org.maxkey.web.WebContext;
@@ -69,6 +70,11 @@ public class ApplicationAutoConfiguration implements InitializingBean {
return new InstitutionService(jdbcTemplate);
}
@Bean(name = "localizationService")
public LocalizationService localizationService(JdbcTemplate jdbcTemplate,InstitutionService institutionService) {
return new LocalizationService(jdbcTemplate,institutionService);
}
/**
* Authentication Password Encoder .
* @return

View File

@@ -46,6 +46,10 @@ public class Institutions extends JpaBaseEntity implements Serializable {
@Column
private String logo;
@Column
private String title;
@Column
private String consoleTitle;
@Column
private String domain;
@Column
private String division;
@@ -111,6 +115,19 @@ public class Institutions extends JpaBaseEntity implements Serializable {
public void setLogo(String logo) {
this.logo = logo;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getConsoleTitle() {
return consoleTitle;
}
public void setConsoleTitle(String consoleTitle) {
this.consoleTitle = consoleTitle;
}
public String getDomain() {
return domain;
}
@@ -228,6 +245,14 @@ public class Institutions extends JpaBaseEntity implements Serializable {
builder.append(name);
builder.append(", fullName=");
builder.append(fullName);
builder.append(", logo=");
builder.append(logo);
builder.append(", title=");
builder.append(title);
builder.append(", consoleTitle=");
builder.append(consoleTitle);
builder.append(", domain=");
builder.append(domain);
builder.append(", division=");
builder.append(division);
builder.append(", country=");

View File

@@ -0,0 +1,126 @@
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;
@Entity
@Table(name = "MXK_LOCALIZATION")
public class Localization extends JpaBaseEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = -142504964446659847L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.AUTO, generator = "snowflakeid")
private String id;
@Column
private String property;
@Column
private String langZh;
@Column
private String langEn;
@Column
private String description;
@Column
private int status;
@Column
private String instId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getLangZh() {
return langZh;
}
public void setLangZh(String langZh) {
this.langZh = langZh;
}
public String getLangEn() {
return langEn;
}
public void setLangEn(String langEn) {
this.langEn = langEn;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getInstId() {
return instId;
}
public void setInstId(String instId) {
this.instId = instId;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Localization [id=");
builder.append(id);
builder.append(", property=");
builder.append(property);
builder.append(", langZh=");
builder.append(langZh);
builder.append(", langEn=");
builder.append(langEn);
builder.append(", description=");
builder.append(description);
builder.append(", status=");
builder.append(status);
builder.append(", instId=");
builder.append(instId);
builder.append("]");
return builder.toString();
}
}

View File

@@ -20,6 +20,7 @@ package org.maxkey.persistence.db;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.maxkey.constants.ConstantsStatus;
@@ -36,13 +37,20 @@ import com.github.benmanes.caffeine.cache.Caffeine;
public class InstitutionService {
private static Logger _logger = LoggerFactory.getLogger(InstitutionService.class);
private static final String SELECT_STATEMENT = "select * from mxk_institutions where domain = ? and status = " + ConstantsStatus.ACTIVE;
private static final String SELECT_STATEMENT =
"select * from mxk_institutions where domain = ? and status = " + ConstantsStatus.ACTIVE;
private static final String SELECT_STATEMENT_BY_ID =
"select * from mxk_institutions where id = ? and status = " + ConstantsStatus.ACTIVE;
protected static final Cache<String, Institutions> institutionsStore =
Caffeine.newBuilder()
.expireAfterWrite(ConstantsTimeInterval.ONE_HOUR, TimeUnit.MINUTES)
.expireAfterWrite(ConstantsTimeInterval.ONE_HOUR, TimeUnit.SECONDS)
.build();
//id domain mapping
protected static final ConcurrentHashMap<String,String> mapper = new ConcurrentHashMap<String,String>();
protected JdbcTemplate jdbcTemplate;
public InstitutionService(JdbcTemplate jdbcTemplate) {
@@ -61,6 +69,24 @@ public class InstitutionService {
}
institutionsStore.put(domain, inst);
mapper.put(inst.getId(), domain);
}
return inst;
}
public Institutions get(String instId) {
_logger.trace(" instId {}" , instId);
Institutions inst = institutionsStore.getIfPresent(mapper.get(instId));
if(inst == null) {
List<Institutions> institutions =
jdbcTemplate.query(SELECT_STATEMENT_BY_ID,new InstitutionsRowMapper(),instId);
if (institutions != null && institutions.size() > 0) {
inst = institutions.get(0);
}
institutionsStore.put(inst.getDomain(), inst);
mapper.put(inst.getId(), inst.getDomain());
}
return inst;
@@ -75,6 +101,8 @@ public class InstitutionService {
institution.setFullName(rs.getString("fullname"));
institution.setLogo(rs.getString("logo"));
institution.setDomain(rs.getString("domain"));
institution.setTitle(rs.getString("title"));
institution.setConsoleTitle(rs.getString("consoletitle"));
return institution;
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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.db;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.maxkey.constants.ConstantsTimeInterval;
import org.maxkey.entity.Localization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
public class LocalizationService {
private static Logger _logger = LoggerFactory.getLogger(LocalizationService.class);
private static final String INSERT_STATEMENT ="insert into mxk_localization (id, property,langzh,langen,status,description,instid)values(?,?,?,?,?,?,?)";
private static final String UPDATE_STATEMENT ="update mxk_localization set langzh = ? , langen =? where id = ?";
private static final String DELETE_STATEMENT ="delete from mxk_localization where id = ?";
private static final String SELECT_STATEMENT ="select * from mxk_localization where ( id = ? ) or (property = ? and instid = ?)";
private static final Pattern PATTERN_HTML = Pattern.compile("<[^>]+>", Pattern.CASE_INSENSITIVE);
protected InstitutionService institutionService;
JdbcTemplate jdbcTemplate;
protected static final Cache<String, String> localizationStore =
Caffeine.newBuilder()
.expireAfterWrite(ConstantsTimeInterval.ONE_HOUR, TimeUnit.SECONDS)
.build();
public LocalizationService() {
}
public String getLocale(String code,String htmlTag,Locale locale,String inst) {
String message = "";
htmlTag = (htmlTag == null ||htmlTag.equalsIgnoreCase("true")) ? "tag" : "rtag";
if(code.equals("global.logo")) {
message = institutionService.get(inst).getLogo();
}else if(code.equals("global.title")) {
message = getFromStore(code, htmlTag, locale, inst);
if(message == null) {
message = institutionService.get(inst).getTitle();
}
}else if(code.equals("global.consoleTitle")) {
message = getFromStore(code, htmlTag, locale, inst);
if(message == null) {
message = institutionService.get(inst).getConsoleTitle();
}
}else {
message = getFromStore(code, htmlTag, locale, inst);
}
if(htmlTag.equalsIgnoreCase("rtag")) {
message = clearHTMLToString(message);
}
_logger.trace("{} = {}" , code , message);
return message == null ? "" : message;
}
public String clearHTMLToString(String message) {
return PATTERN_HTML.matcher(message).replaceAll("");
}
public String getFromStore(String code,String htmlTag,Locale locale,String inst) {
String message = localizationStore.getIfPresent(code+"_"+locale.getLanguage()+"_"+inst);
if(message != null) return message;
Localization localization = get(code,inst);
if(localization != null) {
localizationStore.put(code+"_en_"+inst, localization.getLangEn());
localizationStore.put(code+"_zh_"+inst, localization.getLangZh());
if(locale.getLanguage().equals("en")) {
message = localization.getLangEn();
}else {
message = localization.getLangZh();
}
if(message != null) return message;
}
return message;
}
public void setInstitutionService(InstitutionService institutionService) {
this.institutionService = institutionService;
}
public boolean insert(Localization localization) {
return jdbcTemplate.update(INSERT_STATEMENT,
new Object[] {localization.getId(),localization.getProperty(),
localization.getLangZh(),localization.getLangEn(),
localization.getStatus(),localization.getDescription(),
localization.getInstId()},
new int[] {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER,
Types.VARCHAR, Types.VARCHAR,}) > 0;
}
public boolean update(Localization localization) {
jdbcTemplate.update(UPDATE_STATEMENT,localization.getLangZh(),localization.getLangEn(),localization.getId());
return true;
}
public boolean remove(String id) {
return jdbcTemplate.update(DELETE_STATEMENT,id) > 0;
}
public Localization get(String property,String instId) {
_logger.debug("load property from database , property {} ,instId {}",property, instId);
List<Localization> localizations =
jdbcTemplate.query(
SELECT_STATEMENT,new LocalizationRowMapper(),property,property,instId);
return (localizations==null || localizations.size()==0) ? null : localizations.get(0);
}
public LocalizationService(JdbcTemplate jdbcTemplate,InstitutionService institutionService) {
super();
this.institutionService = institutionService;
this.jdbcTemplate = jdbcTemplate;
}
public class LocalizationRowMapper implements RowMapper<Localization> {
@Override
public Localization mapRow(ResultSet rs, int rowNum) throws SQLException {
Localization localization = new Localization();
localization.setId(rs.getString("id"));
localization.setProperty(rs.getString("property"));
localization.setLangZh(rs.getString("langzh"));
localization.setLangEn(rs.getString("langen"));
localization.setStatus(rs.getInt("status"));
localization.setDescription(rs.getString("description"));
localization.setInstId(rs.getString("instid"));
return localization;
}
}
}

View File

@@ -46,9 +46,11 @@ public class WebConstants {
public static final String CURRENT_USER_PASSWORD_SET_TYPE
= "current_user_password_set_type";
public static final String CURRENT_MESSAGE = "current_message";
public static final String CURRENT_MESSAGE = "current_message";
public static final String CURRENT_INST = "current_inst";
public static final String CURRENT_INST = "current_inst";
public final static String INST_COOKIE_NAME = "mxk_inst";
// SPRING_SECURITY_SAVED_REQUEST
public static final String FIRST_SAVED_REQUEST_PARAMETER

View File

@@ -28,8 +28,11 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.LogFactory;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.entity.Institutions;
import org.maxkey.entity.UserInfo;
import org.maxkey.util.DateUtils;
import org.maxkey.util.IdGenerator;
@@ -120,6 +123,18 @@ public final class WebContext {
public static UserInfo getUserInfo() {
return ((UserInfo) getAttribute(WebConstants.CURRENT_USER));
}
public static String getInst(HttpServletRequest request) {
String instId = "1";
//from session
if(getAttribute(WebConstants.CURRENT_INST) != null) {
instId = ((Institutions)request.getSession().getAttribute(WebConstants.CURRENT_INST)).getId();
}else {
//from cookie
instId = WebContext.readCookieByName(request, WebConstants.INST_COOKIE_NAME).getValue();
}
return StringUtils.isBlank(instId) ? "1" : instId;
}
/**
* set Message to session,session id is Constants.MESSAGE

View File

@@ -39,13 +39,10 @@ public class WebInstRequestFilter extends GenericFilterBean {
public final static String HEADER_HOST = "host";
public final static String LOGO_COOKIE_NAME = "mxk_logo";
InstitutionService institutionService;
ApplicationConfig applicationConfig;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
@@ -64,7 +61,7 @@ public class WebInstRequestFilter extends GenericFilterBean {
Institutions institution =institutionService.findByDomain(host);
_logger.trace("{}" ,institution);
request.getSession().setAttribute(WebConstants.CURRENT_INST, institution);
WebContext.setCookie((HttpServletResponse)servletResponse, host, LOGO_COOKIE_NAME, institution.getLogo());
WebContext.setCookie((HttpServletResponse)servletResponse, host, WebConstants.INST_COOKIE_NAME, institution.getId());
}
chain.doFilter(servletRequest, servletResponse);
}

View File

@@ -39,14 +39,19 @@ public class WebXssRequestFilter extends GenericFilterBean {
final static ConcurrentHashMap <String,String> skipUrlMap = new ConcurrentHashMap <String,String>();
static {
//add or update
skipUrlMap.put("/notices/add", "/notices/add");
skipUrlMap.put("/notices/update", "/notices/update");
skipUrlMap.put("/institutions/update","/institutions/update");
skipUrlMap.put("/localization/update","/localization/update");
//authz
skipUrlMap.put("/authz/cas", "/authz/cas");
skipUrlMap.put("/authz/cas/", "/authz/cas/");
skipUrlMap.put("/authz/cas/login", "/authz/cas/login");
skipUrlMap.put("/authz/oauth/v20/authorize", "/authz/oauth/v20/authorize");
//TENCENT_IOA
skipUrlMap.put("/oauth2/authorize", "/oauth2/authorize");
}
@Override

View File

@@ -26,10 +26,8 @@ import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.maxkey.entity.Institutions;
import org.maxkey.web.WebConstants;
import org.maxkey.persistence.db.LocalizationService;
import org.maxkey.web.WebContext;
import org.maxkey.web.WebInstRequestFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -51,6 +49,9 @@ public class LocaleTagDirective implements TemplateDirectiveModel {
@Autowired
private HttpServletRequest request;
@Autowired
LocalizationService localizationService;
@SuppressWarnings("rawtypes")
@Override
@@ -60,31 +61,39 @@ public class LocaleTagDirective implements TemplateDirectiveModel {
WebApplicationContext webApplicationContext =
RequestContextUtils.findWebApplicationContext(request);
String message = "";
if (params.get("code") == null) {
String code = params.get("code") == null? null : params.get("code").toString();
String htmlTag = params.get("htmltag")==null ? null : params.get("htmltag").toString();
_logger.trace("message code {} , htmltag {}" , code , htmlTag);
if (code == null) {
message = RequestContextUtils.getLocale(request).getLanguage();
} else if (params.get("code").toString().equals("global.application.version")
|| params.get("code").toString().equals("application.version")) {
} else if (code.equals("global.application.version")
|| code.equals("application.version")) {
message = WebContext.properties.getProperty("application.formatted-version");
} else if (params.get("code").toString().equals("global.logo")) {
if(request.getSession().getAttribute(WebConstants.CURRENT_INST)!=null) {
message = ((Institutions)request.getSession().getAttribute(WebConstants.CURRENT_INST)).getLogo();
}else {
message = WebContext.readCookieByName(request, WebInstRequestFilter.LOGO_COOKIE_NAME).getValue();
}
} else if (code.equals("global.logo")) {
message = localizationService.getLocale(
code,
htmlTag,
WebContext.getLocale(),
WebContext.getInst(request));
if(!message.startsWith("http")) {
message = request.getContextPath() + message;
}
}else if (code.equals("global.title")
||code.equals("global.consoleTitle")) {
message = localizationService.getLocale(
code,
htmlTag,
WebContext.getLocale(),
WebContext.getInst(request));
} else {
_logger.trace("message code " + params.get("code"));
try {
message = webApplicationContext.getMessage(
params.get("code").toString(),
code,
null,
RequestContextUtils.getLocale(request));
} catch (Exception e) {
_logger.error("message code " + params.get("code"), e);
_logger.error("message code " + code, e);
}
}
env.getOut().append(message);