MaxKey 3 سال پیش
والد
کامیت
c9870a8146
38فایلهای تغییر یافته به همراه1238 افزوده شده و 139 حذف شده
  1. 1 1
      gradle.properties
  2. 49 24
      maxkey-authentications/maxkey-authentication-social/src/main/java/org/maxkey/authn/support/socialsignon/service/SocialSignOnProviderService.java
  3. 2 2
      maxkey-authentications/maxkey-authentication-social/src/main/java/org/maxkey/autoconfigure/SocialSignOnAutoConfiguration.java
  4. 9 2
      maxkey-core/src/main/java/org/maxkey/autoconfigure/ApplicationAutoConfiguration.java
  5. 25 9
      maxkey-core/src/main/java/org/maxkey/autoconfigure/MvcAutoConfiguration.java
  6. 269 0
      maxkey-core/src/main/java/org/maxkey/entity/Institutions.java
  7. 62 48
      maxkey-core/src/main/java/org/maxkey/entity/SocialsProvider.java
  8. 88 0
      maxkey-core/src/main/java/org/maxkey/entity/SocialsProviderLogin.java
  9. 81 0
      maxkey-core/src/main/java/org/maxkey/persistence/db/InstitutionService.java
  10. 3 5
      maxkey-core/src/main/java/org/maxkey/web/WebConstants.java
  11. 39 0
      maxkey-core/src/main/java/org/maxkey/web/WebContext.java
  12. 78 0
      maxkey-core/src/main/java/org/maxkey/web/WebInstRequestFilter.java
  13. 15 0
      maxkey-core/src/main/java/org/maxkey/web/tag/LocaleTagDirective.java
  14. 1 1
      maxkey-gataway/src/main/resources/application.yml
  15. 28 0
      maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/InstitutionsMapper.java
  16. 45 0
      maxkey-persistence/src/main/java/org/maxkey/persistence/service/InstitutionsService.java
  17. 14 29
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java
  18. 1 1
      maxkey-webs/maxkey-boot-monitor/src/main/resources/application.properties
  19. 5 1
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/SocialSignOnListController.java
  20. 8 5
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LoginEndpoint.java
  21. 3 1
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LogoutEndpoint.java
  22. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/application.properties
  23. 0 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/log4j2.xml
  24. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/layout/nologintop.ftl
  25. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/layout/top.ftl
  26. 8 4
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/login.ftl
  27. 7 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/loginscandingtalk.ftl
  28. 5 0
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/loginscanworkweixin.ftl
  29. 1 0
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java
  30. 73 0
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/contorller/InstitutionsController.java
  31. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/resources/application.properties
  32. 21 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message.properties
  33. 20 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_en.properties
  34. 22 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_zh_CN.properties
  35. 225 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/institutions/updateInstitutions.ftl
  36. 6 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/layout/sidenav.ftl
  37. 10 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/socialsprovider/socialsProviderAdd.ftl
  38. 10 0
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/socialsprovider/socialsProviderUpdate.ftl

+ 1 - 1
gradle.properties

@@ -1,6 +1,6 @@
 #maxkey properties 
 group                           =maxkey.top
-version                         =3.2.0
+version                         =3.2.1
 vendor                          =https://www.maxkey.top
 author                          =MaxKeyTop
 

+ 49 - 24
maxkey-authentications/maxkey-authentication-social/src/main/java/org/maxkey/authn/support/socialsignon/service/SocialSignOnProviderService.java

@@ -22,15 +22,21 @@ import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import org.maxkey.configuration.ApplicationConfig;
+import org.maxkey.constants.ConstantsTimeInterval;
 import org.maxkey.crypto.password.PasswordReciprocal;
 import org.maxkey.entity.SocialsProvider;
+import org.maxkey.entity.SocialsProviderLogin;
 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;
+
 import me.zhyd.oauth.config.AuthConfig;
 import me.zhyd.oauth.model.AuthResponse;
 import me.zhyd.oauth.model.AuthUser;
@@ -39,10 +45,12 @@ import me.zhyd.oauth.request.*;
 public class SocialSignOnProviderService{
 	private static Logger _logger = LoggerFactory.getLogger(SocialSignOnProviderService.class);
 	
-	   private static final String DEFAULT_SELECT_STATEMENT = "select * from mxk_socials_provider where status = 1  order by sortindex";
-	    
-	   
-	List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
+	private static final String DEFAULT_SELECT_STATEMENT = "select * from mxk_socials_provider where instid = ? and status = 1  order by sortindex";
+	
+	protected static final Cache<String, SocialsProviderLogin> socialSignOnProvidersStore = 
+            Caffeine.newBuilder()
+                .expireAfterWrite(ConstantsTimeInterval.ONE_HOUR, TimeUnit.MINUTES)
+                .build();
 	
 	HashMap<String ,SocialsProvider>socialSignOnProviderMaps=new HashMap<String ,SocialsProvider>();
 	
@@ -52,7 +60,6 @@ public class SocialSignOnProviderService{
         this.jdbcTemplate=jdbcTemplate; 
     }
 
-	
 	public SocialsProvider get(String provider){
 		return socialSignOnProviderMaps.get(provider);
 	}
@@ -162,26 +169,43 @@ public class SocialSignOnProviderService{
 	    }
 	    return null;
 	}
-	public List<SocialsProvider> getSocialSignOnProviders() {
-		return socialSignOnProviders;
-	}
 	
