Commit 03bcbf23043bba90da6ca62eb4c809eca2153253

Authored by Volodymyr Babak
2 parents 1c2361fe 92c9bc0a

Merge remote-tracking branch 'upstream/master'

... ... @@ -31,9 +31,11 @@ import org.thingsboard.server.dao.customer.CustomerService;
31 31 import org.thingsboard.server.dao.oauth2.OAuth2User;
32 32 import org.thingsboard.server.dao.tenant.TenantService;
33 33 import org.thingsboard.server.dao.user.UserService;
  34 +import org.thingsboard.server.service.install.InstallScripts;
34 35 import org.thingsboard.server.service.security.model.SecurityUser;
35 36 import org.thingsboard.server.service.security.model.UserPrincipal;
36 37
  38 +import java.io.IOException;
37 39 import java.util.List;
38 40 import java.util.Optional;
39 41 import java.util.concurrent.locks.Lock;
... ... @@ -51,6 +53,9 @@ public abstract class AbstractOAuth2ClientMapper {
51 53 @Autowired
52 54 private CustomerService customerService;
53 55
  56 + @Autowired
  57 + private InstallScripts installScripts;
  58 +
54 59 private final Lock userCreationLock = new ReentrantLock();
55 60
56 61 protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, boolean allowUserCreation) {
... ... @@ -84,6 +89,9 @@ public abstract class AbstractOAuth2ClientMapper {
84 89 user.setLastName(oauth2User.getLastName());
85 90 user = userService.saveUser(user);
86 91 }
  92 + } catch (Exception e) {
  93 + log.error("Can't get or create security user from oauth2 user", e);
  94 + throw new RuntimeException("Can't get or create security user from oauth2 user", e);
87 95 } finally {
88 96 userCreationLock.unlock();
89 97 }
... ... @@ -98,13 +106,14 @@ public abstract class AbstractOAuth2ClientMapper {
98 106 }
99 107 }
100 108
101   - private TenantId getTenantId(String tenantName) {
  109 + private TenantId getTenantId(String tenantName) throws IOException {
102 110 List<Tenant> tenants = tenantService.findTenants(new TextPageLink(1, tenantName)).getData();
103 111 Tenant tenant;
104 112 if (tenants == null || tenants.isEmpty()) {
105 113 tenant = new Tenant();
106 114 tenant.setTitle(tenantName);
107 115 tenant = tenantService.saveTenant(tenant);
  116 + installScripts.createDefaultRuleChains(tenant.getId());
108 117 } else {
109 118 tenant = tenants.get(0);
110 119 }
... ...
... ... @@ -100,34 +100,52 @@ security:
100 100 basic:
101 101 enabled: "${SECURITY_BASIC_ENABLED:false}"
102 102 oauth2:
  103 + # Enable/disable OAuth 2 login functionality
  104 + # For details please refer to https://thingsboard.io/docs/user-guide/oauth-2-support/
103 105 enabled: "${SECURITY_OAUTH2_ENABLED:false}"
  106 + # Redirect URL where access code from external user management system will be processed
104 107 loginProcessingUrl: "${SECURITY_OAUTH2_LOGIN_PROCESSING_URL:/login/oauth2/code/}"
  108 + # List of SSO clients
105 109 clients:
106 110 default:
107   - loginButtonLabel: "${SECURITY_OAUTH2_DEFAULT_LOGIN_BUTTON_LABEL:Default}" # Label that going to be show on login screen
108   - loginButtonIcon: "${SECURITY_OAUTH2_DEFAULT_LOGIN_BUTTON_ICON:}" # Icon that going to be show on login screen. Material design icon ID (https://material.angularjs.org/latest/api/directive/mdIcon)
  111 + # Label that going to be show on login button - 'Login with {loginButtonLabel}'
  112 + loginButtonLabel: "${SECURITY_OAUTH2_DEFAULT_LOGIN_BUTTON_LABEL:Default}"
  113 + # Icon that going to be show on login button. Material design icon ID (https://material.angularjs.org/latest/api/directive/mdIcon)
  114 + loginButtonIcon: "${SECURITY_OAUTH2_DEFAULT_LOGIN_BUTTON_ICON:}"
109 115 clientName: "${SECURITY_OAUTH2_DEFAULT_CLIENT_NAME:ClientName}"
110 116 clientId: "${SECURITY_OAUTH2_DEFAULT_CLIENT_ID:}"
111 117 clientSecret: "${SECURITY_OAUTH2_DEFAULT_CLIENT_SECRET:}"
112 118 accessTokenUri: "${SECURITY_OAUTH2_DEFAULT_ACCESS_TOKEN_URI:}"
113 119 authorizationUri: "${SECURITY_OAUTH2_DEFAULT_AUTHORIZATION_URI:}"
114 120 scope: "${SECURITY_OAUTH2_DEFAULT_SCOPE:}"
115   - redirectUriTemplate: "${SECURITY_OAUTH2_DEFAULT_REDIRECT_URI_TEMPLATE:http://localhost:8080/login/oauth2/code/}" # Must be in sync with security.oauth2.loginProcessingUrl
  121 + # Redirect URL that must be in sync with 'security.oauth2.loginProcessingUrl', but domain name added
  122 + redirectUriTemplate: "${SECURITY_OAUTH2_DEFAULT_REDIRECT_URI_TEMPLATE:http://localhost:8080/login/oauth2/code/}"
116 123 jwkSetUri: "${SECURITY_OAUTH2_DEFAULT_JWK_SET_URI:}"
117   - authorizationGrantType: "${SECURITY_OAUTH2_DEFAULT_AUTHORIZATION_GRANT_TYPE:authorization_code}" # authorization_code, implicit, refresh_token or client_credentials
  124 + # 'authorization_code', 'implicit', 'refresh_token' or 'client_credentials'
  125 + authorizationGrantType: "${SECURITY_OAUTH2_DEFAULT_AUTHORIZATION_GRANT_TYPE:authorization_code}"
118 126 clientAuthenticationMethod: "${SECURITY_OAUTH2_DEFAULT_CLIENT_AUTHENTICATION_METHOD:post}" # basic or post
119 127 userInfoUri: "${SECURITY_OAUTH2_DEFAULT_USER_INFO_URI:}"
120 128 userNameAttributeName: "${SECURITY_OAUTH2_DEFAULT_USER_NAME_ATTRIBUTE_NAME:email}"
121 129 mapperConfig:
122   - type: "${SECURITY_OAUTH2_DEFAULT_MAPPER_TYPE:basic}" # basic or custom
  130 + # Mapper type of converter from external user into internal - 'basic' or 'custom'
  131 + type: "${SECURITY_OAUTH2_DEFAULT_MAPPER_TYPE:basic}"
123 132 basic:
124   - allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_ALLOW_USER_CREATION:true}" # Allows to create user if it not exists
125   - emailAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_EMAIL_ATTRIBUTE_KEY:email}" # Attribute key to use as email for the user
  133 + # Allows to create user if it not exists
  134 + allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_ALLOW_USER_CREATION:true}"
  135 + # Key from attributes of external user object to use as email
  136 + emailAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_EMAIL_ATTRIBUTE_KEY:email}"