-	public void loadSocialsProviders() {
-	    List<SocialsProvider> listSocialsProvider=jdbcTemplate.query(
-	            DEFAULT_SELECT_STATEMENT,
-                new SocialsProviderRowMapper());
-        _logger.trace("query SocialsProvider " + listSocialsProvider);
-        
-        for(SocialsProvider socialsProvider : listSocialsProvider){
-            socialSignOnProviderMaps.put(socialsProvider.getProvider(), socialsProvider);
-            _logger.debug("Social Provider " + socialsProvider.getProvider() 
-                                             + "(" + socialsProvider.getProviderName()+")");
-            if(!socialsProvider.getHidden().equals("true")) {
-                this.socialSignOnProviders.add(socialsProvider);
-            }
-        }
-    
-    _logger.debug("social SignOn Providers {}" , this.socialSignOnProviders);
+	public SocialsProviderLogin loadSocialsProviders(String instId) {
+		SocialsProviderLogin ssl = socialSignOnProvidersStore.getIfPresent(instId);
+		if(ssl == null) {
+		    List<SocialsProvider> listSocialsProvider=jdbcTemplate.query(
+		            DEFAULT_SELECT_STATEMENT,
+	                new SocialsProviderRowMapper(),instId);
+	        _logger.trace("query SocialsProvider " + listSocialsProvider);
+	        
+	        
+	        List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
+	        ssl = new SocialsProviderLogin(socialSignOnProviders);
+	        
+	        for(SocialsProvider socialsProvider : listSocialsProvider){
+	            socialSignOnProviderMaps.put(socialsProvider.getProvider(), socialsProvider);
+	            _logger.debug("Social Provider " + socialsProvider.getProvider() 
+	                                             + "(" + socialsProvider.getProviderName()+")");
+	            if(!socialsProvider.getHidden().equals("true")) {
+	                socialSignOnProviders.add(socialsProvider);
+	            }
+	            
+	            if(socialsProvider.getProvider().equalsIgnoreCase("workweixin")) {
+	            	ssl.setWorkWeixinLogin(socialsProvider.getScanCode());
+	            }else if(socialsProvider.getProvider().equalsIgnoreCase("dingtalk")) {
+	            	ssl.setDingTalkLogin(socialsProvider.getScanCode());
+	            }else if(socialsProvider.getProvider().equalsIgnoreCase("feishu")) {
+	            	ssl.setFeiShuLogin(socialsProvider.getScanCode());
+	            }else if(socialsProvider.getProvider().equalsIgnoreCase("welink")) {
+	            	ssl.setWeLinkLogin(socialsProvider.getScanCode());
+	            }
+	        }
+	        
+	        _logger.debug("social SignOn Providers Login {}" , ssl);
+	       
+	        socialSignOnProvidersStore.put(instId, ssl);
+		}
+        return ssl;
 	}
 	
 	
@@ -201,6 +225,7 @@ public class SocialSignOnProviderService{
             socialsProvider.setAgentId(rs.getString("agentId"));
             socialsProvider.setHidden(rs.getString("hidden"));
             socialsProvider.setSortIndex(rs.getInt("sortindex"));
+            socialsProvider.setScanCode(rs.getString("scancode"));
             socialsProvider.setStatus(rs.getInt("status"));
             return socialsProvider;
         }

+ 2 - 2
maxkey-authentications/maxkey-authentication-social/src/main/java/org/maxkey/autoconfigure/SocialSignOnAutoConfiguration.java

@@ -42,8 +42,8 @@ public class SocialSignOnAutoConfiguration implements InitializingBean {
     public SocialSignOnProviderService socialSignOnProviderService(
                     JdbcTemplate jdbcTemplate) throws IOException {
         SocialSignOnProviderService socialSignOnProviderService = new SocialSignOnProviderService(jdbcTemplate);
-        //load Socials Providers from database
-        socialSignOnProviderService.loadSocialsProviders();
+        //load default Social Providers from database
+        socialSignOnProviderService.loadSocialsProviders("1");
         _logger.debug("SocialSignOnProviderService inited.");
         return socialSignOnProviderService;
     }

+ 9 - 2
maxkey-core/src/main/java/org/maxkey/autoconfigure/ApplicationAutoConfiguration.java

@@ -29,6 +29,7 @@ import org.maxkey.crypto.password.MessageDigestPasswordEncoder;
 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.util.IdGenerator;
 import org.maxkey.util.SnowFlakeId;
 import org.maxkey.web.WebContext;
@@ -39,6 +40,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.Resource;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
@@ -62,6 +64,11 @@ public class ApplicationAutoConfiguration  implements InitializingBean {
         return new DataSourceTransactionManager(dataSource);
     }
     
+    @Bean(name = "institutionService")
+    public InstitutionService institutionService(JdbcTemplate jdbcTemplate) {
+        return new InstitutionService(jdbcTemplate);
+    }
+    
     /**
      * Authentication Password Encoder .
      * @return
@@ -94,10 +101,10 @@ public class ApplicationAutoConfiguration  implements InitializingBean {
         if(_logger.isDebugEnabled()) {
         	 _logger.debug("Password Encoders :");
 	        for (String key : encoders.keySet()) {
-	            _logger.debug(key + "=" + encoders.get(key).getClass().getName());
+	            _logger.debug("{}= {}" ,String.format("%-10s", key), encoders.get(key).getClass().getName());
 	        }
         }
-        _logger.debug("default encoder " + idForEncode);
+        _logger.debug("{} is default encoder" , idForEncode);
         return passwordEncoder;
     }
 

+ 25 - 9
maxkey-core/src/main/java/org/maxkey/autoconfigure/MvcAutoConfiguration.java

@@ -22,11 +22,14 @@ import java.util.List;
 
 import javax.servlet.Filter;
 
+import org.maxkey.configuration.ApplicationConfig;
 import org.maxkey.constants.ConstantsTimeInterval;
+import org.maxkey.persistence.db.InstitutionService;
 import org.maxkey.persistence.db.LoginHistoryService;
 import org.maxkey.persistence.db.LoginService;
 import org.maxkey.web.SessionListenerAdapter;
 import org.maxkey.web.WebXssRequestFilter;
+import org.maxkey.web.WebInstRequestFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
@@ -255,10 +258,22 @@ public class MvcAutoConfiguration implements InitializingBean , WebMvcConfigurer
         return new SecurityContextHolderAwareRequestFilter();
     }
     
+    @Bean
+    public FilterRegistrationBean<Filter> delegatingFilterProxy() {
+        _logger.debug("delegatingFilterProxy init for /* ");
+        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<Filter>();
+        registrationBean.setFilter(new DelegatingFilterProxy("securityContextHolderAwareRequestFilter"));
+        registrationBean.addUrlPatterns("/*");
+        //registrationBean.
+        registrationBean.setName("delegatingFilterProxy");
+        registrationBean.setOrder(1);
+        
+        return registrationBean;
+    }
     
     @Bean
     public FilterRegistrationBean<Filter> webXssRequestFilter() {
-        _logger.debug("delegatingFilterProxy init for /* ");
+        _logger.debug("webXssRequestFilter init for /* ");
         FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<Filter>(new WebXssRequestFilter());
         registrationBean.addUrlPatterns("/*");
         registrationBean.setName("webXssRequestFilter");
@@ -266,16 +281,17 @@ public class MvcAutoConfiguration implements InitializingBean , WebMvcConfigurer
         return registrationBean;
     }
     
+    
     @Bean
-    public FilterRegistrationBean<Filter> delegatingFilterProxy() {
-        _logger.debug("delegatingFilterProxy init for /* ");
-        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<Filter>();
-        registrationBean.setFilter(new DelegatingFilterProxy("securityContextHolderAwareRequestFilter"));
+    public FilterRegistrationBean<Filter> WebInstRequestFilter(
+    											InstitutionService institutionService,
+    											ApplicationConfig applicationConfig) {
+        _logger.debug("WebInstRequestFilter init for /* ");
+        FilterRegistrationBean<Filter> registrationBean = 
+        		new FilterRegistrationBean<Filter>(new WebInstRequestFilter(institutionService,applicationConfig));
         registrationBean.addUrlPatterns("/*");
-        //registrationBean.
-        registrationBean.setName("delegatingFilterProxy");
-        registrationBean.setOrder(1);
-        
+        registrationBean.setName("webInstRequestFilter");
+        registrationBean.setOrder(3);
         return registrationBean;
     }
     

+ 269 - 0
maxkey-core/src/main/java/org/maxkey/entity/Institutions.java

@@ -0,0 +1,269 @@
+/*
+ * 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.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_INSTITUTIONS")
+public class Institutions extends JpaBaseEntity implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -2375872012431214098L;
+	
+	@Id
+    @Column
+    @GeneratedValue(strategy = GenerationType.AUTO, generator = "snowflakeid")
+	private String id;
+	@Column
+	private String name;
+	@Column
+	private String fullName;
+	@Column
+	private String logo;
+	@Column
+	private String domain;
+	@Column
+    private String division;
+    @Column
+    private String country;
+    @Column
+    private String region;
+    @Column
+    private String locality;
+    @Column
+    private String street;
+    @Column
+    private String address;
+    @Column
+    private String contact;
+    @Column
+    private String postalCode;
+    @Column
+    private String phone;
+    @Column
+    private String fax;
+    @Column
+    private String email;
+    
+    @Column
+    private String description;
+    @Column
+    private int status;
+    @Column
+    String createdBy;
+    @Column
+    String createdDate;
+    @Column
+    String modifiedBy;
+    @Column
+    String modifiedDate;
+    
+	public Institutions() {
+		super();
+	}
+	public String getId() {
+		return id;
+	}
+	public void setId(String id) {
+		this.id = id;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public String getFullName() {
+		return fullName;
+	}
+	public void setFullName(String fullName) {
+		this.fullName = fullName;
+	}
+	
+	public String getLogo() {
+		return logo;
+	}
+	public void setLogo(String logo) {
+		this.logo = logo;
+	}
+	public String getDomain() {
+		return domain;
+	}
+	public void setDomain(String domain) {
+		this.domain = domain;
+	}
+	public String getDivision() {
+		return division;
+	}
+	public void setDivision(String division) {
+		this.division = division;
+	}
+	public String getCountry() {
+		return country;
+	}
+	public void setCountry(String country) {
+		this.country = country;
+	}
+	public String getRegion() {
+		return region;
+	}
+	public void setRegion(String region) {
+		this.region = region;
+	}
+	public String getLocality() {
+		return locality;
+	}
+	public void setLocality(String locality) {
+		this.locality = locality;
+	}
+	public String getStreet() {
+		return street;
+	}
+	public void setStreet(String street) {
+		this.street = street;
+	}
+	public String getAddress() {
+		return address;
+	}
+	public void setAddress(String address) {
+		this.address = address;
+	}
+	public String getContact() {
+		return contact;
+	}
+	public void setContact(String contact) {
+		this.contact = contact;
+	}
+	public String getPostalCode() {
+		return postalCode;
+	}
+	public void setPostalCode(String postalCode) {
+		this.postalCode = postalCode;
+	}
+	public String getPhone() {
+		return phone;
+	}
+	public void setPhone(String phone) {
+		this.phone = phone;
+	}
+	public String getFax() {
+		return fax;
+	}
+	public void setFax(String fax) {
+		this.fax = fax;
+	}
+	public String getEmail() {
+		return email;
+	}
+	public void setEmail(String email) {
+		this.email = email;
+	}
+	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 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;
+	}
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("Institutions [id=");
+		builder.append(id);
+		builder.append(", name=");
+		builder.append(name);
+		builder.append(", fullName=");
+		builder.append(fullName);
+		builder.append(", division=");
+		builder.append(division);
+		builder.append(", country=");
+		builder.append(country);
+		builder.append(", region=");
+		builder.append(region);
+		builder.append(", locality=");
+		builder.append(locality);
+		builder.append(", street=");
+		builder.append(street);
+		builder.append(", address=");
+		builder.append(address);
+		builder.append(", contact=");
+		builder.append(contact);
+		builder.append(", postalCode=");
+		builder.append(postalCode);
+		builder.append(", phone=");
+		builder.append(phone);
+		builder.append(", fax=");
+		builder.append(fax);
+		builder.append(", email=");
+		builder.append(email);
+		builder.append(", description=");
+		builder.append(description);
+		builder.append(", status=");
+		builder.append(status);
+		builder.append(", createdBy=");
+		builder.append(createdBy);
+		builder.append(", createdDate=");
+		builder.append(createdDate);
+		builder.append(", modifiedBy=");
+		builder.append(modifiedBy);
+		builder.append(", modifiedDate=");
+		builder.append(modifiedDate);
+		builder.append("]");
+		return builder.toString();
+	}
+
+}

+ 62 - 48
maxkey-core/src/main/java/org/maxkey/entity/SocialsProvider.java

@@ -60,6 +60,8 @@ public class SocialsProvider extends JpaBaseEntity implements Serializable {
     @Column
     private long sortIndex;
     @Column
+    private String scanCode;
+    @Column
     private int status;
     @Column
 	private String instId;
@@ -261,7 +263,15 @@ public class SocialsProvider extends JpaBaseEntity implements Serializable {
         this.sortIndex = sortIndex;
     }
 
-    public String getInstId() {
+    public String getScanCode() {
+		return scanCode;
+	}
+
+	public void setScanCode(String scanCode) {
+		this.scanCode = scanCode;
+	}
+
+	public String getInstId() {
 		return instId;
 	}
 
@@ -270,53 +280,57 @@ public class SocialsProvider extends JpaBaseEntity implements Serializable {
 	}
 
 	@Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("SocialsProvider [id=");
-        builder.append(id);
-        builder.append(", provider=");
-        builder.append(provider);
-        builder.append(", providerName=");
-        builder.append(providerName);
-        builder.append(", icon=");
-        builder.append(icon);
-        builder.append(", clientId=");
-        builder.append(clientId);
-        builder.append(", clientSecret=");
-        builder.append(clientSecret);
-        builder.append(", agentId=");
-        builder.append(agentId);
-        builder.append(", sortOrder=");
-        builder.append(sortOrder);
-        builder.append(", hidden=");
-        builder.append(hidden);
-        builder.append(", status=");
-        builder.append(status);
-        builder.append(", createdBy=");
-        builder.append(createdBy);
-        builder.append(", createdDate=");
-        builder.append(createdDate);
-        builder.append(", modifiedBy=");
-        builder.append(modifiedBy);
-        builder.append(", modifiedDate=");
-        builder.append(modifiedDate);
-        builder.append(", redirectUri=");
-        builder.append(redirectUri);
-        builder.append(", accountId=");
-        builder.append(accountId);
-        builder.append(", bindTime=");
-        builder.append(bindTime);
-        builder.append(", unBindTime=");
-        builder.append(unBindTime);
-        builder.append(", lastLoginTime=");
-        builder.append(lastLoginTime);
-        builder.append(", state=");
-        builder.append(state);
-        builder.append(", userBind=");
-        builder.append(userBind);
-        builder.append("]");
-        return builder.toString();
-    }
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("SocialsProvider [id=");
+		builder.append(id);
+		builder.append(", provider=");
+		builder.append(provider);
+		builder.append(", providerName=");
+		builder.append(providerName);
+		builder.append(", icon=");
+		builder.append(icon);
+		builder.append(", clientId=");
+		builder.append(clientId);
+		builder.append(", clientSecret=");
+		builder.append(clientSecret);
+		builder.append(", agentId=");
+		builder.append(agentId);
+		builder.append(", hidden=");
+		builder.append(hidden);
+		builder.append(", sortIndex=");
+		builder.append(sortIndex);
+		builder.append(", scanCode=");
+		builder.append(scanCode);
+		builder.append(", status=");
+		builder.append(status);
+		builder.append(", instId=");
+		builder.append(instId);
+		builder.append(", createdBy=");
+		builder.append(createdBy);
+		builder.append(", createdDate=");
+		builder.append(createdDate);
+		builder.append(", modifiedBy=");
+		builder.append(modifiedBy);
+		builder.append(", modifiedDate=");
+		builder.append(modifiedDate);
+		builder.append(", redirectUri=");
+		builder.append(redirectUri);
+		builder.append(", accountId=");
+		builder.append(accountId);
+		builder.append(", bindTime=");
+		builder.append(bindTime);
+		builder.append(", unBindTime=");
+		builder.append(unBindTime);
+		builder.append(", lastLoginTime=");
+		builder.append(lastLoginTime);
+		builder.append(", state=");
+		builder.append(state);
+		builder.append(", userBind=");
+		builder.append(userBind);
+		builder.append("]");
+		return builder.toString();
+	}
 	
 	
 

+ 88 - 0
maxkey-core/src/main/java/org/maxkey/entity/SocialsProviderLogin.java

@@ -0,0 +1,88 @@
+/*
+ * 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.entity;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Crystal.Sea
+ *
+ */
+
+public class SocialsProviderLogin implements Serializable {
+
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = -2672107566766342357L;
+	
+	List<SocialsProvider> socialSignOnProviders = new ArrayList<SocialsProvider>();
+	
+	String dingTalkLogin 		= "none";
+	
+	String workWeixinLogin 		= "none";
+	
+	String feiShuLogin 			= "none";
+	
+	String weLinkLogin 			= "none";
+
+	public SocialsProviderLogin(List<SocialsProvider> socialSignOnProviders) {
+		super();
+		this.socialSignOnProviders = socialSignOnProviders;
+	}
+
+	public String getDingTalkLogin() {
+		return dingTalkLogin;
+	}
+
+	public void setDingTalkLogin(String dingTalkLogin) {
+		this.dingTalkLogin = dingTalkLogin;
+	}
+
+	public String getWorkWeixinLogin() {
+		return workWeixinLogin;
+	}
+
+	public void setWorkWeixinLogin(String workWeixinLogin) {
+		this.workWeixinLogin = workWeixinLogin;
+	}
+
+	public String getFeiShuLogin() {
+		return feiShuLogin;
+	}
+
+	public void setFeiShuLogin(String feiShuLogin) {
+		this.feiShuLogin = feiShuLogin;
+	}
+
+	public String getWeLinkLogin() {
+		return weLinkLogin;
+	}
+
+	public void setWeLinkLogin(String weLinkLogin) {
+		this.weLinkLogin = weLinkLogin;
+	}
+
+	public List<SocialsProvider> getSocialSignOnProviders() {
+		return socialSignOnProviders;
+	}
+
+	
+}

+ 81 - 0
maxkey-core/src/main/java/org/maxkey/persistence/db/InstitutionService.java

@@ -0,0 +1,81 @@
+/*
+ * 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.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.maxkey.constants.ConstantsStatus;
+import org.maxkey.constants.ConstantsTimeInterval;
+import org.maxkey.entity.Institutions;
+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 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;
+
+    protected static final Cache<String, Institutions> institutionsStore = 
+            Caffeine.newBuilder()
+                .expireAfterWrite(ConstantsTimeInterval.ONE_HOUR, TimeUnit.MINUTES)
+                .build();
+    
+    protected JdbcTemplate jdbcTemplate;
+    
+    public InstitutionService(JdbcTemplate jdbcTemplate) {
+        this.jdbcTemplate = jdbcTemplate;
+    }
+        
+    public Institutions findByDomain(String domain) {
+        _logger.trace(" domain {}" , domain);
+        Institutions inst = institutionsStore.getIfPresent(domain);
+        if(inst == null) {
+	        List<Institutions> institutions = 
+	        		jdbcTemplate.query(SELECT_STATEMENT,new InstitutionsRowMapper(),domain);
+	        
+	        if (institutions != null && institutions.size() > 0) {
+	        	inst = institutions.get(0);
+	        }
+	        
+	        institutionsStore.put(domain, inst);
+        }
+        
+        return inst;
+    }
+    
+    public class InstitutionsRowMapper implements RowMapper<Institutions> {
+        @Override
+        public Institutions mapRow(ResultSet rs, int rowNum) throws SQLException {
+        	Institutions institution = new Institutions();
+        	institution.setId(rs.getString("id"));
+        	institution.setName(rs.getString("name"));
+        	institution.setFullName(rs.getString("fullname"));
+        	institution.setLogo(rs.getString("logo"));
+        	institution.setDomain(rs.getString("domain"));
+            return institution;
+        }
+    }
+}

+ 3 - 5
maxkey-core/src/main/java/org/maxkey/web/WebConstants.java

@@ -47,6 +47,8 @@ public class WebConstants {
                                     = "current_user_password_set_type";
 
     public static final  String CURRENT_MESSAGE = "current_message";
+    
+    public static final  String CURRENT_INST 	= "current_inst";
 
     // SPRING_SECURITY_SAVED_REQUEST
     public static final  String FIRST_SAVED_REQUEST_PARAMETER 
@@ -92,11 +94,7 @@ public class WebConstants {
     	public static final  String PASSWORD_ERROE 	= "password error";
     	public static final  String USER_NOT_EXIST 	= "user not exist";
     	public static final  String USER_LOCKED 	= "locked";
-    	public static final  String USER_INACTIVE 	= "inactive";
-    	
-    	
-    	
-    	
+    	public static final  String USER_INACTIVE 	= "inactive";	
     }
 
 }

+ 39 - 0
maxkey-core/src/main/java/org/maxkey/web/WebContext.java

@@ -20,6 +20,7 @@ package org.maxkey.web;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -64,6 +65,8 @@ public final class WebContext {
     
     public static ArrayList<String> sessionAttributeNameList = new ArrayList<String>();
     
+    public static ArrayList<String> logoutAttributeNameList = new ArrayList<String>();
+    
     public static IdGenerator idGenerator;
     
     static {
@@ -76,9 +79,27 @@ public final class WebContext {
         sessionAttributeNameList.add(WebConstants.CURRENT_USER_PASSWORD_SET_TYPE);
         sessionAttributeNameList.add(WebConstants.CURRENT_USER_SESSION_ID);
         
+        sessionAttributeNameList.add(WebConstants.CURRENT_INST);
+        
         sessionAttributeNameList.add(WebConstants.FIRST_SAVED_REQUEST_PARAMETER);
         
         sessionAttributeNameList.add(WebConstants.REMEBER_ME_SESSION);
+        
+        //logout
+        logoutAttributeNameList.add(WebConstants.AUTHENTICATION);
+        
+        logoutAttributeNameList.add(WebConstants.AUTHORIZE_SIGN_ON_APP);
+        logoutAttributeNameList.add(WebConstants.AUTHORIZE_SIGN_ON_APP_SAMLV20_ADAPTER);
+        
+        logoutAttributeNameList.add(WebConstants.CURRENT_USER);
+        logoutAttributeNameList.add(WebConstants.CURRENT_USER_PASSWORD_SET_TYPE);
+        logoutAttributeNameList.add(WebConstants.CURRENT_USER_SESSION_ID);
+        
+        
+        logoutAttributeNameList.add(WebConstants.FIRST_SAVED_REQUEST_PARAMETER);
+        
+        logoutAttributeNameList.add(WebConstants.REMEBER_ME_SESSION);
+        
     }
      
     /**
@@ -238,6 +259,24 @@ public final class WebContext {
         return httpContextPath;
 
     }
+    
+    public static void printRequest(final HttpServletRequest request) {
+    	_logger.trace("getRequestURL : "+request.getRequestURL());
+    	_logger.trace("getMethod : "+request.getMethod());
+        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+          String key = (String) headerNames.nextElement();
+          String value = request.getHeader(key);
+          _logger.trace("Header key "+key +" , value " + value);
+        }
+        
+        Enumeration<String> parameterNames = request.getParameterNames();
+        while (parameterNames.hasMoreElements()) {
+          String key = (String) parameterNames.nextElement();
+          String value = request.getParameter(key);
+          _logger.trace("Parameter "+key +" , value " + value);
+        }
+    }
 
     /**
      * get current Session.

+ 78 - 0
maxkey-core/src/main/java/org/maxkey/web/WebInstRequestFilter.java

@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.maxkey.configuration.ApplicationConfig;
+import org.maxkey.entity.Institutions;
+import org.maxkey.persistence.db.InstitutionService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.filter.GenericFilterBean;
+
+public class WebInstRequestFilter  extends GenericFilterBean {
+	final static Logger _logger = LoggerFactory.getLogger(GenericFilterBean.class);	
+	
+	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 {
+		_logger.trace("WebInstRequestFilter");
+		HttpServletRequest request= ((HttpServletRequest)servletRequest);
+		
+		if(request.getSession().getAttribute(WebConstants.CURRENT_INST) == null) {
+			WebContext.printRequest(request);
+			String host = request.getHeader(HEADER_HOST);
+			if(StringUtils.isEmpty(host)) {
+				host = applicationConfig.getDomainName();
+			}
+			if(host.indexOf(":")> -1 ) {
+				host = host.split(":")[0];
+			}
+			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());
+		}
+        chain.doFilter(servletRequest, servletResponse);
+	}
+
+	public WebInstRequestFilter(InstitutionService institutionService,ApplicationConfig applicationConfig) {
+		super();
+		this.institutionService = institutionService;
+		this.applicationConfig = applicationConfig;
+	}
+
+}

+ 15 - 0
maxkey-core/src/main/java/org/maxkey/web/tag/LocaleTagDirective.java

@@ -25,7 +25,11 @@ import freemarker.template.TemplateModel;
 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.web.WebContext;
+import org.maxkey.web.WebInstRequestFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -44,6 +48,7 @@ import org.springframework.web.servlet.support.RequestContextUtils;
 @FreemarkerTag("locale")
 public class LocaleTagDirective implements TemplateDirectiveModel {
     private static final Logger _logger = LoggerFactory.getLogger(LocaleTagDirective.class);
+
     @Autowired
     private HttpServletRequest request;
 
@@ -60,6 +65,16 @@ public class LocaleTagDirective implements TemplateDirectiveModel {
         } else if (params.get("code").toString().equals("global.application.version")
                 || params.get("code").toString().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();
+        	}
+        	
+        	if(!message.startsWith("http")) {
+            	message = request.getContextPath() + message;
+            }
         } else {
             _logger.trace("message code " + params.get("code"));
             try {

+ 1 - 1
maxkey-gataway/src/main/resources/application.yml

@@ -1,7 +1,7 @@
 #端口号
 application:
   name: maxkey-gateway-server
-  formatted-version: v3.2.0 GA
+  formatted-version: v3.2.1 GA
 server:
   port: 9000
 spring:

+ 28 - 0
maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/InstitutionsMapper.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright [2020] [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.ibatis.annotations.Select;
+import org.apache.mybatis.jpa.persistence.IJpaBaseMapper;
+import org.maxkey.constants.ConstantsStatus;
+import org.maxkey.entity.Institutions;
+
+public interface InstitutionsMapper extends IJpaBaseMapper<Institutions> {
+
+	@Select("select * from  mxk_institutions where domain = #{value} and status = " + ConstantsStatus.ACTIVE)
+	public Institutions findByDomain(String domain);
+}

+ 45 - 0
maxkey-persistence/src/main/java/org/maxkey/persistence/service/InstitutionsService.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright [2020] [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.Institutions;
+import org.maxkey.persistence.mapper.InstitutionsMapper;
+import org.springframework.stereotype.Repository;
+
+
+@Repository
+public class InstitutionsService  extends JpaBaseService<Institutions>{
+	
+	public InstitutionsService() {
+		super(InstitutionsMapper.class);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.connsec.db.service.BaseService#getMapper()
+	 */
+	@Override
+	public InstitutionsMapper getMapper() {
+		return (InstitutionsMapper)super.getMapper();
+	}
+ 
+	 public Institutions findByDomain(String domain) {
+		 return getMapper().findByDomain(domain);
+	 };
+	 
+}

+ 14 - 29
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/endpoint/TokenEndpointAuthenticationFilter.java

@@ -17,7 +17,6 @@
 package org.maxkey.authz.oauth2.provider.endpoint;
 
 import java.io.IOException;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -32,8 +31,6 @@ import javax.servlet.annotation.WebFilter;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.maxkey.authn.SigninPrincipal;
 import org.maxkey.authz.oauth2.common.OAuth2Constants;
 import org.maxkey.authz.oauth2.common.util.OAuth2Utils;
@@ -44,6 +41,8 @@ import org.maxkey.authz.oauth2.provider.OAuth2RequestFactory;
 import org.maxkey.util.AuthorizationHeaderCredential;
 import org.maxkey.util.AuthorizationHeaderUtils;
 import org.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.security.authentication.AuthenticationDetailsSource;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
@@ -84,7 +83,7 @@ import org.springframework.web.HttpRequestMethodNotSupportedException;
 							OAuth2Constants.ENDPOINT.ENDPOINT_TENCENT_IOA_TOKEN+"/*"})
 public class TokenEndpointAuthenticationFilter implements Filter {
 
-	private static final Log logger = LogFactory.getLog(TokenEndpointAuthenticationFilter.class);
+	final static Logger _logger = LoggerFactory.getLogger(TokenEndpointAuthenticationFilter.class);
 
 	private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
 	boolean allowOnlyPost;
@@ -122,7 +121,7 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 
 	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
 			ServletException {
-		logger.debug("Authentication TokenEndpoint ");
+		_logger.debug("Authentication TokenEndpoint ");
 		if(authenticationManager==null) {
 			authenticationManager= WebContext.getBean("oauth20UserAuthenticationManager",AuthenticationManager.class);
 		}
@@ -133,26 +132,12 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 		    oauth20ClientAuthenticationManager = WebContext.getBean("oauth20ClientAuthenticationManager",AuthenticationManager.class);
 		}
 		
-		final boolean debug = logger.isDebugEnabled();
+		final boolean debug = _logger.isDebugEnabled();
 		final HttpServletRequest request = (HttpServletRequest) req;
 		final HttpServletResponse response = (HttpServletResponse) res;
 
-		if(logger.isTraceEnabled()) {
-			logger.trace("getRequestURL : "+request.getRequestURL());
-			logger.trace("getMethod : "+request.getMethod());
-	        Enumeration<String> headerNames = request.getHeaderNames();
-	        while (headerNames.hasMoreElements()) {
-	          String key = (String) headerNames.nextElement();
-	          String value = request.getHeader(key);
-	          logger.trace("Header key "+key +" , value " + value);
-	        }
-	        
-	        Enumeration<String> parameterNames = request.getParameterNames();
-	        while (parameterNames.hasMoreElements()) {
-	          String key = (String) parameterNames.nextElement();
-	          String value = request.getParameter(key);
-	          logger.trace("Parameter "+key +" , value " + value);
-	        }
+		if(_logger.isTraceEnabled()) {
+			WebContext.printRequest(request);
 		}
 		
 		try {
@@ -162,7 +147,7 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 				usernamepassword(request,response);
 			}else {
 				Authentication authentication=ClientCredentials(request,response);
-				logger.trace("getPrincipal " + authentication.getPrincipal().getClass());
+				_logger.trace("getPrincipal " + authentication.getPrincipal().getClass());
 				SigninPrincipal auth = null;
 				if(authentication.getPrincipal() instanceof SigninPrincipal) {
 					//authorization_code
@@ -181,7 +166,7 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 			SecurityContextHolder.clearContext();
 
 			if (debug) {
-				logger.debug("Authentication request for failed: " + failed);
+				_logger.debug("Authentication request for failed: " + failed);
 			}
 
 			onUnsuccessfulAuthentication(request, response, failed);
@@ -193,17 +178,17 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 	}
 
 	public void usernamepassword(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
-	logger.debug("Authentication TokenEndpoint ");
+		_logger.debug("Authentication TokenEndpoint ");
 	
 	try {
 		Authentication credentials = extractCredentials(request);
 	
 		if (credentials != null) {
-			logger.debug("Authentication credentials found for '" + credentials.getName() + "'");
+			_logger.debug("Authentication credentials found for '" + credentials.getName() + "'");
 	
 			Authentication authResult = authenticationManager.authenticate(credentials);
 	
-			logger.debug("Authentication success: " + authResult.getName());
+			_logger.debug("Authentication success: " + authResult.getName());
 			String clientId = request.getParameter(OAuth2Constants.PARAMETER.CLIENT_ID);
 	        String clientSecret = request.getParameter(OAuth2Constants.PARAMETER.CLIENT_SECRET);
 	        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId,
@@ -237,7 +222,7 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 		catch (AuthenticationException failed) {
 			SecurityContextHolder.clearContext();
 		
-				logger.debug("Authentication request for failed: " + failed);
+			_logger.debug("Authentication request for failed: " + failed);
 		
 			onUnsuccessfulAuthentication(request, response, failed);
 		
@@ -261,7 +246,7 @@ public class TokenEndpointAuthenticationFilter implements Filter {
 				clientSecret=ahc.getCredential();
 			}
 			
-			 logger.trace("clientId "+clientId +" , clientSecret " + clientSecret);
+			_logger.trace("clientId "+clientId +" , clientSecret " + clientSecret);
 
 			// If the request is already authenticated we can assume that this
 			// filter is not needed

+ 1 - 1
maxkey-webs/maxkey-boot-monitor/src/main/resources/application.properties

@@ -18,7 +18,7 @@
 application.title                               =MaxKey
 #for dynamic service discovery
 spring.application.name                         =maxkey-monitor
-application.formatted-version                   =v3.2.0 GA
+application.formatted-version                   =v3.2.1 GA
 #nacos discovery
 spring.cloud.nacos.discovery.enabled            =${NACOS_DISCOVERY_ENABLED:false}
 spring.cloud.nacos.discovery.instance-enabled   =false

+ 5 - 1
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/SocialSignOnListController.java

@@ -24,7 +24,9 @@ import org.maxkey.authn.support.socialsignon.service.SocialSignOnProviderService
 import org.maxkey.authn.support.socialsignon.service.SocialsAssociate;
 import org.maxkey.authn.support.socialsignon.service.SocialsAssociateService;
 import org.maxkey.configuration.ApplicationConfig;
+import org.maxkey.entity.Institutions;
 import org.maxkey.entity.SocialsProvider;
+import org.maxkey.web.WebConstants;
 import org.maxkey.web.WebContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,7 +57,9 @@ public class SocialSignOnListController {
 		
 		ModelAndView modelAndView=new ModelAndView("social/socialSignOnProvider");
 		if(applicationConfig.getLoginConfig().isSocialSignOn()){
-			List<SocialsProvider>  listSocialSignOnProvider= socialSignOnProviderService.getSocialSignOnProviders();
+			Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
+			List<SocialsProvider>  listSocialSignOnProvider = 
+									socialSignOnProviderService.loadSocialsProviders(inst.getId()).getSocialSignOnProviders();
 			
 			SocialsAssociate socialSignOnUser=new SocialsAssociate();
 			socialSignOnUser.setUserId(WebContext.getUserInfo().getId());

+ 8 - 5
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LoginEndpoint.java

@@ -29,6 +29,7 @@ import org.maxkey.authn.LoginCredential;
 import org.maxkey.authn.support.kerberos.KerberosService;
 import org.maxkey.authn.support.socialsignon.service.SocialSignOnProviderService;
 import org.maxkey.configuration.ApplicationConfig;
+import org.maxkey.entity.Institutions;
 import org.maxkey.entity.UserInfo;
 import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
 import org.maxkey.persistence.service.UserInfoService;
@@ -94,8 +95,11 @@ public class LoginEndpoint {
 	 */
 	@Operation(summary  = "登录接口", description  = "用户登录地址",method="GET")
  	@RequestMapping(value={"/login"})
-	public ModelAndView login() {
+	public ModelAndView login(HttpServletRequest request) {
 		_logger.debug("LoginController /login.");
+		
+		WebContext.printRequest(request);
+		
 		boolean isAuthenticated= WebContext.isAuthenticated();
 		
 		if(isAuthenticated){
@@ -123,7 +127,8 @@ public class LoginEndpoint {
 		//load Social Sign On Providers
 		if(applicationConfig.getLoginConfig().isSocialSignOn()){
 			_logger.debug("Load Social Sign On Providers ");
-			modelAndView.addObject("ssopList", socialSignOnProviderService.getSocialSignOnProviders());
+			Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
+			modelAndView.addObject("sspLogin", socialSignOnProviderService.loadSocialsProviders(inst.getId()));
 		}
 		
 		Object loginErrorMessage=WebContext.getAttribute(WebConstants.LOGIN_ERROR_SESSION_MESSAGE);
@@ -152,9 +157,7 @@ public class LoginEndpoint {
  	@RequestMapping("/login/{username}")
 	@ResponseBody
 	public HashMap <String,Object> queryLoginUserAuth(@PathVariable("username") String username) {
- 		UserInfo userInfo=new UserInfo();
- 		userInfo.setUsername(username);
- 		userInfo=userInfoService.load(userInfo);
+ 		UserInfo userInfo=userInfoService.findByUsername(username);
  		
  		HashMap <String,Object> authnType=new HashMap <String,Object>();
  		authnType.put("authnType", userInfo.getAuthnType());

+ 3 - 1
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LogoutEndpoint.java

@@ -148,8 +148,10 @@ public class LogoutEndpoint {
  					WebConstants.ONLINE_TICKET_NAME, 
  					UUID.randomUUID().toString()
  		);
- 		
  		request.getSession().invalidate();
+ 		//for(String removeAttribute : WebContext.logoutAttributeNameList) {
+ 		//	request.getSession().removeAttribute(removeAttribute);
+ 		//}
  		SecurityContextHolder.clearContext();
  		
  		modelAndView.setViewName(viewName);

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/application.properties

@@ -16,7 +16,7 @@
 #MaxKey Title and Version                                                  #
 ############################################################################
 application.title                           =MaxKey
-application.formatted-version               =v3.2.0 GA
+application.formatted-version               =v3.2.1 GA
 #for dynamic service discovery
 spring.application.name                     =maxkey
 ############################################################################

+ 0 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/log4j2.xml

@@ -26,7 +26,6 @@
     	<Logger level="ERROR"	name="org.reflections.Reflections" ></Logger>
     	<Logger level="OFF"     name="org.hibernate.validator.internal.util.Version" ></Logger>
     	
-    	
         <Root  level="INFO">  
             <AppenderRef  ref="consolePrint" />
             <AppenderRef  ref="RollingFile" /> 

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/layout/nologintop.ftl

@@ -2,7 +2,7 @@
 <div class="container">
 	<div class="row">
 			<div class="col-sm-6">
-				<div style="float:left;margin-left:20px;margin-top: 5px;"><IMG SRC="<@base/>/static/images/logo.jpg" style="width:55px;heigth:55px"></div>
+				<div style="float:left;margin-left:20px;margin-top: 5px;"><IMG SRC="<@locale code="global.logo"/>" style="width:55px;heigth:55px"></div>
 				<div style="margin-top:15px;margin-left:10px;float:left">
 					<div style="letter-spacing:2px;font-size:24px;font-weight:bolder;"><@locale code="global.application"/></div>
 				</div>

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/layout/top.ftl

@@ -3,7 +3,7 @@
     <div class="container row">
     	<div class="col-sm-5">
     		<div>
-    		<div style="float:left;margin-top: 5px;"><IMG SRC="<@base/>/static/images/logo.jpg" style="width:55px;heigth:55px"></div>
+    		<div style="float:left;margin-top: 5px;"><IMG SRC="<@locale code="global.logo"/>" style="width:55px;heigth:55px"></div>
     		<div style="letter-spacing:2px;font-size:24px;font-weight:bolder;margin-top: 16px;float:left;"><@locale code="global.application"/></div>
     		</div>
     	</div>

+ 8 - 4
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/login.ftl

@@ -78,8 +78,12 @@
 								<#include "loginmobile.ftl">
 							</div>
 							<div id="div_qrcodelogin">
-							     <#include "loginworkweixin.ftl"> 
-							     <#-- <#include "logindingtalk.ftl">-->
+							     <#if sspLogin.workWeixinLogin != 'none'>
+							         <#include "loginscanworkweixin.ftl"> 
+							     </#if>  
+							     <#if sspLogin.dingTalkLogin != 'none'>  
+							         <#include "loginscandingtalk.ftl">
+							     </#if>  
 							</div>
 						</td>
 					</tr>
@@ -91,7 +95,7 @@
 					      			<td colspan="3" align="left"><@locale code="login.text.otherlogins"/>:</td>
 					      		</tr>
 					      		
-					      		<#list ssopList as ssop>
+					      		<#list sspLogin.socialSignOnProviders as ssop>
 					      			<#if (ssop_index)%4==0>
 						      			<tr>
 						      		</#if>
@@ -104,7 +108,7 @@
 						      		</tr>
 						      		</#if>
 						      	</#list>
-						      	<#if (ssopList?size)%4!=0>
+						      	<#if (sspLogin.socialSignOnProviders?size)%4!=0>
 						      		</tr>
 						      	</#if>
 					      	</table>

+ 7 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/logindingtalk.ftl → maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/loginscandingtalk.ftl

@@ -1,6 +1,12 @@
+     <#if sspLogin.dingTalkLogin == 'https'> 
      <script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
-     var dingtalkredirect_uri="";
+     </#if>  
+     <#if sspLogin.dingTalkLogin == 'http'> 
+     <script src="http://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
+     </#if>  
+     
      <script type="text/javascript"> 
+        var dingtalkredirect_uri="";
         var handleMessage = function (event) {
         var origin = event.origin;
         console.log("origin", event.origin);

+ 5 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/loginworkweixin.ftl → maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/loginscanworkweixin.ftl

@@ -1,4 +1,9 @@
+     <#if sspLogin.workWeixinLogin == 'https'> 
      <script type="text/javascript" src="https://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.4.js"></script>
+     </#if>  
+     <#if sspLogin.workWeixinLogin == 'http'> 
+     <script type="text/javascript" src="http://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.4.js"></script>
+     </#if>  
      <script type="text/javascript"> 
         $(function(){
            $("#qrcodelogin").on("click",function(){

+ 1 - 0
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java

@@ -129,6 +129,7 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer {
                 .addPathPatterns("/session/**")
                 .addPathPatterns("/socialsprovider/**")
                 .addPathPatterns("/accountsstrategy/**")
+                .addPathPatterns("/institutions/**")
                 
                 ;
         

+ 73 - 0
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/contorller/InstitutionsController.java

@@ -0,0 +1,73 @@
+/*
+ * Copyright [2020] [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.contorller;
+
+import org.maxkey.constants.ConstantsOperateMessage;
+import org.maxkey.entity.Institutions;
+import org.maxkey.persistence.service.InstitutionsService;
+import org.maxkey.web.WebContext;
+import org.maxkey.web.message.Message;
+import org.maxkey.web.message.MessageType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.servlet.ModelAndView;
+
+@Controller
+@RequestMapping(value={"/institutions"})
+public class InstitutionsController {
+
+
+		final static Logger _logger = LoggerFactory.getLogger(InstitutionsController.class);
+		
+		@Autowired
+		private InstitutionsService institutionsService;
+		
+		/**
+		 * 读取
+		 * @return
+		 */
+		@RequestMapping(value={"/forward"})
+		public ModelAndView forward(){
+			Institutions institutions = institutionsService.get(WebContext.getUserInfo().getInstId());
+			return new ModelAndView("institutions/updateInstitutions","model",institutions);
+		}
+		
+		/**
+		 * 更新
+		 * @param sysConfig
+		 * @return
+		 */
+		@RequestMapping(value={"/update"})
+		@ResponseBody
+		public Message updat(@ModelAttribute("institutions") Institutions institutions,BindingResult result) {
+			_logger.debug("updateRole institutions : "+institutions);
+			if(institutionsService.update(institutions)) {
+				return new Message(WebContext.getI18nValue(ConstantsOperateMessage.UPDATE_SUCCESS),MessageType.success);
+			} else {
+				return new Message(WebContext.getI18nValue(ConstantsOperateMessage.UPDATE_ERROR),MessageType.error);
+			}
+		}
+		
+
+}

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/resources/application.properties

@@ -16,7 +16,7 @@
 #MaxKey Title and Version                                                  #
 ############################################################################
 application.title                               =MaxKey-Mgt
-application.formatted-version                   =v3.2.0 GA
+application.formatted-version                   =v3.2.1 GA
 #for dynamic service discovery
 spring.application.name                         =maxkey-mgt
 ############################################################################

+ 21 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message.properties

@@ -468,6 +468,10 @@ socials.provider.clientId=\u51ED\u8BC1
 socials.provider.clientSecret=\u5BC6\u94A5
 socials.provider.agentId=AgentId
 socials.provider.hidden=\u9690\u85CF
+socials.provider.scanCode=\u626B\u7801\u767B\u5F55
+socials.provider.scanCode.none=\u4E0D\u652F\u6301
+socials.provider.scanCode.https=\u652F\u6301https
+socials.provider.scanCode.http=\u652F\u6301http
 #synchronizers
 synchronizers.id=\u7F16\u53F7
 synchronizers.name=\u540C\u6B65\u5668\u540D\u79F0
@@ -486,6 +490,22 @@ synchronizers.trustStorePassword=\u8BC1\u4E66\u5BC6\u94A5
 synchronizers.resumeTime=\u6062\u590D\u65F6\u95F4
 synchronizers.suspendTime=\u6302\u8D77\u65F6\u95F4
 synchronizers.syncStartTime=\u533A\u95F4
+
+institutions.name=\u7B80\u79F0
+institutions.fullName=\u5168\u79F0
+institutions.logo=\u56FE\u6807
+institutions.domain=\u57DF\u540D
+institutions.division=\u5206\u652F\u673A\u6784
+institutions.contact=\u8054\u7CFB\u4EBA
+institutions.phone=\u7535\u8BDD
+institutions.email=\u90AE\u7BB1
+institutions.fax=\u4F20\u771F
+institutions.country=\u56FD\u5BB6
+institutions.region=\u7701/\u5DDE
+institutions.locality=\u5E02
+institutions.street=\u8857\u9053
+institutions.address=\u5730\u5740
+institutions.postalcode=\u90AE\u7F16
 #button
 button.text.action=\u8BBF\u95EE
 button.text.visit=\u8BBF\u95EE
@@ -607,5 +627,6 @@ navs.role.permissions=\u6743\u9650\u7BA1\u7406
 navs.resources=\u8D44\u6E90\u7BA1\u7406
 navs.adapters=\u9002\u914D\u5668\u6CE8\u518C
 navs.notices=\u901A\u77E5\u516C\u544A
+navs.institutions=\u673A\u6784\u914D\u7F6E
 navs.socials.provider=\u793E\u4EA4\u670D\u52A1
 navs.synchronizers=\u540C\u6B65\u5668\u7BA1\u7406

+ 20 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_en.properties

@@ -476,6 +476,10 @@ socials.provider.clientId=ClientId
 socials.provider.clientSecret=ClientSecret
 socials.provider.agentId=AgentId
 socials.provider.hidden=Hidden
+socials.provider.scanCode=ScanCode
+socials.provider.scanCode.none=None
+socials.provider.scanCode.https=https
+socials.provider.scanCode.http=http
 
 #synchronizers
 synchronizers.id=id
@@ -496,6 +500,21 @@ synchronizers.resumeTime=resumeTime
 synchronizers.suspendTime=suspendTime
 synchronizers.syncStartTime=During
 
+institutions.name=name
+institutions.fullName=fullName
+institutions.logo=Logo
+institutions.domain=domainName
+institutions.division=division
+institutions.contact=contact
+institutions.phone=phone
+institutions.email=email
+institutions.fax=fax
+institutions.country=country
+institutions.region=region
+institutions.locality=locality
+institutions.street=street
+institutions.address=address
+institutions.postalcode=postalcode
  
 button.text.action=Action
 button.text.visit=Visit
@@ -617,5 +636,6 @@ navs.role.permissions=Permissions
 navs.resources=Resources
 navs.adapters=Adapters
 navs.notices=Notices
+navs.institutions=Institutions
 navs.socials.provider=SocialsProvider
 navs.synchronizers=Synchronizers

+ 22 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/messages/message_zh_CN.properties

@@ -468,6 +468,10 @@ socials.provider.clientId=\u51ED\u8BC1
 socials.provider.clientSecret=\u5BC6\u94A5
 socials.provider.agentId=AgentId
 socials.provider.hidden=\u9690\u85CF
+socials.provider.scanCode=\u626B\u7801\u767B\u5F55
+socials.provider.scanCode.none=\u4E0D\u652F\u6301
+socials.provider.scanCode.https=\u652F\u6301https
+socials.provider.scanCode.http=\u652F\u6301http
 #synchronizers
 synchronizers.id=\u7F16\u53F7
 synchronizers.name=\u540C\u6B65\u5668\u540D\u79F0
@@ -486,6 +490,23 @@ synchronizers.trustStorePassword=\u8BC1\u4E66\u5BC6\u94A5
 synchronizers.resumeTime=\u6062\u590D\u65F6\u95F4
 synchronizers.suspendTime=\u6302\u8D77\u65F6\u95F4
 synchronizers.syncStartTime=\u533A\u95F4
+
+institutions.name=\u7B80\u79F0
+institutions.fullName=\u5168\u79F0
+institutions.logo=\u56FE\u6807
+institutions.domain=\u57DF\u540D
+institutions.division=\u5206\u652F\u673A\u6784
+institutions.contact=\u8054\u7CFB\u4EBA
+institutions.phone=\u7535\u8BDD
+institutions.email=\u90AE\u7BB1
+institutions.fax=\u4F20\u771F
+institutions.country=\u56FD\u5BB6
+institutions.region=\u7701/\u5DDE
+institutions.locality=\u5E02
+institutions.street=\u8857\u9053
+institutions.address=\u5730\u5740
+institutions.postalcode=\u90AE\u7F16
+
 #button
 button.text.action=\u8BBF\u95EE
 button.text.visit=\u8BBF\u95EE
@@ -607,5 +628,6 @@ navs.role.permissions=\u6743\u9650\u7BA1\u7406
 navs.resources=\u8D44\u6E90\u7BA1\u7406
 navs.adapters=\u9002\u914D\u5668\u6CE8\u518C
 navs.notices=\u901A\u77E5\u516C\u544A
+navs.institutions=\u673A\u6784\u914D\u7F6E
 navs.socials.provider=\u793E\u4EA4\u670D\u52A1
 navs.synchronizers=\u540C\u6B65\u5668\u7BA1\u7406

+ 225 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/institutions/updateInstitutions.ftl

@@ -0,0 +1,225 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<#include  "../layout/header.ftl"/>
+	<#include  "../layout/common.cssjs.ftl"/>
+</head>
+<body> 
+<div class="app header-default side-nav-dark">
+<div class="layout">
+	<div class="header navbar">
+		<#include  "../layout/top.ftl"/>
+	</div>
+	
+	<div class="col-md-3 sidebar-nav side-nav" >
+ 		<#include  "../layout/sidenav.ftl"/>
+	</div>
+	<div class="page-container">
+	
+	<div class="main-content">
+		<div class="container-fluid">
+			<div class="breadcrumb-wrapper row">
+				<div class="col-12 col-lg-3 col-md-6">
+					<h4 class="page-title"><@locale code="navs.institutions"/></h4>
+				</div>
+				<div class="col-12 col-lg-9 col-md-6">
+					<ol class="breadcrumb float-right">
+						<li><a href="<@base/>/main"><@locale code="navs.home"/></a></li>
+						<li class="inactive">/ <@locale code="navs.conf"/></li>
+						<li class="active">/ <@locale code="navs.institutions"/></li>
+					</ol>
+				</div>
+			</div>
+		</div>
+		<div class="container-fluid">
+			<div class="content-wrapper row">
+			<div class="col-12 grid-margin">
+				<div class="card">
+					<div class="card-header border-bottom">
+						<h4 class="card-title"><@locale code="navs.institutions"/></h4>
+					</div>
+					<div class="card-body">
+								<form  method="post" type="label" validate="true" action="<@base/>/institutions/update" id="actionForm"   class="needs-validation" novalidate>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="institutions.name" />:</label>
+												<div class="col-sm-9">
+													<input id="id" name="id" type="hidden" value="${model.id!}"/>
+						   							<input  required="" class="form-control" type="text" id="name" name="name"  value="${model.name!}" />
+												</div>
+											</div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="institutions.fullName" />:</label>
+												<div class="col-sm-9">
+													<input required=""  class="form-control" type="text" id="fullName" name="fullName" value="${model.fullName!}" />
+												</div>
+											</div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="institutions.logo" />:</label>
+												<div class="col-sm-9">
+													<input  required="" class="form-control" type="text" id="logo" name="logo"  value="${model.logo!}" />
+												</div>
+											</div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="institutions.domain" />:</label>
+												<div class="col-sm-9">
+													<input  required="" class="form-control" type="text" id="domain" name="domain" value="${model.domain!}" />
+												</div>
+											</div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="institutions.division" />:</label>
+												<div class="col-sm-9">
+													<input   class="form-control" type="text" id="division" name="division" value="${model.division!}"/>
+												</div>
+											</div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3"><@locale code="institutions.contact" />:</label>
+												<div class="col-sm-9">
+													<input    class="form-control" type="text" id="contact" name="contact"  value="${model.contact!}" />
+												</div>
+											</div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="institutions.phone" />:</label>
+												<div class="col-sm-9">
+													<input   class="form-control" type="text" id="phone" name="phone" value="${model.phone!}" />
+												</div>
+											</div>
+										</div>
+										
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.email" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input   class="form-control" type="text" id="email" name="email" value="${model.email!}" />
+                                                </div>
+                                            </div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.fax" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input   class="form-control" type="text" id="fax" name="fax" value="${model.fax!}" />
+                                                </div>
+                                            </div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.postalcode" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input   class="form-control" type="text" id="postalCode" name="postalCode"  value="${model.postalCode!}" />
+                                                </div>
+                                            </div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.country" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input   class="form-control" type="text" id="country" name="country" value="${model.country!}" />
+                                                </div>
+                                            </div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.region" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input   class="form-control" type="text" id="region" name="region" value="${model.region!}" />
+                                                </div>
+                                            </div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.locality" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input  class="form-control" type="text" id="locality" name="locality" value="${model.locality!}" />
+                                                </div>
+                                            </div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+                                                <label class="col-sm-3 col-form-label"><@locale code="institutions.street" />:</label>
+                                                <div class="col-sm-9">
+                                                    <input   class="form-control" type="text" id="street" name="street" value="${model.street!}" />
+                                                </div>
+                                            </div>
+										</div>
+									</div>
+									<div class="row mb-3">
+										<div class="col-md-12">
+                                            <div class="form-group row">
+                                                <div class="col-sm-2">
+												    <label class="col-form-label"><@locale code="institutions.address" />:</label>
+												</div>
+												<div class="col-sm-10">
+													<input   class="form-control" type="text" id="address" name="address"  value="${model.address!}" />
+												</div>
+											</div>
+										</div>
+									</div>
+                                    <div class="row mb-3">
+                                        <div class="col-md-12">
+                                            <div class="form-group row">
+                                                <div class="col-sm-2">
+                                                    <label class="col-form-label"><@locale code="common.text.description" />:</label>
+                                                </div>
+                                                <div class="col-sm-10">
+                                                    <input   class="form-control" type="text" id="description" name="description"  value="${model.description!}" />
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+									<div class="row">
+										<div class="col-md-4"></div>
+										<div class="col-md-4">
+											<button type="submit" class="button btn-primary btn btn-common btn-block mr-3"    id="submitBtn" ><@locale code="button.text.save" /></button>
+										</div>
+										<div class="col-md-4"></div>
+									</div>
+									
+								</form>
+							</div>
+						</div>
+					</div>
+				</div>
+					<footer class="content-footer">
+		<#include  "../layout/footer.ftl"/>
+	</footer>
+
+	</div>
+	
+	</div>
+</div>
+
+<div id="preloader">
+<div class="loader" id="loader-1"></div>
+</div>
+
+</body>
+</html>

+ 6 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/layout/sidenav.ftl

@@ -136,6 +136,12 @@
              </a>
            </li>
            <li>
+             <a class="side-nav-menu" href="<@base />/institutions/forward/">
+                <@locale code="navs.institutions"/>
+                 <span class="fa fa-fw fa-balance-scale"></span>
+             </a>
+           </li>
+           <li>
              <a class="side-nav-menu" href="<@base />/config/passwordpolicy/forward/">
                 <@locale code="navs.conf.passwordpolicy"/>
                  <span class="fa fa-fw fa-balance-scale"></span>

+ 10 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/socialsprovider/socialsProviderAdd.ftl

@@ -60,6 +60,16 @@
                     </td>
             </tr>
             <tr>
+                    <th><@locale code="socials.provider.scanCode" />:</th>
+                    <td nowrap>
+                        <select  id="hidden" name="scanCode" class="form-control  form-select" >
+                            <option value="none" selected><@locale code="socials.provider.scanCode.none"/></option>
+                            <option value="https" ><@locale code="socials.provider.scanCode.https"/></option>
+                            <option value="http" ><@locale code="socials.provider.scanCode.http"/></option>
+                        </select>
+                    </td>
+            </tr>
+            <tr>
                     <th><@locale code="common.text.sortindex" />:</th>
                     <td nowrap>
                         <input type="text" id="sortIndex" name="sortIndex" class="form-control" title="" value=""  required="" />

+ 10 - 0
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/socialsprovider/socialsProviderUpdate.ftl

@@ -63,6 +63,16 @@
                 </td>
         </tr>
         <tr>
+                    <th><@locale code="socials.provider.scanCode" />:</th>
+                    <td nowrap>
+                        <select  id="hidden" name="scanCode" class="form-control  form-select" >
+                            <option value="none" <#if 'none'==model.scanCode!>selected</#if>><@locale code="socials.provider.scanCode.none"/></option>
+                            <option value="https" <#if 'https'==model.scanCode!>selected</#if>><@locale code="socials.provider.scanCode.https"/></option>
+                            <option value="http" <#if 'http'==model.scanCode!>selected</#if>><@locale code="socials.provider.scanCode.http"/></option>
+                        </select>
+                    </td>
+            </tr>
+        <tr>
                 <th><@locale code="common.text.sortindex" />:</th>
                 <td nowrap>
                     <input type="text" id="sortIndex" name="sortIndex" class="form-control" title="" value="${model.sortIndex!}"  required="" />