126 137 firstNameAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_FIRST_NAME_ATTRIBUTE_KEY:}"
127 138 lastNameAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_LAST_NAME_ATTRIBUTE_KEY:}"
128   - tenantNameStrategy: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_TENANT_NAME_STRATEGY:domain}" # domain, email or custom
129   - tenantNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_TENANT_NAME_PATTERN:}" # %{attribute_key} as placeholder for attributes value by key
130   - customerNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_CUSTOMER_NAME_PATTERN:}" # %{attribute_key} as placeholder for attributes value by key
  139 + # Strategy for generating Tenant from external user object - 'domain', 'email' or 'custom'
  140 + # 'domain' - name of the Tenant will be extracted as domain from the email of the user
  141 + # 'email' - name of the Tenant will email of the user
  142 + # 'custom' - please configure 'tenantNamePattern' for custom mapping
  143 + tenantNameStrategy: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_TENANT_NAME_STRATEGY:domain}"
  144 + # %{attribute_key} as placeholder for attribute value of attributes of external user object
  145 + tenantNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_TENANT_NAME_PATTERN:}"
  146 + # If this field is not empty, user will be created as a user under defined Customer
  147 + # %{attribute_key} as placeholder for attribute value of attributes of external user object
  148 + customerNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_CUSTOMER_NAME_PATTERN:}"
131 149 custom:
132 150 url: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_URL:}"
133 151 username: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_USERNAME:}"
... ...
... ... @@ -94,7 +94,7 @@ export default class TbGoogleMap {
94 94 window[this.initMapFunctionName] = function() { // eslint-disable-line no-undef, angular/window-service
95 95 lazyLoad.load([ // eslint-disable-line no-undef
96 96 { type: 'js', path: 'https://unpkg.com/@google/markerwithlabel@1.2.3/src/markerwithlabel.js' },
97   - { type: 'js', path: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js' }
  97 + { type: 'js', path: 'https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js' }
98 98 ]).then(
99 99 function success() {
100 100 gmGlobals.gmApiKeys[tbMap.apiKey].loaded = true;
... ...