Commit 8e4f8594f74a60889ec394556a452217476a6980

Authored by Igor Kulikov
1 parent e73690f6

Refactor OAuth2 settings. Add mobile application parameters: package and callback URL scheme

Showing 79 changed files with 2801 additions and 545 deletions
@@ -79,6 +79,67 @@ CREATE TABLE IF NOT EXISTS ota_package ( @@ -79,6 +79,67 @@ CREATE TABLE IF NOT EXISTS ota_package (
79 CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) 79 CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
80 ); 80 );
81 81
  82 +CREATE TABLE IF NOT EXISTS oauth2_params (
  83 + id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY,
  84 + enabled boolean,
  85 + tenant_id uuid,
  86 + created_time bigint NOT NULL
  87 +);
  88 +
  89 +CREATE TABLE IF NOT EXISTS oauth2_registration (
  90 + id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY,
  91 + oauth2_params_id uuid NOT NULL,
  92 + created_time bigint NOT NULL,
  93 + additional_info varchar,
  94 + client_id varchar(255),
  95 + client_secret varchar(255),
  96 + authorization_uri varchar(255),
  97 + token_uri varchar(255),
  98 + scope varchar(255),
  99 + user_info_uri varchar(255),
  100 + user_name_attribute_name varchar(255),
  101 + jwk_set_uri varchar(255),
  102 + client_authentication_method varchar(255),
  103 + login_button_label varchar(255),
  104 + login_button_icon varchar(255),
  105 + allow_user_creation boolean,
  106 + activate_user boolean,
  107 + type varchar(31),
  108 + basic_email_attribute_key varchar(31),
  109 + basic_first_name_attribute_key varchar(31),
  110 + basic_last_name_attribute_key varchar(31),
  111 + basic_tenant_name_strategy varchar(31),
  112 + basic_tenant_name_pattern varchar(255),
  113 + basic_customer_name_pattern varchar(255),
  114 + basic_default_dashboard_name varchar(255),
  115 + basic_always_full_screen boolean,
  116 + custom_url varchar(255),
  117 + custom_username varchar(255),
  118 + custom_password varchar(255),
  119 + custom_send_token boolean,
  120 + CONSTRAINT fk_registration_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE
  121 +);
  122 +
  123 +CREATE TABLE IF NOT EXISTS oauth2_domain (
  124 + id uuid NOT NULL CONSTRAINT oauth2_domain_pkey PRIMARY KEY,
  125 + oauth2_params_id uuid NOT NULL,
  126 + created_time bigint NOT NULL,
  127 + domain_name varchar(255),
  128 + domain_scheme varchar(31),
  129 + CONSTRAINT fk_domain_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
  130 + CONSTRAINT oauth2_domain_unq_key UNIQUE (oauth2_params_id, domain_name, domain_scheme)
  131 +);
  132 +
  133 +CREATE TABLE IF NOT EXISTS oauth2_mobile (
  134 + id uuid NOT NULL CONSTRAINT oauth2_mobile_pkey PRIMARY KEY,
  135 + oauth2_params_id uuid NOT NULL,
  136 + created_time bigint NOT NULL,
  137 + pkg_name varchar(255),
  138 + callback_url_scheme varchar(255),
  139 + CONSTRAINT fk_mobile_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
  140 + CONSTRAINT oauth2_mobile_unq_key UNIQUE (oauth2_params_id, pkg_name)
  141 +);
  142 +
82 ALTER TABLE dashboard 143 ALTER TABLE dashboard
83 ADD COLUMN IF NOT EXISTS image varchar(1000000); 144 ADD COLUMN IF NOT EXISTS image varchar(1000000);
84 145
@@ -37,6 +37,8 @@ import org.springframework.util.StringUtils; @@ -37,6 +37,8 @@ import org.springframework.util.StringUtils;
37 import org.springframework.web.util.UriComponents; 37 import org.springframework.web.util.UriComponents;
38 import org.springframework.web.util.UriComponentsBuilder; 38 import org.springframework.web.util.UriComponentsBuilder;
39 import org.thingsboard.server.dao.oauth2.OAuth2Configuration; 39 import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
  40 +import org.thingsboard.server.dao.oauth2.OAuth2Service;
  41 +import org.thingsboard.server.service.security.auth.oauth2.TbOAuth2ParameterNames;
40 import org.thingsboard.server.utils.MiscUtils; 42 import org.thingsboard.server.utils.MiscUtils;
41 43
42 import javax.servlet.http.HttpServletRequest; 44 import javax.servlet.http.HttpServletRequest;
@@ -46,12 +48,13 @@ import java.security.NoSuchAlgorithmException; @@ -46,12 +48,13 @@ import java.security.NoSuchAlgorithmException;
46 import java.util.Base64; 48 import java.util.Base64;
47 import java.util.HashMap; 49 import java.util.HashMap;
48 import java.util.Map; 50 import java.util.Map;
  51 +import java.util.UUID;
49 52
50 @Service 53 @Service
51 @Slf4j 54 @Slf4j
52 public class CustomOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver { 55 public class CustomOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
53 - public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";  
54 - public static final String DEFAULT_LOGIN_PROCESSING_URI = "/login/oauth2/code/"; 56 + private static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";
  57 + private static final String DEFAULT_LOGIN_PROCESSING_URI = "/login/oauth2/code/";
55 private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId"; 58 private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
56 private static final char PATH_DELIMITER = '/'; 59 private static final char PATH_DELIMITER = '/';
57 60
@@ -63,6 +66,9 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza @@ -63,6 +66,9 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
63 @Autowired 66 @Autowired
64 private ClientRegistrationRepository clientRegistrationRepository; 67 private ClientRegistrationRepository clientRegistrationRepository;
65 68
  69 + @Autowired
  70 + private OAuth2Service oAuth2Service;
  71 +
66 @Autowired(required = false) 72 @Autowired(required = false)
67 private OAuth2Configuration oauth2Configuration; 73 private OAuth2Configuration oauth2Configuration;
68 74
@@ -71,7 +77,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza @@ -71,7 +77,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
71 public OAuth2AuthorizationRequest resolve(HttpServletRequest request) { 77 public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
72 String registrationId = this.resolveRegistrationId(request); 78 String registrationId = this.resolveRegistrationId(request);
73 String redirectUriAction = getAction(request, "login"); 79 String redirectUriAction = getAction(request, "login");
74 - return resolve(request, registrationId, redirectUriAction); 80 + String appPackage = getAppPackage(request);
  81 + return resolve(request, registrationId, redirectUriAction, appPackage);
75 } 82 }
76 83
77 @Override 84 @Override
@@ -80,7 +87,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza @@ -80,7 +87,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
80 return null; 87 return null;
81 } 88 }
82 String redirectUriAction = getAction(request, "authorize"); 89 String redirectUriAction = getAction(request, "authorize");
83 - return resolve(request, registrationId, redirectUriAction); 90 + String appPackage = getAppPackage(request);
  91 + return resolve(request, registrationId, redirectUriAction, appPackage);
84 } 92 }
85 93
86 private String getAction(HttpServletRequest request, String defaultAction) { 94 private String getAction(HttpServletRequest request, String defaultAction) {
@@ -91,8 +99,12 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza @@ -91,8 +99,12 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
91 return action; 99 return action;
92 } 100 }
93 101
  102 + private String getAppPackage(HttpServletRequest request) {
  103 + return request.getParameter("pkg");
  104 + }
  105 +
94 @SuppressWarnings("deprecation") 106 @SuppressWarnings("deprecation")
95 - private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction) { 107 + private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction, String appPackage) {
96 if (registrationId == null) { 108 if (registrationId == null) {
97 return null; 109 return null;
98 } 110 }
@@ -104,6 +116,14 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza @@ -104,6 +116,14 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
104 116
105 Map<String, Object> attributes = new HashMap<>(); 117 Map<String, Object> attributes = new HashMap<>();
106 attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId()); 118 attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId());
  119 + if (!StringUtils.isEmpty(appPackage)) {
  120 + String callbackUrlScheme = this.oAuth2Service.findCallbackUrlScheme(UUID.fromString(registrationId), appPackage);
  121 + if (StringUtils.isEmpty(callbackUrlScheme)) {
  122 + throw new IllegalArgumentException("Invalid package: " + appPackage + ". No package info found for Client Registration.");
  123 + } else {
  124 + attributes.put(TbOAuth2ParameterNames.CALLBACK_URL_SCHEME, callbackUrlScheme);
  125 + }
  126 + }
107 127
108 OAuth2AuthorizationRequest.Builder builder; 128 OAuth2AuthorizationRequest.Builder builder;
109 if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) { 129 if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
@@ -22,12 +22,13 @@ import org.springframework.security.access.prepost.PreAuthorize; @@ -22,12 +22,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
22 import org.springframework.web.bind.annotation.RequestBody; 22 import org.springframework.web.bind.annotation.RequestBody;
23 import org.springframework.web.bind.annotation.RequestMapping; 23 import org.springframework.web.bind.annotation.RequestMapping;
24 import org.springframework.web.bind.annotation.RequestMethod; 24 import org.springframework.web.bind.annotation.RequestMethod;
  25 +import org.springframework.web.bind.annotation.RequestParam;
25 import org.springframework.web.bind.annotation.ResponseBody; 26 import org.springframework.web.bind.annotation.ResponseBody;
26 import org.springframework.web.bind.annotation.ResponseStatus; 27 import org.springframework.web.bind.annotation.ResponseStatus;
27 import org.springframework.web.bind.annotation.RestController; 28 import org.springframework.web.bind.annotation.RestController;
28 import org.thingsboard.server.common.data.exception.ThingsboardException; 29 import org.thingsboard.server.common.data.exception.ThingsboardException;
29 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; 30 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
30 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams; 31 +import org.thingsboard.server.common.data.oauth2.OAuth2Info;
31 import org.thingsboard.server.dao.oauth2.OAuth2Configuration; 32 import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
32 import org.thingsboard.server.queue.util.TbCoreComponent; 33 import org.thingsboard.server.queue.util.TbCoreComponent;
33 import org.thingsboard.server.service.security.permission.Operation; 34 import org.thingsboard.server.service.security.permission.Operation;
@@ -49,7 +50,8 @@ public class OAuth2Controller extends BaseController { @@ -49,7 +50,8 @@ public class OAuth2Controller extends BaseController {
49 50
50 @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST) 51 @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST)
51 @ResponseBody 52 @ResponseBody
52 - public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request) throws ThingsboardException { 53 + public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request,
  54 + @RequestParam(required = false) String pkgName) throws ThingsboardException {
53 try { 55 try {
54 if (log.isDebugEnabled()) { 56 if (log.isDebugEnabled()) {
55 log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort()); 57 log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort());
@@ -59,7 +61,7 @@ public class OAuth2Controller extends BaseController { @@ -59,7 +61,7 @@ public class OAuth2Controller extends BaseController {
59 log.debug("Header: {} {}", header, request.getHeader(header)); 61 log.debug("Header: {} {}", header, request.getHeader(header));
60 } 62 }
61 } 63 }
62 - return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request)); 64 + return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName);
63 } catch (Exception e) { 65 } catch (Exception e) {
64 throw handleException(e); 66 throw handleException(e);
65 } 67 }
@@ -68,10 +70,10 @@ public class OAuth2Controller extends BaseController { @@ -68,10 +70,10 @@ public class OAuth2Controller extends BaseController {
68 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 70 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
69 @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json") 71 @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json")
70 @ResponseBody 72 @ResponseBody
71 - public OAuth2ClientsParams getCurrentOAuth2Params() throws ThingsboardException { 73 + public OAuth2Info getCurrentOAuth2Info() throws ThingsboardException {
72 try { 74 try {
73 accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ); 75 accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ);
74 - return oAuth2Service.findOAuth2Params(); 76 + return oAuth2Service.findOAuth2Info();
75 } catch (Exception e) { 77 } catch (Exception e) {
76 throw handleException(e); 78 throw handleException(e);
77 } 79 }
@@ -80,11 +82,11 @@ public class OAuth2Controller extends BaseController { @@ -80,11 +82,11 @@ public class OAuth2Controller extends BaseController {
80 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 82 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
81 @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST) 83 @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST)
82 @ResponseStatus(value = HttpStatus.OK) 84 @ResponseStatus(value = HttpStatus.OK)
83 - public OAuth2ClientsParams saveOAuth2Params(@RequestBody OAuth2ClientsParams oauth2Params) throws ThingsboardException { 85 + public OAuth2Info saveOAuth2Info(@RequestBody OAuth2Info oauth2Info) throws ThingsboardException {
84 try { 86 try {
85 accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.WRITE); 87 accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.WRITE);
86 - oAuth2Service.saveOAuth2Params(oauth2Params);  
87 - return oAuth2Service.findOAuth2Params(); 88 + oAuth2Service.saveOAuth2Info(oauth2Info);
  89 + return oAuth2Service.findOAuth2Info();
88 } catch (Exception e) { 90 } catch (Exception e) {
89 throw handleException(e); 91 throw handleException(e);
90 } 92 }
@@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
23 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.context.annotation.Profile; 24 import org.springframework.context.annotation.Profile;
25 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
  26 +import org.thingsboard.common.util.JacksonUtil;
26 import org.thingsboard.rule.engine.profile.TbDeviceProfileNode; 27 import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
27 import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration; 28 import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration;
28 import org.thingsboard.server.common.data.EntityView; 29 import org.thingsboard.server.common.data.EntityView;
@@ -35,6 +36,8 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -35,6 +36,8 @@ import org.thingsboard.server.common.data.id.TenantId;
35 import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; 36 import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
36 import org.thingsboard.server.common.data.kv.ReadTsKvQuery; 37 import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
37 import org.thingsboard.server.common.data.kv.TsKvEntry; 38 import org.thingsboard.server.common.data.kv.TsKvEntry;
  39 +import org.thingsboard.server.common.data.oauth2.OAuth2Info;
  40 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
38 import org.thingsboard.server.common.data.page.PageData; 41 import org.thingsboard.server.common.data.page.PageData;
39 import org.thingsboard.server.common.data.page.PageLink; 42 import org.thingsboard.server.common.data.page.PageLink;
40 import org.thingsboard.server.common.data.page.TimePageLink; 43 import org.thingsboard.server.common.data.page.TimePageLink;
@@ -45,10 +48,11 @@ import org.thingsboard.server.dao.alarm.AlarmDao; @@ -45,10 +48,11 @@ import org.thingsboard.server.dao.alarm.AlarmDao;
45 import org.thingsboard.server.dao.alarm.AlarmService; 48 import org.thingsboard.server.dao.alarm.AlarmService;
46 import org.thingsboard.server.dao.entity.EntityService; 49 import org.thingsboard.server.dao.entity.EntityService;
47 import org.thingsboard.server.dao.entityview.EntityViewService; 50 import org.thingsboard.server.dao.entityview.EntityViewService;
  51 +import org.thingsboard.server.dao.oauth2.OAuth2Service;
  52 +import org.thingsboard.server.dao.oauth2.OAuth2Utils;
48 import org.thingsboard.server.dao.rule.RuleChainService; 53 import org.thingsboard.server.dao.rule.RuleChainService;
49 import org.thingsboard.server.dao.tenant.TenantService; 54 import org.thingsboard.server.dao.tenant.TenantService;
50 import org.thingsboard.server.dao.timeseries.TimeseriesService; 55 import org.thingsboard.server.dao.timeseries.TimeseriesService;
51 -import org.thingsboard.common.util.JacksonUtil;  
52 import org.thingsboard.server.service.install.InstallScripts; 56 import org.thingsboard.server.service.install.InstallScripts;
53 57
54 import java.util.ArrayList; 58 import java.util.ArrayList;
@@ -88,6 +92,9 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -88,6 +92,9 @@ public class DefaultDataUpdateService implements DataUpdateService {
88 @Autowired 92 @Autowired
89 private AlarmDao alarmDao; 93 private AlarmDao alarmDao;
90 94
  95 + @Autowired
  96 + private OAuth2Service oAuth2Service;
  97 +
91 @Override 98 @Override
92 public void updateData(String fromVersion) throws Exception { 99 public void updateData(String fromVersion) throws Exception {
93 switch (fromVersion) { 100 switch (fromVersion) {
@@ -107,6 +114,7 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -107,6 +114,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
107 log.info("Updating data from version 3.2.2 to 3.3.0 ..."); 114 log.info("Updating data from version 3.2.2 to 3.3.0 ...");
108 tenantsDefaultEdgeRuleChainUpdater.updateEntities(null); 115 tenantsDefaultEdgeRuleChainUpdater.updateEntities(null);
109 tenantsAlarmsCustomerUpdater.updateEntities(null); 116 tenantsAlarmsCustomerUpdater.updateEntities(null);
  117 + updateOAuth2Params();
110 break; 118 break;
111 default: 119 default:
112 throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion); 120 throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion);
@@ -362,4 +370,20 @@ public class DefaultDataUpdateService implements DataUpdateService { @@ -362,4 +370,20 @@ public class DefaultDataUpdateService implements DataUpdateService {
362 } 370 }
363 } 371 }
364 372
  373 + private void updateOAuth2Params() {
  374 + try {
  375 + OAuth2ClientsParams oauth2ClientsParams = oAuth2Service.findOAuth2Params();
  376 + if (!oauth2ClientsParams.getDomainsParams().isEmpty()) {
  377 + log.info("Updating OAuth2 parameters ...");
  378 + OAuth2Info oAuth2Info = OAuth2Utils.clientParamsToOAuth2Info(oauth2ClientsParams);
  379 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  380 + oAuth2Service.saveOAuth2Params(new OAuth2ClientsParams(false, Collections.emptyList()));
  381 + log.info("Successfully updated OAuth2 parameters!");
  382 + }
  383 + }
  384 + catch (Exception e) {
  385 + log.error("Failed to update OAuth2 parameters", e);
  386 + }
  387 + }
  388 +
365 } 389 }
@@ -33,8 +33,8 @@ import org.thingsboard.server.common.data.id.CustomerId; @@ -33,8 +33,8 @@ import org.thingsboard.server.common.data.id.CustomerId;
33 import org.thingsboard.server.common.data.id.DashboardId; 33 import org.thingsboard.server.common.data.id.DashboardId;
34 import org.thingsboard.server.common.data.id.IdBased; 34 import org.thingsboard.server.common.data.id.IdBased;
35 import org.thingsboard.server.common.data.id.TenantId; 35 import org.thingsboard.server.common.data.id.TenantId;
36 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;  
37 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; 36 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  37 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
38 import org.thingsboard.server.common.data.page.PageData; 38 import org.thingsboard.server.common.data.page.PageData;
39 import org.thingsboard.server.common.data.page.PageLink; 39 import org.thingsboard.server.common.data.page.PageLink;
40 import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; 40 import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
@@ -93,9 +93,9 @@ public abstract class AbstractOAuth2ClientMapper { @@ -93,9 +93,9 @@ public abstract class AbstractOAuth2ClientMapper {
93 93
94 private final Lock userCreationLock = new ReentrantLock(); 94 private final Lock userCreationLock = new ReentrantLock();
95 95
96 - protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2ClientRegistrationInfo clientRegistration) { 96 + protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Registration registration) {
97 97
98 - OAuth2MapperConfig config = clientRegistration.getMapperConfig(); 98 + OAuth2MapperConfig config = registration.getMapperConfig();
99 99
100 UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, oauth2User.getEmail()); 100 UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, oauth2User.getEmail());
101 101
@@ -139,9 +139,9 @@ public abstract class AbstractOAuth2ClientMapper { @@ -139,9 +139,9 @@ public abstract class AbstractOAuth2ClientMapper {
139 } 139 }
140 } 140 }
141 141
142 - if (clientRegistration.getAdditionalInfo() != null &&  
143 - clientRegistration.getAdditionalInfo().has("providerName")) {  
144 - additionalInfo.put("authProviderName", clientRegistration.getAdditionalInfo().get("providerName").asText()); 142 + if (registration.getAdditionalInfo() != null &&
  143 + registration.getAdditionalInfo().has("providerName")) {
  144 + additionalInfo.put("authProviderName", registration.getAdditionalInfo().get("providerName").asText());
145 } 145 }
146 146
147 user.setAdditionalInfo(additionalInfo); 147 user.setAdditionalInfo(additionalInfo);
@@ -18,8 +18,8 @@ package org.thingsboard.server.service.security.auth.oauth2; @@ -18,8 +18,8 @@ package org.thingsboard.server.service.security.auth.oauth2;
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; 19 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
20 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
21 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;  
22 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; 21 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  22 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
23 import org.thingsboard.server.dao.oauth2.OAuth2User; 23 import org.thingsboard.server.dao.oauth2.OAuth2User;
24 import org.thingsboard.server.service.security.model.SecurityUser; 24 import org.thingsboard.server.service.security.model.SecurityUser;
25 25
@@ -30,12 +30,12 @@ import java.util.Map; @@ -30,12 +30,12 @@ import java.util.Map;
30 public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper { 30 public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper {
31 31
32 @Override 32 @Override
33 - public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2ClientRegistrationInfo clientRegistration) {  
34 - OAuth2MapperConfig config = clientRegistration.getMapperConfig(); 33 + public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
  34 + OAuth2MapperConfig config = registration.getMapperConfig();
35 Map<String, Object> attributes = token.getPrincipal().getAttributes(); 35 Map<String, Object> attributes = token.getPrincipal().getAttributes();
36 String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey()); 36 String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey());
37 OAuth2User oauth2User = BasicMapperUtils.getOAuth2User(email, attributes, config); 37 OAuth2User oauth2User = BasicMapperUtils.getOAuth2User(email, attributes, config);
38 38
39 - return getOrCreateSecurityUserFromOAuth2User(oauth2User, clientRegistration); 39 + return getOrCreateSecurityUserFromOAuth2User(oauth2User, registration);
40 } 40 }
41 } 41 }
@@ -23,9 +23,9 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic @@ -23,9 +23,9 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic
23 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
24 import org.springframework.util.StringUtils; 24 import org.springframework.util.StringUtils;
25 import org.springframework.web.client.RestTemplate; 25 import org.springframework.web.client.RestTemplate;
26 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;  
27 import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; 26 import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
28 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; 27 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  28 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
29 import org.thingsboard.server.dao.oauth2.OAuth2User; 29 import org.thingsboard.server.dao.oauth2.OAuth2User;
30 import org.thingsboard.server.service.security.model.SecurityUser; 30 import org.thingsboard.server.service.security.model.SecurityUser;
31 31
@@ -39,10 +39,10 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme @@ -39,10 +39,10 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
39 private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); 39 private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
40 40
41 @Override 41 @Override
42 - public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2ClientRegistrationInfo clientRegistration) {  
43 - OAuth2MapperConfig config = clientRegistration.getMapperConfig(); 42 + public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
  43 + OAuth2MapperConfig config = registration.getMapperConfig();
44 OAuth2User oauth2User = getOAuth2User(token, providerAccessToken, config.getCustom()); 44 OAuth2User oauth2User = getOAuth2User(token, providerAccessToken, config.getCustom());
45 - return getOrCreateSecurityUserFromOAuth2User(oauth2User, clientRegistration); 45 + return getOrCreateSecurityUserFromOAuth2User(oauth2User, registration);
46 } 46 }
47 47
48 private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2CustomMapperConfig custom) { 48 private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2CustomMapperConfig custom) {
@@ -23,8 +23,8 @@ import org.springframework.boot.web.client.RestTemplateBuilder; @@ -23,8 +23,8 @@ import org.springframework.boot.web.client.RestTemplateBuilder;
23 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; 23 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
24 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
25 import org.springframework.web.client.RestTemplate; 25 import org.springframework.web.client.RestTemplate;
26 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;  
27 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; 26 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  27 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
28 import org.thingsboard.server.dao.oauth2.OAuth2Configuration; 28 import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
29 import org.thingsboard.server.dao.oauth2.OAuth2User; 29 import org.thingsboard.server.dao.oauth2.OAuth2User;
30 import org.thingsboard.server.service.security.model.SecurityUser; 30 import org.thingsboard.server.service.security.model.SecurityUser;
@@ -46,13 +46,13 @@ public class GithubOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme @@ -46,13 +46,13 @@ public class GithubOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
46 private OAuth2Configuration oAuth2Configuration; 46 private OAuth2Configuration oAuth2Configuration;
47 47
48 @Override 48 @Override
49 - public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2ClientRegistrationInfo clientRegistration) {  
50 - OAuth2MapperConfig config = clientRegistration.getMapperConfig(); 49 + public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
  50 + OAuth2MapperConfig config = registration.getMapperConfig();
51 Map<String, String> githubMapperConfig = oAuth2Configuration.getGithubMapper(); 51 Map<String, String> githubMapperConfig = oAuth2Configuration.getGithubMapper();
52 String email = getEmail(githubMapperConfig.get(EMAIL_URL_KEY), providerAccessToken); 52 String email = getEmail(githubMapperConfig.get(EMAIL_URL_KEY), providerAccessToken);
53 Map<String, Object> attributes = token.getPrincipal().getAttributes(); 53 Map<String, Object> attributes = token.getPrincipal().getAttributes();
54 OAuth2User oAuth2User = BasicMapperUtils.getOAuth2User(email, attributes, config); 54 OAuth2User oAuth2User = BasicMapperUtils.getOAuth2User(email, attributes, config);
55 - return getOrCreateSecurityUserFromOAuth2User(oAuth2User, clientRegistration); 55 + return getOrCreateSecurityUserFromOAuth2User(oAuth2User, registration);
56 } 56 }
57 57
58 private synchronized String getEmail(String emailUrl, String oauth2Token) { 58 private synchronized String getEmail(String emailUrl, String oauth2Token) {
@@ -16,9 +16,10 @@ @@ -16,9 +16,10 @@
16 package org.thingsboard.server.service.security.auth.oauth2; 16 package org.thingsboard.server.service.security.auth.oauth2;
17 17
18 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; 18 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
19 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; 19 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  20 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
20 import org.thingsboard.server.service.security.model.SecurityUser; 21 import org.thingsboard.server.service.security.model.SecurityUser;
21 22
22 public interface OAuth2ClientMapper { 23 public interface OAuth2ClientMapper {
23 - SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2ClientRegistrationInfo clientRegistration); 24 + SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration);
24 } 25 }
@@ -18,8 +18,10 @@ package org.thingsboard.server.service.security.auth.oauth2; @@ -18,8 +18,10 @@ package org.thingsboard.server.service.security.auth.oauth2;
18 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
20 import org.springframework.security.core.AuthenticationException; 20 import org.springframework.security.core.AuthenticationException;
  21 +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
21 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; 22 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
22 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
  24 +import org.thingsboard.server.common.data.StringUtils;
23 import org.thingsboard.server.common.data.id.CustomerId; 25 import org.thingsboard.server.common.data.id.CustomerId;
24 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
25 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
@@ -51,9 +53,19 @@ public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationF @@ -51,9 +53,19 @@ public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationF
51 public void onAuthenticationFailure(HttpServletRequest request, 53 public void onAuthenticationFailure(HttpServletRequest request,
52 HttpServletResponse response, AuthenticationException exception) 54 HttpServletResponse response, AuthenticationException exception)
53 throws IOException, ServletException { 55 throws IOException, ServletException {
54 - String baseUrl = this.systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, new CustomerId(EntityId.NULL_UUID), request); 56 + String baseUrl;
  57 + String errorPrefix;
  58 + OAuth2AuthorizationRequest authorizationRequest = httpCookieOAuth2AuthorizationRequestRepository.loadAuthorizationRequest(request);
  59 + String callbackUrlScheme = authorizationRequest.getAttribute(TbOAuth2ParameterNames.CALLBACK_URL_SCHEME);
  60 + if (!StringUtils.isEmpty(callbackUrlScheme)) {
  61 + baseUrl = callbackUrlScheme + ":";
  62 + errorPrefix = "/?error=";
  63 + } else {
  64 + baseUrl = this.systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, new CustomerId(EntityId.NULL_UUID), request);
  65 + errorPrefix = "/login?loginError=";
  66 + }
55 httpCookieOAuth2AuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response); 67 httpCookieOAuth2AuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response);
56 - getRedirectStrategy().sendRedirect(request, response, baseUrl + "/login?loginError=" + 68 + getRedirectStrategy().sendRedirect(request, response, baseUrl + errorPrefix +
57 URLEncoder.encode(exception.getMessage(), StandardCharsets.UTF_8.toString())); 69 URLEncoder.encode(exception.getMessage(), StandardCharsets.UTF_8.toString()));
58 } 70 }
59 } 71 }
@@ -20,12 +20,14 @@ import org.springframework.security.core.Authentication; @@ -20,12 +20,14 @@ import org.springframework.security.core.Authentication;
20 import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; 20 import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
21 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; 21 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
22 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; 22 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
  23 +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
23 import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; 24 import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
24 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
  26 +import org.thingsboard.server.common.data.StringUtils;
25 import org.thingsboard.server.common.data.id.CustomerId; 27 import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.EntityId; 28 import org.thingsboard.server.common.data.id.EntityId;
27 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
28 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; 30 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
29 import org.thingsboard.server.common.data.security.model.JwtToken; 31 import org.thingsboard.server.common.data.security.model.JwtToken;
30 import org.thingsboard.server.dao.oauth2.OAuth2Service; 32 import org.thingsboard.server.dao.oauth2.OAuth2Service;
31 import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; 33 import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
@@ -72,17 +74,24 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS @@ -72,17 +74,24 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
72 public void onAuthenticationSuccess(HttpServletRequest request, 74 public void onAuthenticationSuccess(HttpServletRequest request,
73 HttpServletResponse response, 75 HttpServletResponse response,
74 Authentication authentication) throws IOException { 76 Authentication authentication) throws IOException {
75 - String baseUrl = this.systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, new CustomerId(EntityId.NULL_UUID), request); 77 + OAuth2AuthorizationRequest authorizationRequest = httpCookieOAuth2AuthorizationRequestRepository.loadAuthorizationRequest(request);
  78 + String callbackUrlScheme = authorizationRequest.getAttribute(TbOAuth2ParameterNames.CALLBACK_URL_SCHEME);
  79 + String baseUrl;
  80 + if (!StringUtils.isEmpty(callbackUrlScheme)) {
  81 + baseUrl = callbackUrlScheme + ":";
  82 + } else {
  83 + baseUrl = this.systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, new CustomerId(EntityId.NULL_UUID), request);
  84 + }
76 try { 85 try {
77 OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; 86 OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
78 87
79 - OAuth2ClientRegistrationInfo clientRegistration = oAuth2Service.findClientRegistrationInfo(UUID.fromString(token.getAuthorizedClientRegistrationId())); 88 + OAuth2Registration registration = oAuth2Service.findRegistration(UUID.fromString(token.getAuthorizedClientRegistrationId()));
80 OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient( 89 OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient(
81 token.getAuthorizedClientRegistrationId(), 90 token.getAuthorizedClientRegistrationId(),
82 token.getPrincipal().getName()); 91 token.getPrincipal().getName());
83 - OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(clientRegistration.getMapperConfig().getType()); 92 + OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(registration.getMapperConfig().getType());
84 SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oAuth2AuthorizedClient.getAccessToken().getTokenValue(), 93 SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oAuth2AuthorizedClient.getAccessToken().getTokenValue(),
85 - clientRegistration); 94 + registration);
86 95
87 JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); 96 JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
88 JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); 97 JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
@@ -91,7 +100,13 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS @@ -91,7 +100,13 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
91 getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); 100 getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken());
92 } catch (Exception e) { 101 } catch (Exception e) {
93 clearAuthenticationAttributes(request, response); 102 clearAuthenticationAttributes(request, response);
94 - getRedirectStrategy().sendRedirect(request, response, baseUrl + "/login?loginError=" + 103 + String errorPrefix;
  104 + if (!StringUtils.isEmpty(callbackUrlScheme)) {
  105 + errorPrefix = "/?error=";
  106 + } else {
  107 + errorPrefix = "/login?loginError=";
  108 + }
  109 + getRedirectStrategy().sendRedirect(request, response, baseUrl + errorPrefix +
95 URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.toString())); 110 URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.toString()));
96 } 111 }
97 } 112 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.service.security.auth.oauth2;
  17 +
  18 +public interface TbOAuth2ParameterNames {
  19 +
  20 + String CALLBACK_URL_SCHEME = "callback_url_scheme";
  21 +
  22 +}
@@ -16,20 +16,30 @@ @@ -16,20 +16,30 @@
16 package org.thingsboard.server.dao.oauth2; 16 package org.thingsboard.server.dao.oauth2;
17 17
18 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; 18 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
19 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;  
20 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams; 19 +import org.thingsboard.server.common.data.oauth2.OAuth2Info;
  20 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  21 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
  22 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
21 23
22 import java.util.List; 24 import java.util.List;
23 import java.util.UUID; 25 import java.util.UUID;
24 26
25 public interface OAuth2Service { 27 public interface OAuth2Service {
26 - List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName); 28 + List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName, String pkgName);
27 29
  30 + @Deprecated
28 void saveOAuth2Params(OAuth2ClientsParams oauth2Params); 31 void saveOAuth2Params(OAuth2ClientsParams oauth2Params);
29 32
  33 + @Deprecated
30 OAuth2ClientsParams findOAuth2Params(); 34 OAuth2ClientsParams findOAuth2Params();
31 35
32 - OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id); 36 + void saveOAuth2Info(OAuth2Info oauth2Info);
33 37
34 - List<OAuth2ClientRegistrationInfo> findAllClientRegistrationInfos(); 38 + OAuth2Info findOAuth2Info();
  39 +
  40 + OAuth2Registration findRegistration(UUID id);
  41 +
  42 + List<OAuth2Registration> findAllRegistrations();
  43 +
  44 + String findCallbackUrlScheme(UUID registrationId, String pkgName);
35 } 45 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonCreator;
  19 +import com.fasterxml.jackson.annotation.JsonProperty;
  20 +
  21 +import java.util.UUID;
  22 +
  23 +public class OAuth2DomainId extends UUIDBased {
  24 +
  25 + @JsonCreator
  26 + public OAuth2DomainId(@JsonProperty("id") UUID id) {
  27 + super(id);
  28 + }
  29 +
  30 + public static OAuth2DomainId fromString(String oauth2DomainId) {
  31 + return new OAuth2DomainId(UUID.fromString(oauth2DomainId));
  32 + }
  33 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonCreator;
  19 +import com.fasterxml.jackson.annotation.JsonProperty;
  20 +
  21 +import java.util.UUID;
  22 +
  23 +public class OAuth2MobileId extends UUIDBased {
  24 +
  25 + @JsonCreator
  26 + public OAuth2MobileId(@JsonProperty("id") UUID id) {
  27 + super(id);
  28 + }
  29 +
  30 + public static OAuth2MobileId fromString(String oauth2MobileId) {
  31 + return new OAuth2MobileId(UUID.fromString(oauth2MobileId));
  32 + }
  33 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonCreator;
  19 +import com.fasterxml.jackson.annotation.JsonProperty;
  20 +
  21 +import java.util.UUID;
  22 +
  23 +public class OAuth2ParamsId extends UUIDBased {
  24 +
  25 + @JsonCreator
  26 + public OAuth2ParamsId(@JsonProperty("id") UUID id) {
  27 + super(id);
  28 + }
  29 +
  30 + public static OAuth2ParamsId fromString(String oauth2ParamsId) {
  31 + return new OAuth2ParamsId(UUID.fromString(oauth2ParamsId));
  32 + }
  33 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonCreator;
  19 +import com.fasterxml.jackson.annotation.JsonProperty;
  20 +
  21 +import java.util.UUID;
  22 +
  23 +public class OAuth2RegistrationId extends UUIDBased {
  24 +
  25 + @JsonCreator
  26 + public OAuth2RegistrationId(@JsonProperty("id") UUID id) {
  27 + super(id);
  28 + }
  29 +
  30 + public static OAuth2RegistrationId fromString(String oauth2RegistrationId) {
  31 + return new OAuth2RegistrationId(UUID.fromString(oauth2RegistrationId));
  32 + }
  33 +}
common/data/src/main/java/org/thingsboard/server/common/data/id/deprecated/OAuth2ClientRegistrationId.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientRegistrationId.java
@@ -13,13 +13,15 @@ @@ -13,13 +13,15 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.id; 16 +package org.thingsboard.server.common.data.id.deprecated;
17 17
18 import com.fasterxml.jackson.annotation.JsonCreator; 18 import com.fasterxml.jackson.annotation.JsonCreator;
19 import com.fasterxml.jackson.annotation.JsonProperty; 19 import com.fasterxml.jackson.annotation.JsonProperty;
  20 +import org.thingsboard.server.common.data.id.UUIDBased;
20 21
21 import java.util.UUID; 22 import java.util.UUID;
22 23
  24 +@Deprecated
23 public class OAuth2ClientRegistrationId extends UUIDBased { 25 public class OAuth2ClientRegistrationId extends UUIDBased {
24 26
25 @JsonCreator 27 @JsonCreator
common/data/src/main/java/org/thingsboard/server/common/data/id/deprecated/OAuth2ClientRegistrationInfoId.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientRegistrationInfoId.java
@@ -13,13 +13,15 @@ @@ -13,13 +13,15 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.id; 16 +package org.thingsboard.server.common.data.id.deprecated;
17 17
18 import com.fasterxml.jackson.annotation.JsonCreator; 18 import com.fasterxml.jackson.annotation.JsonCreator;
19 import com.fasterxml.jackson.annotation.JsonProperty; 19 import com.fasterxml.jackson.annotation.JsonProperty;
  20 +import org.thingsboard.server.common.data.id.UUIDBased;
20 21
21 import java.util.UUID; 22 import java.util.UUID;
22 23
  24 +@Deprecated
23 public class OAuth2ClientRegistrationInfoId extends UUIDBased { 25 public class OAuth2ClientRegistrationInfoId extends UUIDBased {
24 26
25 @JsonCreator 27 @JsonCreator
@@ -20,10 +20,8 @@ import lombok.EqualsAndHashCode; @@ -20,10 +20,8 @@ import lombok.EqualsAndHashCode;
20 import lombok.NoArgsConstructor; 20 import lombok.NoArgsConstructor;
21 import lombok.ToString; 21 import lombok.ToString;
22 import org.thingsboard.server.common.data.HasName; 22 import org.thingsboard.server.common.data.HasName;
23 -import org.thingsboard.server.common.data.HasTenantId;  
24 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; 23 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
25 import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; 24 import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId;
26 -import org.thingsboard.server.common.data.id.TenantId;  
27 25
28 import java.util.List; 26 import java.util.List;
29 27
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import lombok.NoArgsConstructor;
  21 +import lombok.ToString;
  22 +import org.thingsboard.server.common.data.BaseData;
  23 +import org.thingsboard.server.common.data.id.OAuth2DomainId;
  24 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  25 +
  26 +@EqualsAndHashCode(callSuper = true)
  27 +@Data
  28 +@ToString
  29 +@NoArgsConstructor
  30 +public class OAuth2Domain extends BaseData<OAuth2DomainId> {
  31 +
  32 + private OAuth2ParamsId oauth2ParamsId;
  33 + private String domainName;
  34 + private SchemeType domainScheme;
  35 +
  36 + public OAuth2Domain(OAuth2Domain domain) {
  37 + super(domain);
  38 + this.oauth2ParamsId = domain.oauth2ParamsId;
  39 + this.domainName = domain.domainName;
  40 + this.domainScheme = domain.domainScheme;
  41 + }
  42 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.AllArgsConstructor;
  19 +import lombok.Builder;
  20 +import lombok.Data;
  21 +import lombok.EqualsAndHashCode;
  22 +import lombok.NoArgsConstructor;
  23 +import lombok.ToString;
  24 +
  25 +@EqualsAndHashCode
  26 +@Data
  27 +@ToString
  28 +@NoArgsConstructor
  29 +@AllArgsConstructor
  30 +@Builder
  31 +public class OAuth2DomainInfo {
  32 + private SchemeType scheme;
  33 + private String name;
  34 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.*;
  19 +
  20 +import java.util.List;
  21 +
  22 +@EqualsAndHashCode
  23 +@Data
  24 +@ToString
  25 +@Builder(toBuilder = true)
  26 +@NoArgsConstructor
  27 +@AllArgsConstructor
  28 +public class OAuth2Info {
  29 + private boolean enabled;
  30 + private List<OAuth2ParamsInfo> oauth2ParamsInfos;
  31 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import lombok.NoArgsConstructor;
  21 +import lombok.ToString;
  22 +import org.thingsboard.server.common.data.BaseData;
  23 +import org.thingsboard.server.common.data.id.OAuth2MobileId;
  24 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  25 +
  26 +@EqualsAndHashCode(callSuper = true)
  27 +@Data
  28 +@ToString
  29 +@NoArgsConstructor
  30 +public class OAuth2Mobile extends BaseData<OAuth2MobileId> {
  31 +
  32 + private OAuth2ParamsId oauth2ParamsId;
  33 + private String pkgName;
  34 + private String callbackUrlScheme;
  35 +
  36 + public OAuth2Mobile(OAuth2Mobile mobile) {
  37 + super(mobile);
  38 + this.oauth2ParamsId = mobile.oauth2ParamsId;
  39 + this.pkgName = mobile.pkgName;
  40 + this.callbackUrlScheme = mobile.callbackUrlScheme;
  41 + }
  42 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.AllArgsConstructor;
  19 +import lombok.Builder;
  20 +import lombok.Data;
  21 +import lombok.EqualsAndHashCode;
  22 +import lombok.NoArgsConstructor;
  23 +import lombok.ToString;
  24 +
  25 +@EqualsAndHashCode
  26 +@Data
  27 +@ToString
  28 +@NoArgsConstructor
  29 +@AllArgsConstructor
  30 +@Builder
  31 +public class OAuth2MobileInfo {
  32 + private String pkgName;
  33 + private String callbackUrlScheme;
  34 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import lombok.NoArgsConstructor;
  21 +import lombok.ToString;
  22 +import org.thingsboard.server.common.data.BaseData;
  23 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  24 +import org.thingsboard.server.common.data.id.TenantId;
  25 +
  26 +@EqualsAndHashCode(callSuper = true)
  27 +@Data
  28 +@ToString
  29 +@NoArgsConstructor
  30 +public class OAuth2Params extends BaseData<OAuth2ParamsId> {
  31 +
  32 + private boolean enabled;
  33 + private TenantId tenantId;
  34 +
  35 + public OAuth2Params(OAuth2Params oauth2Params) {
  36 + super(oauth2Params);
  37 + this.enabled = oauth2Params.enabled;
  38 + this.tenantId = oauth2Params.tenantId;
  39 + }
  40 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import lombok.AllArgsConstructor;
  19 +import lombok.Builder;
  20 +import lombok.Data;
  21 +import lombok.EqualsAndHashCode;
  22 +import lombok.NoArgsConstructor;
  23 +import lombok.ToString;
  24 +
  25 +import java.util.List;
  26 +
  27 +@EqualsAndHashCode
  28 +@Data
  29 +@ToString
  30 +@Builder(toBuilder = true)
  31 +@NoArgsConstructor
  32 +@AllArgsConstructor
  33 +public class OAuth2ParamsInfo {
  34 +
  35 + private List<OAuth2DomainInfo> domainInfos;
  36 + private List<OAuth2MobileInfo> mobileInfos;
  37 + private List<OAuth2RegistrationInfo> clientRegistrations;
  38 +
  39 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonProperty;
  19 +import lombok.Data;
  20 +import lombok.EqualsAndHashCode;
  21 +import lombok.NoArgsConstructor;
  22 +import lombok.ToString;
  23 +import org.thingsboard.server.common.data.HasName;
  24 +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
  25 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  26 +import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
  27 +
  28 +import java.util.List;
  29 +
  30 +@EqualsAndHashCode(callSuper = true)
  31 +@Data
  32 +@ToString(exclude = {"clientSecret"})
  33 +@NoArgsConstructor
  34 +public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2RegistrationId> implements HasName {
  35 +
  36 + private OAuth2ParamsId oauth2ParamsId;
  37 + private OAuth2MapperConfig mapperConfig;
  38 + private String clientId;
  39 + private String clientSecret;
  40 + private String authorizationUri;
  41 + private String accessTokenUri;
  42 + private List<String> scope;
  43 + private String userInfoUri;
  44 + private String userNameAttributeName;
  45 + private String jwkSetUri;
  46 + private String clientAuthenticationMethod;
  47 + private String loginButtonLabel;
  48 + private String loginButtonIcon;
  49 +
  50 + public OAuth2Registration(OAuth2Registration registration) {
  51 + super(registration);
  52 + this.oauth2ParamsId = registration.oauth2ParamsId;
  53 + this.mapperConfig = registration.mapperConfig;
  54 + this.clientId = registration.clientId;
  55 + this.clientSecret = registration.clientSecret;
  56 + this.authorizationUri = registration.authorizationUri;
  57 + this.accessTokenUri = registration.accessTokenUri;
  58 + this.scope = registration.scope;
  59 + this.userInfoUri = registration.userInfoUri;
  60 + this.userNameAttributeName = registration.userNameAttributeName;
  61 + this.jwkSetUri = registration.jwkSetUri;
  62 + this.clientAuthenticationMethod = registration.clientAuthenticationMethod;
  63 + this.loginButtonLabel = registration.loginButtonLabel;
  64 + this.loginButtonIcon = registration.loginButtonIcon;
  65 + }
  66 +
  67 + @Override
  68 + @JsonProperty(access = JsonProperty.Access.READ_ONLY)
  69 + public String getName() {
  70 + return loginButtonLabel;
  71 + }
  72 +
  73 + @Override
  74 + public String getSearchText() {
  75 + return getName();
  76 + }
  77 +}
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ClientRegistrationDto.java
@@ -17,7 +17,6 @@ package org.thingsboard.server.common.data.oauth2; @@ -17,7 +17,6 @@ package org.thingsboard.server.common.data.oauth2;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import lombok.*; 19 import lombok.*;
20 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;  
21 20
22 import java.util.List; 21 import java.util.List;
23 22
@@ -27,7 +26,7 @@ import java.util.List; @@ -27,7 +26,7 @@ import java.util.List;
27 @NoArgsConstructor 26 @NoArgsConstructor
28 @AllArgsConstructor 27 @AllArgsConstructor
29 @Builder 28 @Builder
30 -public class ClientRegistrationDto { 29 +public class OAuth2RegistrationInfo {
31 private OAuth2MapperConfig mapperConfig; 30 private OAuth2MapperConfig mapperConfig;
32 private String clientId; 31 private String clientId;
33 private String clientSecret; 32 private String clientSecret;
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.oauth2.deprecated;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import lombok.*;
  20 +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  21 +
  22 +import java.util.List;
  23 +
  24 +@Deprecated
  25 +@EqualsAndHashCode
  26 +@Data
  27 +@ToString(exclude = {"clientSecret"})
  28 +@NoArgsConstructor
  29 +@AllArgsConstructor
  30 +@Builder
  31 +public class ClientRegistrationDto {
  32 + private OAuth2MapperConfig mapperConfig;
  33 + private String clientId;
  34 + private String clientSecret;
  35 + private String authorizationUri;
  36 + private String accessTokenUri;
  37 + private List<String> scope;
  38 + private String userInfoUri;
  39 + private String userNameAttributeName;
  40 + private String jwkSetUri;
  41 + private String clientAuthenticationMethod;
  42 + private String loginButtonLabel;
  43 + private String loginButtonIcon;
  44 + private JsonNode additionalInfo;
  45 +}
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/deprecated/DomainInfo.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/DomainInfo.java
@@ -13,10 +13,12 @@ @@ -13,10 +13,12 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.oauth2; 16 +package org.thingsboard.server.common.data.oauth2.deprecated;
17 17
18 import lombok.*; 18 import lombok.*;
  19 +import org.thingsboard.server.common.data.oauth2.SchemeType;
19 20
  21 +@Deprecated
20 @EqualsAndHashCode 22 @EqualsAndHashCode
21 @Data 23 @Data
22 @ToString 24 @ToString
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/deprecated/ExtendedOAuth2ClientRegistrationInfo.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/ExtendedOAuth2ClientRegistrationInfo.java
@@ -13,11 +13,14 @@ @@ -13,11 +13,14 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.oauth2; 16 +package org.thingsboard.server.common.data.oauth2.deprecated;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
  20 +import org.thingsboard.server.common.data.oauth2.SchemeType;
  21 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
20 22
  23 +@Deprecated
21 @EqualsAndHashCode(callSuper = true) 24 @EqualsAndHashCode(callSuper = true)
22 @Data 25 @Data
23 public class ExtendedOAuth2ClientRegistrationInfo extends OAuth2ClientRegistrationInfo { 26 public class ExtendedOAuth2ClientRegistrationInfo extends OAuth2ClientRegistrationInfo {
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/deprecated/OAuth2ClientRegistration.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistration.java
@@ -13,16 +13,18 @@ @@ -13,16 +13,18 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.oauth2; 16 +package org.thingsboard.server.common.data.oauth2.deprecated;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
20 import lombok.NoArgsConstructor; 20 import lombok.NoArgsConstructor;
21 import lombok.ToString; 21 import lombok.ToString;
22 import org.thingsboard.server.common.data.BaseData; 22 import org.thingsboard.server.common.data.BaseData;
23 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;  
24 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; 23 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationId;
  24 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
  25 +import org.thingsboard.server.common.data.oauth2.SchemeType;
25 26
  27 +@Deprecated
26 @EqualsAndHashCode(callSuper = true) 28 @EqualsAndHashCode(callSuper = true)
27 @Data 29 @Data
28 @ToString 30 @ToString
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/deprecated/OAuth2ClientRegistrationInfo.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationInfo.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.oauth2; 16 +package org.thingsboard.server.common.data.oauth2.deprecated;
17 17
18 import com.fasterxml.jackson.annotation.JsonProperty; 18 import com.fasterxml.jackson.annotation.JsonProperty;
19 import lombok.Data; 19 import lombok.Data;
@@ -22,10 +22,12 @@ import lombok.NoArgsConstructor; @@ -22,10 +22,12 @@ import lombok.NoArgsConstructor;
22 import lombok.ToString; 22 import lombok.ToString;
23 import org.thingsboard.server.common.data.HasName; 23 import org.thingsboard.server.common.data.HasName;
24 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; 24 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
25 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; 25 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
  26 +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
26 27
27 import java.util.List; 28 import java.util.List;
28 29
  30 +@Deprecated
29 @EqualsAndHashCode(callSuper = true) 31 @EqualsAndHashCode(callSuper = true)
30 @Data 32 @Data
31 @ToString(exclude = {"clientSecret"}) 33 @ToString(exclude = {"clientSecret"})
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/deprecated/OAuth2ClientsDomainParams.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsDomainParams.java
@@ -13,13 +13,13 @@ @@ -13,13 +13,13 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.oauth2; 16 +package org.thingsboard.server.common.data.oauth2.deprecated;
17 17
18 import lombok.*; 18 import lombok.*;
19 19
20 import java.util.List; 20 import java.util.List;
21 -import java.util.Set;  
22 21
  22 +@Deprecated
23 @EqualsAndHashCode 23 @EqualsAndHashCode
24 @Data 24 @Data
25 @ToString 25 @ToString
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/deprecated/OAuth2ClientsParams.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientsParams.java
@@ -13,13 +13,13 @@ @@ -13,13 +13,13 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.data.oauth2; 16 +package org.thingsboard.server.common.data.oauth2.deprecated;
17 17
18 import lombok.*; 18 import lombok.*;
19 19
20 import java.util.List; 20 import java.util.List;
21 -import java.util.Set;  
22 21
  22 +@Deprecated
23 @EqualsAndHashCode 23 @EqualsAndHashCode
24 @Data 24 @Data
25 @ToString 25 @ToString
@@ -408,10 +408,20 @@ public class ModelConstants { @@ -408,10 +408,20 @@ public class ModelConstants {
408 /** 408 /**
409 * OAuth2 client registration constants. 409 * OAuth2 client registration constants.
410 */ 410 */
411 - public static final String OAUTH2_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; 411 +
  412 + public static final String OAUTH2_PARAMS_COLUMN_FAMILY_NAME = "oauth2_params";
  413 + public static final String OAUTH2_PARAMS_ENABLED_PROPERTY = "enabled";
  414 + public static final String OAUTH2_PARAMS_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
  415 +
  416 + public static final String OAUTH2_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_registration";
  417 + public static final String OAUTH2_DOMAIN_COLUMN_FAMILY_NAME = "oauth2_domain";
  418 + public static final String OAUTH2_MOBILE_COLUMN_FAMILY_NAME = "oauth2_mobile";
  419 + public static final String OAUTH2_PARAMS_ID_PROPERTY = "oauth2_params_id";
  420 + public static final String OAUTH2_PKG_NAME_PROPERTY = "pkg_name";
  421 + public static final String OAUTH2_CALLBACK_URL_SCHEME_PROPERTY = "callback_url_scheme";
  422 +
412 public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info"; 423 public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info";
413 public static final String OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_client_registration"; 424 public static final String OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_client_registration";
414 - public static final String OAUTH2_CLIENT_REGISTRATION_TO_DOMAIN_COLUMN_FAMILY_NAME = "oauth2_client_registration_to_domain";  
415 public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template"; 425 public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template";
416 public static final String OAUTH2_ENABLED_PROPERTY = "enabled"; 426 public static final String OAUTH2_ENABLED_PROPERTY = "enabled";
417 public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id"; 427 public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id";
@@ -422,7 +432,6 @@ public class ModelConstants { @@ -422,7 +432,6 @@ public class ModelConstants {
422 public static final String OAUTH2_CLIENT_SECRET_PROPERTY = "client_secret"; 432 public static final String OAUTH2_CLIENT_SECRET_PROPERTY = "client_secret";
423 public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri"; 433 public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri";
424 public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri"; 434 public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri";
425 - public static final String OAUTH2_REDIRECT_URI_TEMPLATE_PROPERTY = "redirect_uri_template";  
426 public static final String OAUTH2_SCOPE_PROPERTY = "scope"; 435 public static final String OAUTH2_SCOPE_PROPERTY = "scope";
427 public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri"; 436 public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri";
428 public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name"; 437 public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name";
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import org.thingsboard.server.common.data.id.OAuth2DomainId;
  21 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  22 +import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
  23 +import org.thingsboard.server.common.data.oauth2.SchemeType;
  24 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  25 +import org.thingsboard.server.dao.model.ModelConstants;
  26 +
  27 +import javax.persistence.Column;
  28 +import javax.persistence.Entity;
  29 +import javax.persistence.EnumType;
  30 +import javax.persistence.Enumerated;
  31 +import javax.persistence.Table;
  32 +import java.util.UUID;
  33 +
  34 +@Data
  35 +@EqualsAndHashCode(callSuper = true)
  36 +@Entity
  37 +@Table(name = ModelConstants.OAUTH2_DOMAIN_COLUMN_FAMILY_NAME)
  38 +public class OAuth2DomainEntity extends BaseSqlEntity<OAuth2Domain> {
  39 +
  40 + @Column(name = ModelConstants.OAUTH2_PARAMS_ID_PROPERTY)
  41 + private UUID oauth2ParamsId;
  42 +
  43 + @Column(name = ModelConstants.OAUTH2_DOMAIN_NAME_PROPERTY)
  44 + private String domainName;
  45 +
  46 + @Enumerated(EnumType.STRING)
  47 + @Column(name = ModelConstants.OAUTH2_DOMAIN_SCHEME_PROPERTY)
  48 + private SchemeType domainScheme;
  49 +
  50 + public OAuth2DomainEntity() {
  51 + super();
  52 + }
  53 +
  54 + public OAuth2DomainEntity(OAuth2Domain domain) {
  55 + if (domain.getId() != null) {
  56 + this.setUuid(domain.getId().getId());
  57 + }
  58 + this.setCreatedTime(domain.getCreatedTime());
  59 + if (domain.getOauth2ParamsId() != null) {
  60 + this.oauth2ParamsId = domain.getOauth2ParamsId().getId();
  61 + }
  62 + this.domainName = domain.getDomainName();
  63 + this.domainScheme = domain.getDomainScheme();
  64 + }
  65 +
  66 + @Override
  67 + public OAuth2Domain toData() {
  68 + OAuth2Domain domain = new OAuth2Domain();
  69 + domain.setId(new OAuth2DomainId(id));
  70 + domain.setCreatedTime(createdTime);
  71 + domain.setOauth2ParamsId(new OAuth2ParamsId(oauth2ParamsId));
  72 + domain.setDomainName(domainName);
  73 + domain.setDomainScheme(domainScheme);
  74 + return domain;
  75 + }
  76 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import org.thingsboard.server.common.data.id.OAuth2MobileId;
  21 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  22 +import org.thingsboard.server.common.data.oauth2.OAuth2Mobile;
  23 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  24 +import org.thingsboard.server.dao.model.ModelConstants;
  25 +
  26 +import javax.persistence.Column;
  27 +import javax.persistence.Entity;
  28 +import javax.persistence.Table;
  29 +import java.util.UUID;
  30 +
  31 +@Data
  32 +@EqualsAndHashCode(callSuper = true)
  33 +@Entity
  34 +@Table(name = ModelConstants.OAUTH2_MOBILE_COLUMN_FAMILY_NAME)
  35 +public class OAuth2MobileEntity extends BaseSqlEntity<OAuth2Mobile> {
  36 +
  37 + @Column(name = ModelConstants.OAUTH2_PARAMS_ID_PROPERTY)
  38 + private UUID oauth2ParamsId;
  39 +
  40 + @Column(name = ModelConstants.OAUTH2_PKG_NAME_PROPERTY)
  41 + private String pkgName;
  42 +
  43 + @Column(name = ModelConstants.OAUTH2_CALLBACK_URL_SCHEME_PROPERTY)
  44 + private String callbackUrlScheme;
  45 +
  46 + public OAuth2MobileEntity() {
  47 + super();
  48 + }
  49 +
  50 + public OAuth2MobileEntity(OAuth2Mobile mobile) {
  51 + if (mobile.getId() != null) {
  52 + this.setUuid(mobile.getId().getId());
  53 + }
  54 + this.setCreatedTime(mobile.getCreatedTime());
  55 + if (mobile.getOauth2ParamsId() != null) {
  56 + this.oauth2ParamsId = mobile.getOauth2ParamsId().getId();
  57 + }
  58 + this.pkgName = mobile.getPkgName();
  59 + this.callbackUrlScheme = mobile.getCallbackUrlScheme();
  60 + }
  61 +
  62 + @Override
  63 + public OAuth2Mobile toData() {
  64 + OAuth2Mobile mobile = new OAuth2Mobile();
  65 + mobile.setId(new OAuth2MobileId(id));
  66 + mobile.setCreatedTime(createdTime);
  67 + mobile.setOauth2ParamsId(new OAuth2ParamsId(oauth2ParamsId));
  68 + mobile.setPkgName(pkgName);
  69 + mobile.setCallbackUrlScheme(callbackUrlScheme);
  70 + return mobile;
  71 + }
  72 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import lombok.Data;
  19 +import lombok.EqualsAndHashCode;
  20 +import lombok.NoArgsConstructor;
  21 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  22 +import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.common.data.oauth2.OAuth2Params;
  24 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  25 +import org.thingsboard.server.dao.model.ModelConstants;
  26 +
  27 +import javax.persistence.Column;
  28 +import javax.persistence.Entity;
  29 +import javax.persistence.Table;
  30 +import java.util.UUID;
  31 +
  32 +@Data
  33 +@EqualsAndHashCode(callSuper = true)
  34 +@Entity
  35 +@Table(name = ModelConstants.OAUTH2_PARAMS_COLUMN_FAMILY_NAME)
  36 +@NoArgsConstructor
  37 +public class OAuth2ParamsEntity extends BaseSqlEntity<OAuth2Params> {
  38 +
  39 + @Column(name = ModelConstants.OAUTH2_PARAMS_ENABLED_PROPERTY)
  40 + private Boolean enabled;
  41 +
  42 + @Column(name = ModelConstants.OAUTH2_PARAMS_TENANT_ID_PROPERTY)
  43 + private UUID tenantId;
  44 +
  45 + public OAuth2ParamsEntity(OAuth2Params oauth2Params) {
  46 + if (oauth2Params.getId() != null) {
  47 + this.setUuid(oauth2Params.getUuidId());
  48 + }
  49 + this.setCreatedTime(oauth2Params.getCreatedTime());
  50 + this.enabled = oauth2Params.isEnabled();
  51 + if (oauth2Params.getTenantId() != null) {
  52 + this.tenantId = oauth2Params.getTenantId().getId();
  53 + }
  54 + }
  55 +
  56 + @Override
  57 + public OAuth2Params toData() {
  58 + OAuth2Params oauth2Params = new OAuth2Params();
  59 + oauth2Params.setId(new OAuth2ParamsId(id));
  60 + oauth2Params.setCreatedTime(createdTime);
  61 + oauth2Params.setTenantId(new TenantId(tenantId));
  62 + oauth2Params.setEnabled(enabled);
  63 + return oauth2Params;
  64 + }
  65 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import lombok.Data;
  20 +import lombok.EqualsAndHashCode;
  21 +import org.hibernate.annotations.Type;
  22 +import org.hibernate.annotations.TypeDef;
  23 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  24 +import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
  25 +import org.thingsboard.server.common.data.oauth2.MapperType;
  26 +import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig;
  27 +import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
  28 +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  29 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  30 +import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType;
  31 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  32 +import org.thingsboard.server.dao.model.ModelConstants;
  33 +import org.thingsboard.server.dao.util.mapping.JsonStringType;
  34 +
  35 +import javax.persistence.Column;
  36 +import javax.persistence.Entity;
  37 +import javax.persistence.EnumType;
  38 +import javax.persistence.Enumerated;
  39 +import javax.persistence.Table;
  40 +import java.util.Arrays;
  41 +import java.util.UUID;
  42 +
  43 +@Data
  44 +@EqualsAndHashCode(callSuper = true)
  45 +@Entity
  46 +@TypeDef(name = "json", typeClass = JsonStringType.class)
  47 +@Table(name = ModelConstants.OAUTH2_REGISTRATION_COLUMN_FAMILY_NAME)
  48 +public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> {
  49 +
  50 + @Column(name = ModelConstants.OAUTH2_PARAMS_ID_PROPERTY)
  51 + private UUID oauth2ParamsId;
  52 + @Column(name = ModelConstants.OAUTH2_CLIENT_ID_PROPERTY)
  53 + private String clientId;
  54 + @Column(name = ModelConstants.OAUTH2_CLIENT_SECRET_PROPERTY)
  55 + private String clientSecret;
  56 + @Column(name = ModelConstants.OAUTH2_AUTHORIZATION_URI_PROPERTY)
  57 + private String authorizationUri;
  58 + @Column(name = ModelConstants.OAUTH2_TOKEN_URI_PROPERTY)
  59 + private String tokenUri;
  60 + @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY)
  61 + private String scope;
  62 + @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY)
  63 + private String userInfoUri;
  64 + @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY)
  65 + private String userNameAttributeName;
  66 + @Column(name = ModelConstants.OAUTH2_JWK_SET_URI_PROPERTY)
  67 + private String jwkSetUri;
  68 + @Column(name = ModelConstants.OAUTH2_CLIENT_AUTHENTICATION_METHOD_PROPERTY)
  69 + private String clientAuthenticationMethod;
  70 + @Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_LABEL_PROPERTY)
  71 + private String loginButtonLabel;
  72 + @Column(name = ModelConstants.OAUTH2_LOGIN_BUTTON_ICON_PROPERTY)
  73 + private String loginButtonIcon;
  74 + @Column(name = ModelConstants.OAUTH2_ALLOW_USER_CREATION_PROPERTY)
  75 + private Boolean allowUserCreation;
  76 + @Column(name = ModelConstants.OAUTH2_ACTIVATE_USER_PROPERTY)
  77 + private Boolean activateUser;
  78 + @Enumerated(EnumType.STRING)
  79 + @Column(name = ModelConstants.OAUTH2_MAPPER_TYPE_PROPERTY)
  80 + private MapperType type;
  81 + @Column(name = ModelConstants.OAUTH2_EMAIL_ATTRIBUTE_KEY_PROPERTY)
  82 + private String emailAttributeKey;
  83 + @Column(name = ModelConstants.OAUTH2_FIRST_NAME_ATTRIBUTE_KEY_PROPERTY)
  84 + private String firstNameAttributeKey;
  85 + @Column(name = ModelConstants.OAUTH2_LAST_NAME_ATTRIBUTE_KEY_PROPERTY)
  86 + private String lastNameAttributeKey;
  87 + @Enumerated(EnumType.STRING)
  88 + @Column(name = ModelConstants.OAUTH2_TENANT_NAME_STRATEGY_PROPERTY)
  89 + private TenantNameStrategyType tenantNameStrategy;
  90 + @Column(name = ModelConstants.OAUTH2_TENANT_NAME_PATTERN_PROPERTY)
  91 + private String tenantNamePattern;
  92 + @Column(name = ModelConstants.OAUTH2_CUSTOMER_NAME_PATTERN_PROPERTY)
  93 + private String customerNamePattern;
  94 + @Column(name = ModelConstants.OAUTH2_DEFAULT_DASHBOARD_NAME_PROPERTY)
  95 + private String defaultDashboardName;
  96 + @Column(name = ModelConstants.OAUTH2_ALWAYS_FULL_SCREEN_PROPERTY)
  97 + private Boolean alwaysFullScreen;
  98 + @Column(name = ModelConstants.OAUTH2_MAPPER_URL_PROPERTY)
  99 + private String url;
  100 + @Column(name = ModelConstants.OAUTH2_MAPPER_USERNAME_PROPERTY)
  101 + private String username;
  102 + @Column(name = ModelConstants.OAUTH2_MAPPER_PASSWORD_PROPERTY)
  103 + private String password;
  104 + @Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY)
  105 + private Boolean sendToken;
  106 +
  107 + @Type(type = "json")
  108 + @Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY)
  109 + private JsonNode additionalInfo;
  110 +
  111 + public OAuth2RegistrationEntity() {
  112 + super();
  113 + }
  114 +
  115 + public OAuth2RegistrationEntity(OAuth2Registration registration) {
  116 + if (registration.getId() != null) {
  117 + this.setUuid(registration.getId().getId());
  118 + }
  119 + this.setCreatedTime(registration.getCreatedTime());
  120 + if (registration.getOauth2ParamsId() != null) {
  121 + this.oauth2ParamsId = registration.getOauth2ParamsId().getId();
  122 + }
  123 + this.clientId = registration.getClientId();
  124 + this.clientSecret = registration.getClientSecret();
  125 + this.authorizationUri = registration.getAuthorizationUri();
  126 + this.tokenUri = registration.getAccessTokenUri();
  127 + this.scope = registration.getScope().stream().reduce((result, element) -> result + "," + element).orElse("");
  128 + this.userInfoUri = registration.getUserInfoUri();
  129 + this.userNameAttributeName = registration.getUserNameAttributeName();
  130 + this.jwkSetUri = registration.getJwkSetUri();
  131 + this.clientAuthenticationMethod = registration.getClientAuthenticationMethod();
  132 + this.loginButtonLabel = registration.getLoginButtonLabel();
  133 + this.loginButtonIcon = registration.getLoginButtonIcon();
  134 + this.additionalInfo = registration.getAdditionalInfo();
  135 + OAuth2MapperConfig mapperConfig = registration.getMapperConfig();
  136 + if (mapperConfig != null) {
  137 + this.allowUserCreation = mapperConfig.isAllowUserCreation();
  138 + this.activateUser = mapperConfig.isActivateUser();
  139 + this.type = mapperConfig.getType();
  140 + OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
  141 + if (basicConfig != null) {
  142 + this.emailAttributeKey = basicConfig.getEmailAttributeKey();
  143 + this.firstNameAttributeKey = basicConfig.getFirstNameAttributeKey();
  144 + this.lastNameAttributeKey = basicConfig.getLastNameAttributeKey();
  145 + this.tenantNameStrategy = basicConfig.getTenantNameStrategy();
  146 + this.tenantNamePattern = basicConfig.getTenantNamePattern();
  147 + this.customerNamePattern = basicConfig.getCustomerNamePattern();
  148 + this.defaultDashboardName = basicConfig.getDefaultDashboardName();
  149 + this.alwaysFullScreen = basicConfig.isAlwaysFullScreen();
  150 + }
  151 + OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom();
  152 + if (customConfig != null) {
  153 + this.url = customConfig.getUrl();
  154 + this.username = customConfig.getUsername();
  155 + this.password = customConfig.getPassword();
  156 + this.sendToken = customConfig.isSendToken();
  157 + }
  158 + }
  159 + }
  160 +
  161 + @Override
  162 + public OAuth2Registration toData() {
  163 + OAuth2Registration registration = new OAuth2Registration();
  164 + registration.setId(new OAuth2RegistrationId(id));
  165 + registration.setCreatedTime(createdTime);
  166 + registration.setOauth2ParamsId(new OAuth2ParamsId(oauth2ParamsId));
  167 + registration.setAdditionalInfo(additionalInfo);
  168 + registration.setMapperConfig(
  169 + OAuth2MapperConfig.builder()
  170 + .allowUserCreation(allowUserCreation)
  171 + .activateUser(activateUser)
  172 + .type(type)
  173 + .basic(
  174 + (type == MapperType.BASIC || type == MapperType.GITHUB) ?
  175 + OAuth2BasicMapperConfig.builder()
  176 + .emailAttributeKey(emailAttributeKey)
  177 + .firstNameAttributeKey(firstNameAttributeKey)
  178 + .lastNameAttributeKey(lastNameAttributeKey)
  179 + .tenantNameStrategy(tenantNameStrategy)
  180 + .tenantNamePattern(tenantNamePattern)
  181 + .customerNamePattern(customerNamePattern)
  182 + .defaultDashboardName(defaultDashboardName)
  183 + .alwaysFullScreen(alwaysFullScreen)
  184 + .build()
  185 + : null
  186 + )
  187 + .custom(
  188 + type == MapperType.CUSTOM ?
  189 + OAuth2CustomMapperConfig.builder()
  190 + .url(url)
  191 + .username(username)
  192 + .password(password)
  193 + .sendToken(sendToken)
  194 + .build()
  195 + : null
  196 + )
  197 + .build()
  198 + );
  199 + registration.setClientId(clientId);
  200 + registration.setClientSecret(clientSecret);
  201 + registration.setAuthorizationUri(authorizationUri);
  202 + registration.setAccessTokenUri(tokenUri);
  203 + registration.setScope(Arrays.asList(scope.split(",")));
  204 + registration.setUserInfoUri(userInfoUri);
  205 + registration.setUserNameAttributeName(userNameAttributeName);
  206 + registration.setJwkSetUri(jwkSetUri);
  207 + registration.setClientAuthenticationMethod(clientAuthenticationMethod);
  208 + registration.setLoginButtonLabel(loginButtonLabel);
  209 + registration.setLoginButtonIcon(loginButtonIcon);
  210 + return registration;
  211 + }
  212 +}
dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/AbstractOAuth2ClientRegistrationInfoEntity.java renamed from dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractOAuth2ClientRegistrationInfoEntity.java
@@ -13,22 +13,25 @@ @@ -13,22 +13,25 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.model.sql; 16 +package org.thingsboard.server.dao.model.sql.deprecated;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import lombok.Data; 19 import lombok.Data;
20 import lombok.EqualsAndHashCode; 20 import lombok.EqualsAndHashCode;
21 import org.hibernate.annotations.Type; 21 import org.hibernate.annotations.Type;
22 import org.hibernate.annotations.TypeDef; 22 import org.hibernate.annotations.TypeDef;
23 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; 23 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
24 import org.thingsboard.server.common.data.oauth2.*; 24 import org.thingsboard.server.common.data.oauth2.*;
  25 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
25 import org.thingsboard.server.dao.model.BaseSqlEntity; 26 import org.thingsboard.server.dao.model.BaseSqlEntity;
26 import org.thingsboard.server.dao.model.ModelConstants; 27 import org.thingsboard.server.dao.model.ModelConstants;
  28 +import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
27 import org.thingsboard.server.dao.util.mapping.JsonStringType; 29 import org.thingsboard.server.dao.util.mapping.JsonStringType;
28 30
29 import javax.persistence.*; 31 import javax.persistence.*;
30 import java.util.Arrays; 32 import java.util.Arrays;
31 33
  34 +@Deprecated
32 @Data 35 @Data
33 @EqualsAndHashCode(callSuper = true) 36 @EqualsAndHashCode(callSuper = true)
34 @TypeDef(name = "json", typeClass = JsonStringType.class) 37 @TypeDef(name = "json", typeClass = JsonStringType.class)
dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/ExtendedOAuth2ClientRegistrationInfoEntity.java renamed from dao/src/main/java/org/thingsboard/server/dao/model/sql/ExtendedOAuth2ClientRegistrationInfoEntity.java
@@ -13,13 +13,14 @@ @@ -13,13 +13,14 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.model.sql; 16 +package org.thingsboard.server.dao.model.sql.deprecated;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
20 -import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo; 20 +import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
21 import org.thingsboard.server.common.data.oauth2.SchemeType; 21 import org.thingsboard.server.common.data.oauth2.SchemeType;
22 22
  23 +@Deprecated
23 @Data 24 @Data
24 @EqualsAndHashCode(callSuper = true) 25 @EqualsAndHashCode(callSuper = true)
25 public class ExtendedOAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity<ExtendedOAuth2ClientRegistrationInfo> { 26 public class ExtendedOAuth2ClientRegistrationInfoEntity extends AbstractOAuth2ClientRegistrationInfoEntity<ExtendedOAuth2ClientRegistrationInfo> {
dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationEntity.java renamed from dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationEntity.java
@@ -13,22 +13,23 @@ @@ -13,22 +13,23 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.model.sql; 16 +package org.thingsboard.server.dao.model.sql.deprecated;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
20 import org.hibernate.annotations.TypeDef; 20 import org.hibernate.annotations.TypeDef;
21 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationId;  
22 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; 21 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationId;
  22 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
23 import org.thingsboard.server.common.data.oauth2.*; 23 import org.thingsboard.server.common.data.oauth2.*;
  24 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
24 import org.thingsboard.server.dao.model.BaseSqlEntity; 25 import org.thingsboard.server.dao.model.BaseSqlEntity;
25 import org.thingsboard.server.dao.model.ModelConstants; 26 import org.thingsboard.server.dao.model.ModelConstants;
26 import org.thingsboard.server.dao.util.mapping.JsonStringType; 27 import org.thingsboard.server.dao.util.mapping.JsonStringType;
27 28
28 import javax.persistence.*; 29 import javax.persistence.*;
29 -import java.util.Arrays;  
30 import java.util.UUID; 30 import java.util.UUID;
31 31
  32 +@Deprecated
32 @Data 33 @Data
33 @EqualsAndHashCode(callSuper = true) 34 @EqualsAndHashCode(callSuper = true)
34 @Entity 35 @Entity
dao/src/main/java/org/thingsboard/server/dao/model/sql/deprecated/OAuth2ClientRegistrationInfoEntity.java renamed from dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientRegistrationInfoEntity.java
@@ -13,18 +13,19 @@ @@ -13,18 +13,19 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.model.sql; 16 +package org.thingsboard.server.dao.model.sql.deprecated;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.EqualsAndHashCode; 19 import lombok.EqualsAndHashCode;
20 import org.hibernate.annotations.TypeDef; 20 import org.hibernate.annotations.TypeDef;
21 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; 21 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
22 import org.thingsboard.server.dao.model.ModelConstants; 22 import org.thingsboard.server.dao.model.ModelConstants;
23 import org.thingsboard.server.dao.util.mapping.JsonStringType; 23 import org.thingsboard.server.dao.util.mapping.JsonStringType;
24 24
25 import javax.persistence.Entity; 25 import javax.persistence.Entity;
26 import javax.persistence.Table; 26 import javax.persistence.Table;
27 27
  28 +@Deprecated
28 @Data 29 @Data
29 @EqualsAndHashCode(callSuper = true) 30 @EqualsAndHashCode(callSuper = true)
30 @Entity 31 @Entity
@@ -21,7 +21,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio @@ -21,7 +21,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
21 import org.springframework.security.oauth2.core.AuthorizationGrantType; 21 import org.springframework.security.oauth2.core.AuthorizationGrantType;
22 import org.springframework.security.oauth2.core.ClientAuthenticationMethod; 22 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
23 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
24 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; 24 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
25 25
26 import java.util.UUID; 26 import java.util.UUID;
27 27
@@ -34,25 +34,25 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep @@ -34,25 +34,25 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
34 34
35 @Override 35 @Override
36 public ClientRegistration findByRegistrationId(String registrationId) { 36 public ClientRegistration findByRegistrationId(String registrationId) {
37 - OAuth2ClientRegistrationInfo oAuth2ClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(UUID.fromString(registrationId));  
38 - return oAuth2ClientRegistrationInfo == null ?  
39 - null : toSpringClientRegistration(oAuth2ClientRegistrationInfo); 37 + OAuth2Registration registration = oAuth2Service.findRegistration(UUID.fromString(registrationId));
  38 + return registration == null ?
  39 + null : toSpringClientRegistration(registration);
40 } 40 }
41 41
42 - private ClientRegistration toSpringClientRegistration(OAuth2ClientRegistrationInfo localClientRegistration){  
43 - String registrationId = localClientRegistration.getUuidId().toString(); 42 + private ClientRegistration toSpringClientRegistration(OAuth2Registration registration){
  43 + String registrationId = registration.getUuidId().toString();
44 return ClientRegistration.withRegistrationId(registrationId) 44 return ClientRegistration.withRegistrationId(registrationId)
45 - .clientName(localClientRegistration.getName())  
46 - .clientId(localClientRegistration.getClientId())  
47 - .authorizationUri(localClientRegistration.getAuthorizationUri())  
48 - .clientSecret(localClientRegistration.getClientSecret())  
49 - .tokenUri(localClientRegistration.getAccessTokenUri())  
50 - .scope(localClientRegistration.getScope()) 45 + .clientName(registration.getName())
  46 + .clientId(registration.getClientId())
  47 + .authorizationUri(registration.getAuthorizationUri())
  48 + .clientSecret(registration.getClientSecret())
  49 + .tokenUri(registration.getAccessTokenUri())
  50 + .scope(registration.getScope())
51 .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) 51 .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
52 - .userInfoUri(localClientRegistration.getUserInfoUri())  
53 - .userNameAttributeName(localClientRegistration.getUserNameAttributeName())  
54 - .jwkSetUri(localClientRegistration.getJwkSetUri())  
55 - .clientAuthenticationMethod(new ClientAuthenticationMethod(localClientRegistration.getClientAuthenticationMethod())) 52 + .userInfoUri(registration.getUserInfoUri())
  53 + .userNameAttributeName(registration.getUserNameAttributeName())
  54 + .jwkSetUri(registration.getJwkSetUri())
  55 + .clientAuthenticationMethod(new ClientAuthenticationMethod(registration.getClientAuthenticationMethod()))
56 .redirectUri(defaultRedirectUriTemplate) 56 .redirectUri(defaultRedirectUriTemplate)
57 .build(); 57 .build();
58 } 58 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.oauth2;
  17 +
  18 +import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
  19 +import org.thingsboard.server.dao.Dao;
  20 +
  21 +import java.util.List;
  22 +import java.util.UUID;
  23 +
  24 +public interface OAuth2DomainDao extends Dao<OAuth2Domain> {
  25 +
  26 + List<OAuth2Domain> findByOAuth2ParamsId(UUID oauth2ParamsId);
  27 +
  28 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.oauth2;
  17 +
  18 +import org.thingsboard.server.common.data.oauth2.OAuth2Mobile;
  19 +import org.thingsboard.server.dao.Dao;
  20 +
  21 +import java.util.List;
  22 +import java.util.UUID;
  23 +
  24 +public interface OAuth2MobileDao extends Dao<OAuth2Mobile> {
  25 +
  26 + List<OAuth2Mobile> findByOAuth2ParamsId(UUID oauth2ParamsId);
  27 +
  28 +}
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ParamsDao.java renamed from dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationDao.java
@@ -15,9 +15,9 @@ @@ -15,9 +15,9 @@
15 */ 15 */
16 package org.thingsboard.server.dao.oauth2; 16 package org.thingsboard.server.dao.oauth2;
17 17
18 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration; 18 +import org.thingsboard.server.common.data.oauth2.OAuth2Params;
19 import org.thingsboard.server.dao.Dao; 19 import org.thingsboard.server.dao.Dao;
20 20
21 -public interface OAuth2ClientRegistrationDao extends Dao<OAuth2ClientRegistration> { 21 +public interface OAuth2ParamsDao extends Dao<OAuth2Params> {
22 void deleteAll(); 22 void deleteAll();
23 } 23 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.oauth2;
  17 +
  18 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  19 +import org.thingsboard.server.common.data.oauth2.SchemeType;
  20 +import org.thingsboard.server.dao.Dao;
  21 +
  22 +import java.util.List;
  23 +import java.util.UUID;
  24 +
  25 +public interface OAuth2RegistrationDao extends Dao<OAuth2Registration> {
  26 +
  27 + List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgName(List<SchemeType> domainSchemes, String domainName, String pkgName);
  28 +
  29 + List<OAuth2Registration> findByOAuth2ParamsId(UUID oauth2ParamsId);
  30 +
  31 + String findCallbackUrlScheme(UUID id, String pkgName);
  32 +
  33 +}
@@ -19,11 +19,21 @@ import lombok.extern.slf4j.Slf4j; @@ -19,11 +19,21 @@ import lombok.extern.slf4j.Slf4j;
19 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
21 import org.springframework.util.StringUtils; 21 import org.springframework.util.StringUtils;
  22 +import org.thingsboard.server.common.data.BaseData;
22 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
23 import org.thingsboard.server.common.data.oauth2.*; 24 import org.thingsboard.server.common.data.oauth2.*;
  25 +import org.thingsboard.server.common.data.oauth2.deprecated.ClientRegistrationDto;
  26 +import org.thingsboard.server.common.data.oauth2.deprecated.DomainInfo;
  27 +import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
  28 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
  29 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
  30 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsDomainParams;
  31 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
24 import org.thingsboard.server.dao.entity.AbstractEntityService; 32 import org.thingsboard.server.dao.entity.AbstractEntityService;
25 import org.thingsboard.server.dao.exception.DataValidationException; 33 import org.thingsboard.server.dao.exception.DataValidationException;
26 import org.thingsboard.server.dao.exception.IncorrectParameterException; 34 import org.thingsboard.server.dao.exception.IncorrectParameterException;
  35 +import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationDao;
  36 +import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationInfoDao;
27 37
28 import javax.transaction.Transactional; 38 import javax.transaction.Transactional;
29 import java.util.*; 39 import java.util.*;
@@ -45,9 +55,17 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -45,9 +55,17 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
45 private OAuth2ClientRegistrationInfoDao clientRegistrationInfoDao; 55 private OAuth2ClientRegistrationInfoDao clientRegistrationInfoDao;
46 @Autowired 56 @Autowired
47 private OAuth2ClientRegistrationDao clientRegistrationDao; 57 private OAuth2ClientRegistrationDao clientRegistrationDao;
  58 + @Autowired
  59 + private OAuth2ParamsDao oauth2ParamsDao;
  60 + @Autowired
  61 + private OAuth2RegistrationDao oauth2RegistrationDao;
  62 + @Autowired
  63 + private OAuth2DomainDao oauth2DomainDao;
  64 + @Autowired
  65 + private OAuth2MobileDao oauth2MobileDao;
48 66
49 @Override 67 @Override
50 - public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName) { 68 + public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName) {
51 log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName); 69 log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName);
52 if (domainSchemeStr == null) { 70 if (domainSchemeStr == null) {
53 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); 71 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
@@ -59,12 +77,12 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -59,12 +77,12 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
59 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); 77 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
60 } 78 }
61 validateString(domainName, INCORRECT_DOMAIN_NAME + domainName); 79 validateString(domainName, INCORRECT_DOMAIN_NAME + domainName);
62 - return clientRegistrationInfoDao.findByDomainSchemesAndDomainName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName).stream()  
63 - .filter(OAuth2ClientRegistrationInfo::isEnabled) 80 + return oauth2RegistrationDao.findEnabledByDomainSchemesDomainNameAndPkgName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName, pkgName).stream()
64 .map(OAuth2Utils::toClientInfo) 81 .map(OAuth2Utils::toClientInfo)
65 .collect(Collectors.toList()); 82 .collect(Collectors.toList());
66 } 83 }
67 84
  85 + @Deprecated
68 @Override 86 @Override
69 @Transactional 87 @Transactional
70 public void saveOAuth2Params(OAuth2ClientsParams oauth2Params) { 88 public void saveOAuth2Params(OAuth2ClientsParams oauth2Params) {
@@ -86,6 +104,33 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -86,6 +104,33 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
86 } 104 }
87 105
88 @Override 106 @Override
  107 + @Transactional
  108 + public void saveOAuth2Info(OAuth2Info oauth2Info) {
  109 + log.trace("Executing saveOAuth2Info [{}]", oauth2Info);
  110 + oauth2InfoValidator.accept(oauth2Info);
  111 + oauth2ParamsDao.deleteAll();
  112 + oauth2Info.getOauth2ParamsInfos().forEach(oauth2ParamsInfo -> {
  113 + OAuth2Params oauth2Params = OAuth2Utils.infoToOAuth2Params(oauth2Info);
  114 + OAuth2Params savedOauth2Params = oauth2ParamsDao.save(TenantId.SYS_TENANT_ID, oauth2Params);
  115 + oauth2ParamsInfo.getClientRegistrations().forEach(registrationInfo -> {
  116 + OAuth2Registration registration = OAuth2Utils.toOAuth2Registration(savedOauth2Params.getId(), registrationInfo);
  117 + oauth2RegistrationDao.save(TenantId.SYS_TENANT_ID, registration);
  118 + });
  119 + oauth2ParamsInfo.getDomainInfos().forEach(domainInfo -> {
  120 + OAuth2Domain domain = OAuth2Utils.toOAuth2Domain(savedOauth2Params.getId(), domainInfo);
  121 + oauth2DomainDao.save(TenantId.SYS_TENANT_ID, domain);
  122 + });
  123 + if (oauth2ParamsInfo.getMobileInfos() != null) {
  124 + oauth2ParamsInfo.getMobileInfos().forEach(mobileInfo -> {
  125 + OAuth2Mobile mobile = OAuth2Utils.toOAuth2Mobile(savedOauth2Params.getId(), mobileInfo);
  126 + oauth2MobileDao.save(TenantId.SYS_TENANT_ID, mobile);
  127 + });
  128 + }
  129 + });
  130 + }
  131 +
  132 + @Deprecated
  133 + @Override
89 public OAuth2ClientsParams findOAuth2Params() { 134 public OAuth2ClientsParams findOAuth2Params() {
90 log.trace("Executing findOAuth2Params"); 135 log.trace("Executing findOAuth2Params");
91 List<ExtendedOAuth2ClientRegistrationInfo> extendedInfos = clientRegistrationInfoDao.findAllExtended(); 136 List<ExtendedOAuth2ClientRegistrationInfo> extendedInfos = clientRegistrationInfoDao.findAllExtended();
@@ -93,16 +138,42 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -93,16 +138,42 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
93 } 138 }
94 139
95 @Override 140 @Override
96 - public OAuth2ClientRegistrationInfo findClientRegistrationInfo(UUID id) {  
97 - log.trace("Executing findClientRegistrationInfo [{}]", id); 141 + public OAuth2Info findOAuth2Info() {
  142 + log.trace("Executing findOAuth2Info");
  143 + OAuth2Info oauth2Info = new OAuth2Info();
  144 + List<OAuth2Params> oauth2ParamsList = oauth2ParamsDao.find(TenantId.SYS_TENANT_ID);
  145 + oauth2Info.setEnabled(oauth2ParamsList.stream().anyMatch(param -> param.isEnabled()));
  146 + List<OAuth2ParamsInfo> oauth2ParamsInfos = new ArrayList<>();
  147 + oauth2Info.setOauth2ParamsInfos(oauth2ParamsInfos);
  148 + oauth2ParamsList.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(oauth2Params -> {
  149 + List<OAuth2Registration> registrations = oauth2RegistrationDao.findByOAuth2ParamsId(oauth2Params.getId().getId());
  150 + List<OAuth2Domain> domains = oauth2DomainDao.findByOAuth2ParamsId(oauth2Params.getId().getId());
  151 + List<OAuth2Mobile> mobiles = oauth2MobileDao.findByOAuth2ParamsId(oauth2Params.getId().getId());
  152 + oauth2ParamsInfos.add(OAuth2Utils.toOAuth2ParamsInfo(registrations, domains, mobiles));
  153 + });
  154 + return oauth2Info;
  155 + }
  156 +
  157 + @Override
  158 + public OAuth2Registration findRegistration(UUID id) {
  159 + log.trace("Executing findRegistration [{}]", id);
  160 + validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id);
  161 + return oauth2RegistrationDao.findById(null, id);
  162 + }
  163 +
  164 + @Override
  165 + public String findCallbackUrlScheme(UUID id, String pkgName) {
  166 + log.trace("Executing findCallbackUrlScheme [{}][{}]", id, pkgName);
98 validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id); 167 validateId(id, INCORRECT_CLIENT_REGISTRATION_ID + id);
99 - return clientRegistrationInfoDao.findById(null, id); 168 + validateString(pkgName, "Incorrect package name");
  169 + return oauth2RegistrationDao.findCallbackUrlScheme(id, pkgName);
100 } 170 }
101 171
  172 +
102 @Override 173 @Override
103 - public List<OAuth2ClientRegistrationInfo> findAllClientRegistrationInfos() {  
104 - log.trace("Executing findAllClientRegistrationInfos");  
105 - return clientRegistrationInfoDao.findAll(); 174 + public List<OAuth2Registration> findAllRegistrations() {
  175 + log.trace("Executing findAllRegistrations");
  176 + return oauth2RegistrationDao.find(TenantId.SYS_TENANT_ID);
106 } 177 }
107 178
108 private final Consumer<OAuth2ClientsParams> clientParamsValidator = oauth2Params -> { 179 private final Consumer<OAuth2ClientsParams> clientParamsValidator = oauth2Params -> {
@@ -212,4 +283,136 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se @@ -212,4 +283,136 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
212 } 283 }
213 } 284 }
214 }; 285 };
  286 +
  287 + private final Consumer<OAuth2Info> oauth2InfoValidator = oauth2Info -> {
  288 + if (oauth2Info == null
  289 + || oauth2Info.getOauth2ParamsInfos() == null) {
  290 + throw new DataValidationException("OAuth2 param infos should be specified!");
  291 + }
  292 + for (OAuth2ParamsInfo oauth2Params : oauth2Info.getOauth2ParamsInfos()) {
  293 + if (oauth2Params.getDomainInfos() == null
  294 + || oauth2Params.getDomainInfos().isEmpty()) {
  295 + throw new DataValidationException("List of domain configuration should be specified!");
  296 + }
  297 + for (OAuth2DomainInfo domainInfo : oauth2Params.getDomainInfos()) {
  298 + if (StringUtils.isEmpty(domainInfo.getName())) {
  299 + throw new DataValidationException("Domain name should be specified!");
  300 + }
  301 + if (domainInfo.getScheme() == null) {
  302 + throw new DataValidationException("Domain scheme should be specified!");
  303 + }
  304 + }
  305 + oauth2Params.getDomainInfos().stream()
  306 + .collect(Collectors.groupingBy(OAuth2DomainInfo::getName))
  307 + .forEach((domainName, domainInfos) -> {
  308 + if (domainInfos.size() > 1 && domainInfos.stream().anyMatch(domainInfo -> domainInfo.getScheme() == SchemeType.MIXED)) {
  309 + throw new DataValidationException("MIXED scheme type shouldn't be combined with another scheme type!");
  310 + }
  311 + domainInfos.stream()
  312 + .collect(Collectors.groupingBy(OAuth2DomainInfo::getScheme))
  313 + .forEach((schemeType, domainInfosBySchemeType) -> {
  314 + if (domainInfosBySchemeType.size() > 1) {
  315 + throw new DataValidationException("Domain name and protocol must be unique within OAuth2 parameters!");
  316 + }
  317 + });
  318 + });
  319 + if (oauth2Params.getMobileInfos() != null) {
  320 + for (OAuth2MobileInfo mobileInfo : oauth2Params.getMobileInfos()) {
  321 + if (StringUtils.isEmpty(mobileInfo.getPkgName())) {
  322 + throw new DataValidationException("Package should be specified!");
  323 + }
  324 + if (StringUtils.isEmpty(mobileInfo.getCallbackUrlScheme())) {
  325 + throw new DataValidationException("Callback URL scheme should be specified!");
  326 + }
  327 + }
  328 + oauth2Params.getMobileInfos().stream()
  329 + .collect(Collectors.groupingBy(OAuth2MobileInfo::getPkgName))
  330 + .forEach((pkgName, mobileInfos) -> {
  331 + if (mobileInfos.size() > 1) {
  332 + throw new DataValidationException("Mobile app package name must be unique within OAuth2 parameters!");
  333 + }
  334 + });
  335 + }
  336 + if (oauth2Params.getClientRegistrations() == null || oauth2Params.getClientRegistrations().isEmpty()) {
  337 + throw new DataValidationException("Client registrations should be specified!");
  338 + }
  339 + for (OAuth2RegistrationInfo clientRegistration : oauth2Params.getClientRegistrations()) {
  340 + if (StringUtils.isEmpty(clientRegistration.getClientId())) {
  341 + throw new DataValidationException("Client ID should be specified!");
  342 + }
  343 + if (StringUtils.isEmpty(clientRegistration.getClientSecret())) {
  344 + throw new DataValidationException("Client secret should be specified!");
  345 + }
  346 + if (StringUtils.isEmpty(clientRegistration.getAuthorizationUri())) {
  347 + throw new DataValidationException("Authorization uri should be specified!");
  348 + }
  349 + if (StringUtils.isEmpty(clientRegistration.getAccessTokenUri())) {
  350 + throw new DataValidationException("Token uri should be specified!");
  351 + }
  352 + if (StringUtils.isEmpty(clientRegistration.getScope())) {
  353 + throw new DataValidationException("Scope should be specified!");
  354 + }
  355 + if (StringUtils.isEmpty(clientRegistration.getUserInfoUri())) {
  356 + throw new DataValidationException("User info uri should be specified!");
  357 + }
  358 + if (StringUtils.isEmpty(clientRegistration.getUserNameAttributeName())) {
  359 + throw new DataValidationException("User name attribute name should be specified!");
  360 + }
  361 + if (StringUtils.isEmpty(clientRegistration.getClientAuthenticationMethod())) {
  362 + throw new DataValidationException("Client authentication method should be specified!");
  363 + }
  364 + if (StringUtils.isEmpty(clientRegistration.getLoginButtonLabel())) {
  365 + throw new DataValidationException("Login button label should be specified!");
  366 + }
  367 + OAuth2MapperConfig mapperConfig = clientRegistration.getMapperConfig();
  368 + if (mapperConfig == null) {
  369 + throw new DataValidationException("Mapper config should be specified!");
  370 + }
  371 + if (mapperConfig.getType() == null) {
  372 + throw new DataValidationException("Mapper config type should be specified!");
  373 + }
  374 + if (mapperConfig.getType() == MapperType.BASIC) {
  375 + OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
  376 + if (basicConfig == null) {
  377 + throw new DataValidationException("Basic config should be specified!");
  378 + }
  379 + if (StringUtils.isEmpty(basicConfig.getEmailAttributeKey())) {
  380 + throw new DataValidationException("Email attribute key should be specified!");
  381 + }
  382 + if (basicConfig.getTenantNameStrategy() == null) {
  383 + throw new DataValidationException("Tenant name strategy should be specified!");
  384 + }
  385 + if (basicConfig.getTenantNameStrategy() == TenantNameStrategyType.CUSTOM
  386 + && StringUtils.isEmpty(basicConfig.getTenantNamePattern())) {
  387 + throw new DataValidationException("Tenant name pattern should be specified!");
  388 + }
  389 + }
  390 + if (mapperConfig.getType() == MapperType.GITHUB) {
  391 + OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
  392 + if (basicConfig == null) {
  393 + throw new DataValidationException("Basic config should be specified!");
  394 + }
  395 + if (!StringUtils.isEmpty(basicConfig.getEmailAttributeKey())) {
  396 + throw new DataValidationException("Email attribute key cannot be configured for GITHUB mapper type!");
  397 + }
  398 + if (basicConfig.getTenantNameStrategy() == null) {
  399 + throw new DataValidationException("Tenant name strategy should be specified!");
  400 + }
  401 + if (basicConfig.getTenantNameStrategy() == TenantNameStrategyType.CUSTOM
  402 + && StringUtils.isEmpty(basicConfig.getTenantNamePattern())) {
  403 + throw new DataValidationException("Tenant name pattern should be specified!");
  404 + }
  405 + }
  406 + if (mapperConfig.getType() == MapperType.CUSTOM) {
  407 + OAuth2CustomMapperConfig customConfig = mapperConfig.getCustom();
  408 + if (customConfig == null) {
  409 + throw new DataValidationException("Custom config should be specified!");
  410 + }
  411 + if (StringUtils.isEmpty(customConfig.getUrl())) {
  412 + throw new DataValidationException("Custom mapper URL should be specified!");
  413 + }
  414 + }
  415 + }
  416 + }
  417 + };
215 } 418 }
@@ -15,19 +15,30 @@ @@ -15,19 +15,30 @@
15 */ 15 */
16 package org.thingsboard.server.dao.oauth2; 16 package org.thingsboard.server.dao.oauth2;
17 17
18 -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId; 18 +import org.thingsboard.server.common.data.BaseData;
  19 +import org.thingsboard.server.common.data.id.OAuth2ParamsId;
  20 +import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.data.id.deprecated.OAuth2ClientRegistrationInfoId;
19 import org.thingsboard.server.common.data.oauth2.*; 22 import org.thingsboard.server.common.data.oauth2.*;
  23 +import org.thingsboard.server.common.data.oauth2.deprecated.ClientRegistrationDto;
  24 +import org.thingsboard.server.common.data.oauth2.deprecated.DomainInfo;
  25 +import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
  26 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
  27 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
  28 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsDomainParams;
  29 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams;
20 30
21 import java.util.*; 31 import java.util.*;
  32 +import java.util.stream.Collectors;
22 33
23 public class OAuth2Utils { 34 public class OAuth2Utils {
24 public static final String OAUTH2_AUTHORIZATION_PATH_TEMPLATE = "/oauth2/authorization/%s"; 35 public static final String OAUTH2_AUTHORIZATION_PATH_TEMPLATE = "/oauth2/authorization/%s";
25 36
26 - public static OAuth2ClientInfo toClientInfo(OAuth2ClientRegistrationInfo clientRegistrationInfo) { 37 + public static OAuth2ClientInfo toClientInfo(OAuth2Registration registration) {
27 OAuth2ClientInfo client = new OAuth2ClientInfo(); 38 OAuth2ClientInfo client = new OAuth2ClientInfo();
28 - client.setName(clientRegistrationInfo.getLoginButtonLabel());  
29 - client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, clientRegistrationInfo.getUuidId().toString()));  
30 - client.setIcon(clientRegistrationInfo.getLoginButtonIcon()); 39 + client.setName(registration.getLoginButtonLabel());
  40 + client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, registration.getUuidId().toString()));
  41 + client.setIcon(registration.getLoginButtonIcon());
31 return client; 42 return client;
32 } 43 }
33 44
@@ -99,4 +110,127 @@ public class OAuth2Utils { @@ -99,4 +110,127 @@ public class OAuth2Utils {
99 clientRegistration.setDomainScheme(domainScheme); 110 clientRegistration.setDomainScheme(domainScheme);
100 return clientRegistration; 111 return clientRegistration;
101 } 112 }
  113 +
  114 + public static OAuth2ParamsInfo toOAuth2ParamsInfo(List<OAuth2Registration> registrations, List<OAuth2Domain> domains, List<OAuth2Mobile> mobiles) {
  115 + OAuth2ParamsInfo oauth2ParamsInfo = new OAuth2ParamsInfo();
  116 + oauth2ParamsInfo.setClientRegistrations(registrations.stream().sorted(Comparator.comparing(BaseData::getUuidId)).map(OAuth2Utils::toOAuth2RegistrationInfo).collect(Collectors.toList()));
  117 + oauth2ParamsInfo.setDomainInfos(domains.stream().sorted(Comparator.comparing(BaseData::getUuidId)).map(OAuth2Utils::toOAuth2DomainInfo).collect(Collectors.toList()));
  118 + oauth2ParamsInfo.setMobileInfos(mobiles.stream().sorted(Comparator.comparing(BaseData::getUuidId)).map(OAuth2Utils::toOAuth2MobileInfo).collect(Collectors.toList()));
  119 + return oauth2ParamsInfo;
  120 + }
  121 +
  122 + public static OAuth2RegistrationInfo toOAuth2RegistrationInfo(OAuth2Registration registration) {
  123 + return OAuth2RegistrationInfo.builder()
  124 + .mapperConfig(registration.getMapperConfig())
  125 + .clientId(registration.getClientId())
  126 + .clientSecret(registration.getClientSecret())
  127 + .authorizationUri(registration.getAuthorizationUri())
  128 + .accessTokenUri(registration.getAccessTokenUri())
  129 + .scope(registration.getScope())
  130 + .userInfoUri(registration.getUserInfoUri())
  131 + .userNameAttributeName(registration.getUserNameAttributeName())
  132 + .jwkSetUri(registration.getJwkSetUri())
  133 + .clientAuthenticationMethod(registration.getClientAuthenticationMethod())
  134 + .loginButtonLabel(registration.getLoginButtonLabel())
  135 + .loginButtonIcon(registration.getLoginButtonIcon())
  136 + .additionalInfo(registration.getAdditionalInfo())
  137 + .build();
  138 + }
  139 +
  140 + public static OAuth2DomainInfo toOAuth2DomainInfo(OAuth2Domain domain) {
  141 + return OAuth2DomainInfo.builder()
  142 + .name(domain.getDomainName())
  143 + .scheme(domain.getDomainScheme())
  144 + .build();
  145 + }
  146 +
  147 + public static OAuth2MobileInfo toOAuth2MobileInfo(OAuth2Mobile mobile) {
  148 + return OAuth2MobileInfo.builder()
  149 + .pkgName(mobile.getPkgName())
  150 + .callbackUrlScheme(mobile.getCallbackUrlScheme())
  151 + .build();
  152 + }
  153 +
  154 + public static OAuth2Params infoToOAuth2Params(OAuth2Info oauth2Info) {
  155 + OAuth2Params oauth2Params = new OAuth2Params();
  156 + oauth2Params.setEnabled(oauth2Info.isEnabled());
  157 + oauth2Params.setTenantId(TenantId.SYS_TENANT_ID);
  158 + return oauth2Params;
  159 + }
  160 +
  161 + public static OAuth2Registration toOAuth2Registration(OAuth2ParamsId oauth2ParamsId, OAuth2RegistrationInfo registrationInfo) {
  162 + OAuth2Registration registration = new OAuth2Registration();
  163 + registration.setOauth2ParamsId(oauth2ParamsId);
  164 + registration.setMapperConfig(registrationInfo.getMapperConfig());
  165 + registration.setClientId(registrationInfo.getClientId());
  166 + registration.setClientSecret(registrationInfo.getClientSecret());
  167 + registration.setAuthorizationUri(registrationInfo.getAuthorizationUri());
  168 + registration.setAccessTokenUri(registrationInfo.getAccessTokenUri());
  169 + registration.setScope(registrationInfo.getScope());
  170 + registration.setUserInfoUri(registrationInfo.getUserInfoUri());
  171 + registration.setUserNameAttributeName(registrationInfo.getUserNameAttributeName());
  172 + registration.setJwkSetUri(registrationInfo.getJwkSetUri());
  173 + registration.setClientAuthenticationMethod(registrationInfo.getClientAuthenticationMethod());
  174 + registration.setLoginButtonLabel(registrationInfo.getLoginButtonLabel());
  175 + registration.setLoginButtonIcon(registrationInfo.getLoginButtonIcon());
  176 + registration.setAdditionalInfo(registrationInfo.getAdditionalInfo());
  177 + return registration;
  178 + }
  179 +
  180 + public static OAuth2Domain toOAuth2Domain(OAuth2ParamsId oauth2ParamsId, OAuth2DomainInfo domainInfo) {
  181 + OAuth2Domain domain = new OAuth2Domain();
  182 + domain.setOauth2ParamsId(oauth2ParamsId);
  183 + domain.setDomainName(domainInfo.getName());
  184 + domain.setDomainScheme(domainInfo.getScheme());
  185 + return domain;
  186 + }
  187 +
  188 + public static OAuth2Mobile toOAuth2Mobile(OAuth2ParamsId oauth2ParamsId, OAuth2MobileInfo mobileInfo) {
  189 + OAuth2Mobile mobile = new OAuth2Mobile();
  190 + mobile.setOauth2ParamsId(oauth2ParamsId);
  191 + mobile.setPkgName(mobileInfo.getPkgName());
  192 + mobile.setCallbackUrlScheme(mobileInfo.getCallbackUrlScheme());
  193 + return mobile;
  194 + }
  195 +
  196 + @Deprecated
  197 + public static OAuth2Info clientParamsToOAuth2Info(OAuth2ClientsParams clientsParams) {
  198 + OAuth2Info oauth2Info = new OAuth2Info();
  199 + oauth2Info.setEnabled(clientsParams.isEnabled());
  200 + oauth2Info.setOauth2ParamsInfos(clientsParams.getDomainsParams().stream().map(OAuth2Utils::clientsDomainParamsToOAuth2ParamsInfo).collect(Collectors.toList()));
  201 + return oauth2Info;
  202 + }
  203 +
  204 + private static OAuth2ParamsInfo clientsDomainParamsToOAuth2ParamsInfo(OAuth2ClientsDomainParams clientsDomainParams) {
  205 + OAuth2ParamsInfo oauth2ParamsInfo = new OAuth2ParamsInfo();
  206 + oauth2ParamsInfo.setMobileInfos(Collections.emptyList());
  207 + oauth2ParamsInfo.setClientRegistrations(clientsDomainParams.getClientRegistrations().stream().map(OAuth2Utils::clientRegistrationDtoToOAuth2RegistrationInfo).collect(Collectors.toList()));
  208 + oauth2ParamsInfo.setDomainInfos(clientsDomainParams.getDomainInfos().stream().map(OAuth2Utils::domainInfoToOAuth2DomainInfo).collect(Collectors.toList()));
  209 + return oauth2ParamsInfo;
  210 + }
  211 +
  212 + private static OAuth2RegistrationInfo clientRegistrationDtoToOAuth2RegistrationInfo(ClientRegistrationDto clientRegistrationDto) {
  213 + return OAuth2RegistrationInfo.builder()
  214 + .mapperConfig(clientRegistrationDto.getMapperConfig())
  215 + .clientId(clientRegistrationDto.getClientId())
  216 + .clientSecret(clientRegistrationDto.getClientSecret())
  217 + .authorizationUri(clientRegistrationDto.getAuthorizationUri())
  218 + .accessTokenUri(clientRegistrationDto.getAccessTokenUri())
  219 + .scope(clientRegistrationDto.getScope())
  220 + .userInfoUri(clientRegistrationDto.getUserInfoUri())
  221 + .userNameAttributeName(clientRegistrationDto.getUserNameAttributeName())
  222 + .jwkSetUri(clientRegistrationDto.getJwkSetUri())
  223 + .clientAuthenticationMethod(clientRegistrationDto.getClientAuthenticationMethod())
  224 + .loginButtonLabel(clientRegistrationDto.getLoginButtonLabel())
  225 + .loginButtonIcon(clientRegistrationDto.getLoginButtonIcon())
  226 + .additionalInfo(clientRegistrationDto.getAdditionalInfo())
  227 + .build();
  228 + }
  229 +
  230 + private static OAuth2DomainInfo domainInfoToOAuth2DomainInfo(DomainInfo domainInfo) {
  231 + return OAuth2DomainInfo.builder()
  232 + .name(domainInfo.getName())
  233 + .scheme(domainInfo.getScheme())
  234 + .build();
  235 + }
102 } 236 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.oauth2.deprecated;
  17 +
  18 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
  19 +import org.thingsboard.server.dao.Dao;
  20 +
  21 +@Deprecated
  22 +public interface OAuth2ClientRegistrationDao extends Dao<OAuth2ClientRegistration> {
  23 + void deleteAll();
  24 +}
dao/src/main/java/org/thingsboard/server/dao/oauth2/deprecated/OAuth2ClientRegistrationInfoDao.java renamed from dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientRegistrationInfoDao.java
@@ -13,16 +13,16 @@ @@ -13,16 +13,16 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.oauth2; 16 +package org.thingsboard.server.dao.oauth2.deprecated;
17 17
18 -import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;  
19 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; 18 +import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
  19 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
20 import org.thingsboard.server.common.data.oauth2.SchemeType; 20 import org.thingsboard.server.common.data.oauth2.SchemeType;
21 import org.thingsboard.server.dao.Dao; 21 import org.thingsboard.server.dao.Dao;
22 22
23 import java.util.List; 23 import java.util.List;
24 -import java.util.Set;  
25 24
  25 +@Deprecated
26 public interface OAuth2ClientRegistrationInfoDao extends Dao<OAuth2ClientRegistrationInfo> { 26 public interface OAuth2ClientRegistrationInfoDao extends Dao<OAuth2ClientRegistrationInfo> {
27 List<OAuth2ClientRegistrationInfo> findAll(); 27 List<OAuth2ClientRegistrationInfo> findAll();
28 28
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.oauth2.OAuth2Domain;
  22 +import org.thingsboard.server.dao.DaoUtil;
  23 +import org.thingsboard.server.dao.model.sql.OAuth2DomainEntity;
  24 +import org.thingsboard.server.dao.oauth2.OAuth2DomainDao;
  25 +import org.thingsboard.server.dao.sql.JpaAbstractDao;
  26 +
  27 +import java.util.List;
  28 +import java.util.UUID;
  29 +
  30 +@Component
  31 +@RequiredArgsConstructor
  32 +public class JpaOAuth2DomainDao extends JpaAbstractDao<OAuth2DomainEntity, OAuth2Domain> implements OAuth2DomainDao {
  33 +
  34 + private final OAuth2DomainRepository repository;
  35 +
  36 + @Override
  37 + protected Class<OAuth2DomainEntity> getEntityClass() {
  38 + return OAuth2DomainEntity.class;
  39 + }
  40 +
  41 + @Override
  42 + protected CrudRepository<OAuth2DomainEntity, UUID> getCrudRepository() {
  43 + return repository;
  44 + }
  45 +
  46 + @Override
  47 + public List<OAuth2Domain> findByOAuth2ParamsId(UUID oauth2ParamsId) {
  48 + return DaoUtil.convertDataList(repository.findByOauth2ParamsId(oauth2ParamsId));
  49 + }
  50 +
  51 +}
  52 +
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.oauth2.OAuth2Mobile;
  22 +import org.thingsboard.server.dao.DaoUtil;
  23 +import org.thingsboard.server.dao.model.sql.OAuth2MobileEntity;
  24 +import org.thingsboard.server.dao.oauth2.OAuth2MobileDao;
  25 +import org.thingsboard.server.dao.sql.JpaAbstractDao;
  26 +
  27 +import java.util.List;
  28 +import java.util.UUID;
  29 +
  30 +@Component
  31 +@RequiredArgsConstructor
  32 +public class JpaOAuth2MobileDao extends JpaAbstractDao<OAuth2MobileEntity, OAuth2Mobile> implements OAuth2MobileDao {
  33 +
  34 + private final OAuth2MobileRepository repository;
  35 +
  36 + @Override
  37 + protected Class<OAuth2MobileEntity> getEntityClass() {
  38 + return OAuth2MobileEntity.class;
  39 + }
  40 +
  41 + @Override
  42 + protected CrudRepository<OAuth2MobileEntity, UUID> getCrudRepository() {
  43 + return repository;
  44 + }
  45 +
  46 + @Override
  47 + public List<OAuth2Mobile> findByOAuth2ParamsId(UUID oauth2ParamsId) {
  48 + return DaoUtil.convertDataList(repository.findByOauth2ParamsId(oauth2ParamsId));
  49 + }
  50 +
  51 +}
  52 +
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.oauth2.OAuth2Params;
  22 +import org.thingsboard.server.dao.model.sql.OAuth2ParamsEntity;
  23 +import org.thingsboard.server.dao.oauth2.OAuth2ParamsDao;
  24 +import org.thingsboard.server.dao.sql.JpaAbstractDao;
  25 +
  26 +import java.util.UUID;
  27 +
  28 +@Component
  29 +@RequiredArgsConstructor
  30 +public class JpaOAuth2ParamsDao extends JpaAbstractDao<OAuth2ParamsEntity, OAuth2Params> implements OAuth2ParamsDao {
  31 + private final OAuth2ParamsRepository repository;
  32 +
  33 + @Override
  34 + protected Class<OAuth2ParamsEntity> getEntityClass() {
  35 + return OAuth2ParamsEntity.class;
  36 + }
  37 +
  38 + @Override
  39 + protected CrudRepository<OAuth2ParamsEntity, UUID> getCrudRepository() {
  40 + return repository;
  41 + }
  42 +
  43 + @Override
  44 + public void deleteAll() {
  45 + repository.deleteAll();
  46 + }
  47 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  22 +import org.thingsboard.server.common.data.oauth2.SchemeType;
  23 +import org.thingsboard.server.dao.DaoUtil;
  24 +import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
  25 +import org.thingsboard.server.dao.oauth2.OAuth2RegistrationDao;
  26 +import org.thingsboard.server.dao.sql.JpaAbstractDao;
  27 +
  28 +import java.util.List;
  29 +import java.util.UUID;
  30 +
  31 +@Component
  32 +@RequiredArgsConstructor
  33 +public class JpaOAuth2RegistrationDao extends JpaAbstractDao<OAuth2RegistrationEntity, OAuth2Registration> implements OAuth2RegistrationDao {
  34 +
  35 + private final OAuth2RegistrationRepository repository;
  36 +
  37 + @Override
  38 + protected Class<OAuth2RegistrationEntity> getEntityClass() {
  39 + return OAuth2RegistrationEntity.class;
  40 + }
  41 +
  42 + @Override
  43 + protected CrudRepository<OAuth2RegistrationEntity, UUID> getCrudRepository() {
  44 + return repository;
  45 + }
  46 +
  47 + @Override
  48 + public List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgName(List<SchemeType> domainSchemes, String domainName, String pkgName) {
  49 + return DaoUtil.convertDataList(repository.findAllEnabledByDomainSchemesNameAndPkgName(domainSchemes, domainName, pkgName));
  50 + }
  51 +
  52 + @Override
  53 + public List<OAuth2Registration> findByOAuth2ParamsId(UUID oauth2ParamsId) {
  54 + return DaoUtil.convertDataList(repository.findByOauth2ParamsId(oauth2ParamsId));
  55 + }
  56 +
  57 + @Override
  58 + public String findCallbackUrlScheme(UUID id, String pkgName) {
  59 + return repository.findCallbackUrlScheme(id, pkgName);
  60 + }
  61 +
  62 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import org.springframework.data.repository.CrudRepository;
  19 +import org.thingsboard.server.dao.model.sql.OAuth2DomainEntity;
  20 +
  21 +import java.util.List;
  22 +import java.util.UUID;
  23 +
  24 +public interface OAuth2DomainRepository extends CrudRepository<OAuth2DomainEntity, UUID> {
  25 +
  26 + List<OAuth2DomainEntity> findByOauth2ParamsId(UUID oauth2ParamsId);
  27 +
  28 +}
  29 +
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import org.springframework.data.repository.CrudRepository;
  19 +import org.thingsboard.server.dao.model.sql.OAuth2MobileEntity;
  20 +
  21 +import java.util.List;
  22 +import java.util.UUID;
  23 +
  24 +public interface OAuth2MobileRepository extends CrudRepository<OAuth2MobileEntity, UUID> {
  25 +
  26 + List<OAuth2MobileEntity> findByOauth2ParamsId(UUID oauth2ParamsId);
  27 +
  28 +}
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ParamsRepository.java renamed from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationRepository.java
@@ -16,9 +16,9 @@ @@ -16,9 +16,9 @@
16 package org.thingsboard.server.dao.sql.oauth2; 16 package org.thingsboard.server.dao.sql.oauth2;
17 17
18 import org.springframework.data.repository.CrudRepository; 18 import org.springframework.data.repository.CrudRepository;
19 -import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity; 19 +import org.thingsboard.server.dao.model.sql.OAuth2ParamsEntity;
20 20
21 import java.util.UUID; 21 import java.util.UUID;
22 22
23 -public interface OAuth2ClientRegistrationRepository extends CrudRepository<OAuth2ClientRegistrationEntity, UUID> { 23 +public interface OAuth2ParamsRepository extends CrudRepository<OAuth2ParamsEntity, UUID> {
24 } 24 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2;
  17 +
  18 +import org.springframework.data.jpa.repository.Query;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.data.repository.query.Param;
  21 +import org.thingsboard.server.common.data.oauth2.SchemeType;
  22 +import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
  23 +
  24 +import java.util.List;
  25 +import java.util.UUID;
  26 +
  27 +public interface OAuth2RegistrationRepository extends CrudRepository<OAuth2RegistrationEntity, UUID> {
  28 +
  29 + @Query("SELECT reg " +
  30 + "FROM OAuth2RegistrationEntity reg " +
  31 + "LEFT JOIN OAuth2ParamsEntity params on reg.oauth2ParamsId = params.id " +
  32 + "LEFT JOIN OAuth2DomainEntity domain on reg.oauth2ParamsId = domain.oauth2ParamsId " +
  33 + "LEFT JOIN OAuth2MobileEntity mobile on reg.oauth2ParamsId = mobile.oauth2ParamsId " +
  34 + "WHERE params.enabled = true " +
  35 + "AND domain.domainName = :domainName " +
  36 + "AND domain.domainScheme IN (:domainSchemes) " +
  37 + "AND (:pkgName IS NULL OR mobile.pkgName = :pkgName)")
  38 + List<OAuth2RegistrationEntity> findAllEnabledByDomainSchemesNameAndPkgName(@Param("domainSchemes") List<SchemeType> domainSchemes,
  39 + @Param("domainName") String domainName,
  40 + @Param("pkgName") String pkgName);
  41 +
  42 + List<OAuth2RegistrationEntity> findByOauth2ParamsId(UUID oauth2ParamsId);
  43 +
  44 + @Query("SELECT mobile.callbackUrlScheme " +
  45 + "FROM OAuth2MobileEntity mobile " +
  46 + "LEFT JOIN OAuth2RegistrationEntity reg on mobile.oauth2ParamsId = reg.oauth2ParamsId " +
  47 + "WHERE reg.id = :registrationId " +
  48 + "AND mobile.pkgName = :pkgName")
  49 + String findCallbackUrlScheme(@Param("registrationId") UUID id,
  50 + @Param("pkgName") String pkgName);
  51 +
  52 +}
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationDao.java renamed from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationDao.java
@@ -13,19 +13,19 @@ @@ -13,19 +13,19 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.sql.oauth2; 16 +package org.thingsboard.server.dao.sql.oauth2.deprecated;
17 17
18 import lombok.RequiredArgsConstructor; 18 import lombok.RequiredArgsConstructor;
19 -import lombok.extern.slf4j.Slf4j;  
20 import org.springframework.data.repository.CrudRepository; 19 import org.springframework.data.repository.CrudRepository;
21 import org.springframework.stereotype.Component; 20 import org.springframework.stereotype.Component;
22 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistration;  
23 -import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationEntity;  
24 -import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationDao; 21 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
  22 +import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationEntity;
  23 +import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationDao;
25 import org.thingsboard.server.dao.sql.JpaAbstractDao; 24 import org.thingsboard.server.dao.sql.JpaAbstractDao;
26 25
27 import java.util.UUID; 26 import java.util.UUID;
28 27
  28 +@Deprecated
29 @Component 29 @Component
30 @RequiredArgsConstructor 30 @RequiredArgsConstructor
31 public class JpaOAuth2ClientRegistrationDao extends JpaAbstractDao<OAuth2ClientRegistrationEntity, OAuth2ClientRegistration> implements OAuth2ClientRegistrationDao { 31 public class JpaOAuth2ClientRegistrationDao extends JpaAbstractDao<OAuth2ClientRegistrationEntity, OAuth2ClientRegistration> implements OAuth2ClientRegistrationDao {
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/JpaOAuth2ClientRegistrationInfoDao.java renamed from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientRegistrationInfoDao.java
@@ -13,17 +13,17 @@ @@ -13,17 +13,17 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.sql.oauth2; 16 +package org.thingsboard.server.dao.sql.oauth2.deprecated;
17 17
18 import lombok.RequiredArgsConstructor; 18 import lombok.RequiredArgsConstructor;
19 import org.springframework.data.repository.CrudRepository; 19 import org.springframework.data.repository.CrudRepository;
20 import org.springframework.stereotype.Component; 20 import org.springframework.stereotype.Component;
21 -import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;  
22 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; 21 +import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
  22 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
23 import org.thingsboard.server.common.data.oauth2.SchemeType; 23 import org.thingsboard.server.common.data.oauth2.SchemeType;
24 import org.thingsboard.server.dao.DaoUtil; 24 import org.thingsboard.server.dao.DaoUtil;
25 -import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity;  
26 -import org.thingsboard.server.dao.oauth2.OAuth2ClientRegistrationInfoDao; 25 +import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
  26 +import org.thingsboard.server.dao.oauth2.deprecated.OAuth2ClientRegistrationInfoDao;
27 import org.thingsboard.server.dao.sql.JpaAbstractDao; 27 import org.thingsboard.server.dao.sql.JpaAbstractDao;
28 28
29 import java.util.ArrayList; 29 import java.util.ArrayList;
@@ -31,6 +31,7 @@ import java.util.List; @@ -31,6 +31,7 @@ import java.util.List;
31 import java.util.UUID; 31 import java.util.UUID;
32 import java.util.stream.Collectors; 32 import java.util.stream.Collectors;
33 33
  34 +@Deprecated
34 @Component 35 @Component
35 @RequiredArgsConstructor 36 @RequiredArgsConstructor
36 public class JpaOAuth2ClientRegistrationInfoDao extends JpaAbstractDao<OAuth2ClientRegistrationInfoEntity, OAuth2ClientRegistrationInfo> implements OAuth2ClientRegistrationInfoDao { 37 public class JpaOAuth2ClientRegistrationInfoDao extends JpaAbstractDao<OAuth2ClientRegistrationInfoEntity, OAuth2ClientRegistrationInfo> implements OAuth2ClientRegistrationInfoDao {
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/deprecated/OAuth2ClientRegistrationInfoRepository.java renamed from dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRegistrationInfoRepository.java
@@ -13,18 +13,19 @@ @@ -13,18 +13,19 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.sql.oauth2; 16 +package org.thingsboard.server.dao.sql.oauth2.deprecated;
17 17
18 import org.springframework.data.jpa.repository.Query; 18 import org.springframework.data.jpa.repository.Query;
19 import org.springframework.data.repository.CrudRepository; 19 import org.springframework.data.repository.CrudRepository;
20 import org.springframework.data.repository.query.Param; 20 import org.springframework.data.repository.query.Param;
21 import org.thingsboard.server.common.data.oauth2.SchemeType; 21 import org.thingsboard.server.common.data.oauth2.SchemeType;
22 -import org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity;  
23 -import org.thingsboard.server.dao.model.sql.OAuth2ClientRegistrationInfoEntity; 22 +import org.thingsboard.server.dao.model.sql.deprecated.ExtendedOAuth2ClientRegistrationInfoEntity;
  23 +import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
24 24
25 import java.util.List; 25 import java.util.List;
26 import java.util.UUID; 26 import java.util.UUID;
27 27
  28 +@Deprecated
28 public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> { 29 public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> {
29 @Query("SELECT new OAuth2ClientRegistrationInfoEntity(cr_info) " + 30 @Query("SELECT new OAuth2ClientRegistrationInfoEntity(cr_info) " +
30 "FROM OAuth2ClientRegistrationInfoEntity cr_info " + 31 "FROM OAuth2ClientRegistrationInfoEntity cr_info " +
@@ -34,7 +35,7 @@ public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<O @@ -34,7 +35,7 @@ public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<O
34 List<OAuth2ClientRegistrationInfoEntity> findAllByDomainSchemesAndName(@Param("domainSchemes") List<SchemeType> domainSchemes, 35 List<OAuth2ClientRegistrationInfoEntity> findAllByDomainSchemesAndName(@Param("domainSchemes") List<SchemeType> domainSchemes,
35 @Param("domainName") String domainName); 36 @Param("domainName") String domainName);
36 37
37 - @Query("SELECT new org.thingsboard.server.dao.model.sql.ExtendedOAuth2ClientRegistrationInfoEntity(cr_info, cr.domainName, cr.domainScheme) " + 38 + @Query("SELECT new org.thingsboard.server.dao.model.sql.deprecated.ExtendedOAuth2ClientRegistrationInfoEntity(cr_info, cr.domainName, cr.domainScheme) " +
38 "FROM OAuth2ClientRegistrationInfoEntity cr_info " + 39 "FROM OAuth2ClientRegistrationInfoEntity cr_info " +
39 "LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId ") 40 "LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId ")
40 List<ExtendedOAuth2ClientRegistrationInfoEntity> findAllExtended(); 41 List<ExtendedOAuth2ClientRegistrationInfoEntity> findAllExtended();
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.oauth2.deprecated;
  17 +
  18 +import org.springframework.data.repository.CrudRepository;
  19 +import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationEntity;
  20 +
  21 +import java.util.UUID;
  22 +
  23 +@Deprecated
  24 +public interface OAuth2ClientRegistrationRepository extends CrudRepository<OAuth2ClientRegistrationEntity, UUID> {
  25 +}
@@ -374,9 +374,16 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary ( @@ -374,9 +374,16 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary (
374 CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) 374 CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
375 ); 375 );
376 376
377 -CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (  
378 - id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY, 377 +CREATE TABLE IF NOT EXISTS oauth2_params (
  378 + id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY,
379 enabled boolean, 379 enabled boolean,
  380 + tenant_id uuid,
  381 + created_time bigint NOT NULL
  382 +);
  383 +
  384 +CREATE TABLE IF NOT EXISTS oauth2_registration (
  385 + id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY,
  386 + oauth2_params_id uuid NOT NULL,
380 created_time bigint NOT NULL, 387 created_time bigint NOT NULL,
381 additional_info varchar, 388 additional_info varchar,
382 client_id varchar(255), 389 client_id varchar(255),
@@ -404,15 +411,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info ( @@ -404,15 +411,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
404 custom_url varchar(255), 411 custom_url varchar(255),
405 custom_username varchar(255), 412 custom_username varchar(255),
406 custom_password varchar(255), 413 custom_password varchar(255),
407 - custom_send_token boolean 414 + custom_send_token boolean,
  415 + CONSTRAINT fk_registration_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE
408 ); 416 );
409 417
410 -CREATE TABLE IF NOT EXISTS oauth2_client_registration (  
411 - id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY, 418 +CREATE TABLE IF NOT EXISTS oauth2_domain (
  419 + id uuid NOT NULL CONSTRAINT oauth2_domain_pkey PRIMARY KEY,
  420 + oauth2_params_id uuid NOT NULL,
412 created_time bigint NOT NULL, 421 created_time bigint NOT NULL,
413 domain_name varchar(255), 422 domain_name varchar(255),
414 domain_scheme varchar(31), 423 domain_scheme varchar(31),
415 - client_registration_info_id uuid 424 + CONSTRAINT fk_domain_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
  425 + CONSTRAINT oauth2_domain_unq_key UNIQUE (oauth2_params_id, domain_name, domain_scheme)
  426 +);
  427 +
  428 +CREATE TABLE IF NOT EXISTS oauth2_mobile (
  429 + id uuid NOT NULL CONSTRAINT oauth2_mobile_pkey PRIMARY KEY,
  430 + oauth2_params_id uuid NOT NULL,
  431 + created_time bigint NOT NULL,
  432 + pkg_name varchar(255),
  433 + callback_url_scheme varchar(255),
  434 + CONSTRAINT fk_mobile_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
  435 + CONSTRAINT oauth2_mobile_unq_key UNIQUE (oauth2_params_id, pkg_name)
416 ); 436 );
417 437
418 CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( 438 CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
@@ -443,6 +463,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( @@ -443,6 +463,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
443 CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) 463 CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id)
444 ); 464 );
445 465
  466 +-- Deprecated
  467 +CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
  468 + id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
  469 + enabled boolean,
  470 + created_time bigint NOT NULL,
  471 + additional_info varchar,
  472 + client_id varchar(255),
  473 + client_secret varchar(255),
  474 + authorization_uri varchar(255),
  475 + token_uri varchar(255),
  476 + scope varchar(255),
  477 + user_info_uri varchar(255),
  478 + user_name_attribute_name varchar(255),
  479 + jwk_set_uri varchar(255),
  480 + client_authentication_method varchar(255),
  481 + login_button_label varchar(255),
  482 + login_button_icon varchar(255),
  483 + allow_user_creation boolean,
  484 + activate_user boolean,
  485 + type varchar(31),
  486 + basic_email_attribute_key varchar(31),
  487 + basic_first_name_attribute_key varchar(31),
  488 + basic_last_name_attribute_key varchar(31),
  489 + basic_tenant_name_strategy varchar(31),
  490 + basic_tenant_name_pattern varchar(255),
  491 + basic_customer_name_pattern varchar(255),
  492 + basic_default_dashboard_name varchar(255),
  493 + basic_always_full_screen boolean,
  494 + custom_url varchar(255),
  495 + custom_username varchar(255),
  496 + custom_password varchar(255),
  497 + custom_send_token boolean
  498 +);
  499 +
  500 +-- Deprecated
  501 +CREATE TABLE IF NOT EXISTS oauth2_client_registration (
  502 + id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
  503 + created_time bigint NOT NULL,
  504 + domain_name varchar(255),
  505 + domain_scheme varchar(31),
  506 + client_registration_info_id uuid
  507 +);
  508 +
446 CREATE TABLE IF NOT EXISTS api_usage_state ( 509 CREATE TABLE IF NOT EXISTS api_usage_state (
447 id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY, 510 id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY,
448 created_time bigint NOT NULL, 511 created_time bigint NOT NULL,
@@ -411,9 +411,16 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary @@ -411,9 +411,16 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary
411 CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) 411 CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
412 ); 412 );
413 413
414 -CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (  
415 - id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY, 414 +CREATE TABLE IF NOT EXISTS oauth2_params (
  415 + id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY,
416 enabled boolean, 416 enabled boolean,
  417 + tenant_id uuid,
  418 + created_time bigint NOT NULL
  419 +);
  420 +
  421 +CREATE TABLE IF NOT EXISTS oauth2_registration (
  422 + id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY,
  423 + oauth2_params_id uuid NOT NULL,
417 created_time bigint NOT NULL, 424 created_time bigint NOT NULL,
418 additional_info varchar, 425 additional_info varchar,
419 client_id varchar(255), 426 client_id varchar(255),
@@ -441,15 +448,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info ( @@ -441,15 +448,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
441 custom_url varchar(255), 448 custom_url varchar(255),
442 custom_username varchar(255), 449 custom_username varchar(255),
443 custom_password varchar(255), 450 custom_password varchar(255),
444 - custom_send_token boolean 451 + custom_send_token boolean,
  452 + CONSTRAINT fk_registration_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE
445 ); 453 );
446 454
447 -CREATE TABLE IF NOT EXISTS oauth2_client_registration (  
448 - id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY, 455 +CREATE TABLE IF NOT EXISTS oauth2_domain (
  456 + id uuid NOT NULL CONSTRAINT oauth2_domain_pkey PRIMARY KEY,
  457 + oauth2_params_id uuid NOT NULL,
449 created_time bigint NOT NULL, 458 created_time bigint NOT NULL,
450 domain_name varchar(255), 459 domain_name varchar(255),
451 domain_scheme varchar(31), 460 domain_scheme varchar(31),
452 - client_registration_info_id uuid 461 + CONSTRAINT fk_domain_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
  462 + CONSTRAINT oauth2_domain_unq_key UNIQUE (oauth2_params_id, domain_name, domain_scheme)
  463 +);
  464 +
  465 +CREATE TABLE IF NOT EXISTS oauth2_mobile (
  466 + id uuid NOT NULL CONSTRAINT oauth2_mobile_pkey PRIMARY KEY,
  467 + oauth2_params_id uuid NOT NULL,
  468 + created_time bigint NOT NULL,
  469 + pkg_name varchar(255),
  470 + callback_url_scheme varchar(255),
  471 + CONSTRAINT fk_mobile_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE,
  472 + CONSTRAINT oauth2_mobile_unq_key UNIQUE (oauth2_params_id, pkg_name)
453 ); 473 );
454 474
455 CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( 475 CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
@@ -480,6 +500,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( @@ -480,6 +500,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
480 CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) 500 CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id)
481 ); 501 );
482 502
  503 +-- Deprecated
  504 +CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
  505 + id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY,
  506 + enabled boolean,
  507 + created_time bigint NOT NULL,
  508 + additional_info varchar,
  509 + client_id varchar(255),
  510 + client_secret varchar(255),
  511 + authorization_uri varchar(255),
  512 + token_uri varchar(255),
  513 + scope varchar(255),
  514 + user_info_uri varchar(255),
  515 + user_name_attribute_name varchar(255),
  516 + jwk_set_uri varchar(255),
  517 + client_authentication_method varchar(255),
  518 + login_button_label varchar(255),
  519 + login_button_icon varchar(255),
  520 + allow_user_creation boolean,
  521 + activate_user boolean,
  522 + type varchar(31),
  523 + basic_email_attribute_key varchar(31),
  524 + basic_first_name_attribute_key varchar(31),
  525 + basic_last_name_attribute_key varchar(31),
  526 + basic_tenant_name_strategy varchar(31),
  527 + basic_tenant_name_pattern varchar(255),
  528 + basic_customer_name_pattern varchar(255),
  529 + basic_default_dashboard_name varchar(255),
  530 + basic_always_full_screen boolean,
  531 + custom_url varchar(255),
  532 + custom_username varchar(255),
  533 + custom_password varchar(255),
  534 + custom_send_token boolean
  535 +);
  536 +
  537 +-- Deprecated
  538 +CREATE TABLE IF NOT EXISTS oauth2_client_registration (
  539 + id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY,
  540 + created_time bigint NOT NULL,
  541 + domain_name varchar(255),
  542 + domain_scheme varchar(31),
  543 + client_registration_info_id uuid
  544 +);
  545 +
483 CREATE TABLE IF NOT EXISTS api_usage_state ( 546 CREATE TABLE IF NOT EXISTS api_usage_state (
484 id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY, 547 id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY,
485 created_time bigint NOT NULL, 548 created_time bigint NOT NULL,
@@ -16,208 +16,225 @@ @@ -16,208 +16,225 @@
16 package org.thingsboard.server.dao.service; 16 package org.thingsboard.server.dao.service;
17 17
18 import com.google.common.collect.Lists; 18 import com.google.common.collect.Lists;
19 -import com.google.common.collect.Sets;  
20 import org.junit.After; 19 import org.junit.After;
21 import org.junit.Assert; 20 import org.junit.Assert;
22 import org.junit.Before; 21 import org.junit.Before;
23 import org.junit.Test; 22 import org.junit.Test;
24 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
25 -import org.thingsboard.server.common.data.oauth2.*; 24 +import org.thingsboard.server.common.data.oauth2.MapperType;
  25 +import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
  26 +import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
  27 +import org.thingsboard.server.common.data.oauth2.OAuth2DomainInfo;
  28 +import org.thingsboard.server.common.data.oauth2.OAuth2Info;
  29 +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  30 +import org.thingsboard.server.common.data.oauth2.OAuth2MobileInfo;
  31 +import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo;
  32 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
  33 +import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
  34 +import org.thingsboard.server.common.data.oauth2.SchemeType;
26 import org.thingsboard.server.dao.exception.DataValidationException; 35 import org.thingsboard.server.dao.exception.DataValidationException;
27 import org.thingsboard.server.dao.oauth2.OAuth2Service; 36 import org.thingsboard.server.dao.oauth2.OAuth2Service;
28 37
29 -import java.util.*; 38 +import java.util.Arrays;
  39 +import java.util.Collections;
  40 +import java.util.List;
  41 +import java.util.UUID;
30 import java.util.stream.Collectors; 42 import java.util.stream.Collectors;
31 43
32 public class BaseOAuth2ServiceTest extends AbstractServiceTest { 44 public class BaseOAuth2ServiceTest extends AbstractServiceTest {
33 - private static final OAuth2ClientsParams EMPTY_PARAMS = new OAuth2ClientsParams(false, new ArrayList<>()); 45 + private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, Collections.emptyList());
34 46
35 @Autowired 47 @Autowired
36 protected OAuth2Service oAuth2Service; 48 protected OAuth2Service oAuth2Service;
37 49
38 @Before 50 @Before
39 public void beforeRun() { 51 public void beforeRun() {
40 - Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty()); 52 + Assert.assertTrue(oAuth2Service.findAllRegistrations().isEmpty());
41 } 53 }
42 54
43 @After 55 @After
44 public void after() { 56 public void after() {
45 - oAuth2Service.saveOAuth2Params(EMPTY_PARAMS);  
46 - Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty());  
47 - Assert.assertTrue(oAuth2Service.findOAuth2Params().getDomainsParams().isEmpty()); 57 + oAuth2Service.saveOAuth2Info(EMPTY_PARAMS);
  58 + Assert.assertTrue(oAuth2Service.findAllRegistrations().isEmpty());
  59 + Assert.assertTrue(oAuth2Service.findOAuth2Info().getOauth2ParamsInfos().isEmpty());
48 } 60 }
49 61
50 @Test(expected = DataValidationException.class) 62 @Test(expected = DataValidationException.class)
51 public void testSaveHttpAndMixedDomainsTogether() { 63 public void testSaveHttpAndMixedDomainsTogether() {
52 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
53 - OAuth2ClientsDomainParams.builder() 64 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  65 + OAuth2ParamsInfo.builder()
54 .domainInfos(Lists.newArrayList( 66 .domainInfos(Lists.newArrayList(
55 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
56 - DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),  
57 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 67 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  68 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
  69 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
58 )) 70 ))
59 .clientRegistrations(Lists.newArrayList( 71 .clientRegistrations(Lists.newArrayList(
60 - validClientRegistrationDto(),  
61 - validClientRegistrationDto(),  
62 - validClientRegistrationDto() 72 + validRegistrationInfo(),
  73 + validRegistrationInfo(),
  74 + validRegistrationInfo()
63 )) 75 ))
64 .build() 76 .build()
65 )); 77 ));
66 - oAuth2Service.saveOAuth2Params(clientsParams); 78 + oAuth2Service.saveOAuth2Info(oAuth2Info);
67 } 79 }
68 80
69 @Test(expected = DataValidationException.class) 81 @Test(expected = DataValidationException.class)
70 public void testSaveHttpsAndMixedDomainsTogether() { 82 public void testSaveHttpsAndMixedDomainsTogether() {
71 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
72 - OAuth2ClientsDomainParams.builder() 83 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  84 + OAuth2ParamsInfo.builder()
73 .domainInfos(Lists.newArrayList( 85 .domainInfos(Lists.newArrayList(
74 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(),  
75 - DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),  
76 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 86 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(),
  87 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
  88 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
77 )) 89 ))
78 .clientRegistrations(Lists.newArrayList( 90 .clientRegistrations(Lists.newArrayList(
79 - validClientRegistrationDto(),  
80 - validClientRegistrationDto(),  
81 - validClientRegistrationDto() 91 + validRegistrationInfo(),
  92 + validRegistrationInfo(),
  93 + validRegistrationInfo()
82 )) 94 ))
83 .build() 95 .build()
84 )); 96 ));
85 - oAuth2Service.saveOAuth2Params(clientsParams); 97 + oAuth2Service.saveOAuth2Info(oAuth2Info);
86 } 98 }
87 99
88 @Test 100 @Test
89 public void testCreateAndFindParams() { 101 public void testCreateAndFindParams() {
90 - OAuth2ClientsParams clientsParams = createDefaultClientsParams();  
91 - oAuth2Service.saveOAuth2Params(clientsParams);  
92 - OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();  
93 - Assert.assertNotNull(foundClientsParams); 102 + OAuth2Info oAuth2Info = createDefaultOAuth2Info();
  103 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  104 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  105 + Assert.assertNotNull(foundOAuth2Info);
94 // TODO ask if it's safe to check equality on AdditionalProperties 106 // TODO ask if it's safe to check equality on AdditionalProperties
95 - Assert.assertEquals(clientsParams, foundClientsParams); 107 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
96 } 108 }
97 109
98 @Test 110 @Test
99 public void testDisableParams() { 111 public void testDisableParams() {
100 - OAuth2ClientsParams clientsParams = createDefaultClientsParams();  
101 - clientsParams.setEnabled(true);  
102 - oAuth2Service.saveOAuth2Params(clientsParams);  
103 - OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();  
104 - Assert.assertNotNull(foundClientsParams);  
105 - Assert.assertEquals(clientsParams, foundClientsParams);  
106 -  
107 - clientsParams.setEnabled(false);  
108 - oAuth2Service.saveOAuth2Params(clientsParams);  
109 - OAuth2ClientsParams foundDisabledClientsParams = oAuth2Service.findOAuth2Params();  
110 - Assert.assertEquals(clientsParams, foundDisabledClientsParams); 112 + OAuth2Info oAuth2Info = createDefaultOAuth2Info();
  113 + oAuth2Info.setEnabled(true);
  114 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  115 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  116 + Assert.assertNotNull(foundOAuth2Info);
  117 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
  118 +
  119 + oAuth2Info.setEnabled(false);
  120 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  121 + OAuth2Info foundDisabledOAuth2Info = oAuth2Service.findOAuth2Info();
  122 + Assert.assertEquals(oAuth2Info, foundDisabledOAuth2Info);
111 } 123 }
112 124
113 @Test 125 @Test
114 public void testClearDomainParams() { 126 public void testClearDomainParams() {
115 - OAuth2ClientsParams clientsParams = createDefaultClientsParams();  
116 - oAuth2Service.saveOAuth2Params(clientsParams);  
117 - OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();  
118 - Assert.assertNotNull(foundClientsParams);  
119 - Assert.assertEquals(clientsParams, foundClientsParams);  
120 -  
121 - oAuth2Service.saveOAuth2Params(EMPTY_PARAMS);  
122 - OAuth2ClientsParams foundAfterClearClientsParams = oAuth2Service.findOAuth2Params(); 127 + OAuth2Info oAuth2Info = createDefaultOAuth2Info();
  128 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  129 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  130 + Assert.assertNotNull(foundOAuth2Info);
  131 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
  132 +
  133 + oAuth2Service.saveOAuth2Info(EMPTY_PARAMS);
  134 + OAuth2Info foundAfterClearClientsParams = oAuth2Service.findOAuth2Info();
123 Assert.assertNotNull(foundAfterClearClientsParams); 135 Assert.assertNotNull(foundAfterClearClientsParams);
124 Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams); 136 Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams);
125 } 137 }
126 138
127 @Test 139 @Test
128 public void testUpdateClientsParams() { 140 public void testUpdateClientsParams() {
129 - OAuth2ClientsParams clientsParams = createDefaultClientsParams();  
130 - oAuth2Service.saveOAuth2Params(clientsParams);  
131 - OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();  
132 - Assert.assertNotNull(foundClientsParams);  
133 - Assert.assertEquals(clientsParams, foundClientsParams);  
134 -  
135 - OAuth2ClientsParams newClientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
136 - OAuth2ClientsDomainParams.builder() 141 + OAuth2Info oAuth2Info = createDefaultOAuth2Info();
  142 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  143 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  144 + Assert.assertNotNull(foundOAuth2Info);
  145 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
  146 +
  147 + OAuth2Info newOAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  148 + OAuth2ParamsInfo.builder()
137 .domainInfos(Lists.newArrayList( 149 .domainInfos(Lists.newArrayList(
138 - DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build() 150 + OAuth2DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build()
139 )) 151 ))
  152 + .mobileInfos(Collections.emptyList())
140 .clientRegistrations(Lists.newArrayList( 153 .clientRegistrations(Lists.newArrayList(
141 - validClientRegistrationDto() 154 + validRegistrationInfo()
142 )) 155 ))
143 .build(), 156 .build(),
144 - OAuth2ClientsDomainParams.builder() 157 + OAuth2ParamsInfo.builder()
145 .domainInfos(Lists.newArrayList( 158 .domainInfos(Lists.newArrayList(
146 - DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build() 159 + OAuth2DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build()
147 )) 160 ))
  161 + .mobileInfos(Collections.emptyList())
148 .clientRegistrations(Lists.newArrayList( 162 .clientRegistrations(Lists.newArrayList(
149 - validClientRegistrationDto() 163 + validRegistrationInfo()
150 )) 164 ))
151 .build() 165 .build()
152 )); 166 ));
153 - oAuth2Service.saveOAuth2Params(newClientsParams);  
154 - OAuth2ClientsParams foundAfterUpdateClientsParams = oAuth2Service.findOAuth2Params();  
155 - Assert.assertNotNull(foundAfterUpdateClientsParams);  
156 - Assert.assertEquals(newClientsParams, foundAfterUpdateClientsParams); 167 + oAuth2Service.saveOAuth2Info(newOAuth2Info);
  168 + OAuth2Info foundAfterUpdateOAuth2Info = oAuth2Service.findOAuth2Info();
  169 + Assert.assertNotNull(foundAfterUpdateOAuth2Info);
  170 + Assert.assertEquals(newOAuth2Info, foundAfterUpdateOAuth2Info);
157 } 171 }
158 172
159 @Test 173 @Test
160 public void testGetOAuth2Clients() { 174 public void testGetOAuth2Clients() {
161 - List<ClientRegistrationDto> firstGroup = Lists.newArrayList(  
162 - validClientRegistrationDto(),  
163 - validClientRegistrationDto(),  
164 - validClientRegistrationDto(),  
165 - validClientRegistrationDto() 175 + List<OAuth2RegistrationInfo> firstGroup = Lists.newArrayList(
  176 + validRegistrationInfo(),
  177 + validRegistrationInfo(),
  178 + validRegistrationInfo(),
  179 + validRegistrationInfo()
166 ); 180 );
167 - List<ClientRegistrationDto> secondGroup = Lists.newArrayList(  
168 - validClientRegistrationDto(),  
169 - validClientRegistrationDto() 181 + List<OAuth2RegistrationInfo> secondGroup = Lists.newArrayList(
  182 + validRegistrationInfo(),
  183 + validRegistrationInfo()
170 ); 184 );
171 - List<ClientRegistrationDto> thirdGroup = Lists.newArrayList(  
172 - validClientRegistrationDto() 185 + List<OAuth2RegistrationInfo> thirdGroup = Lists.newArrayList(
  186 + validRegistrationInfo()
173 ); 187 );
174 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
175 - OAuth2ClientsDomainParams.builder() 188 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  189 + OAuth2ParamsInfo.builder()
176 .domainInfos(Lists.newArrayList( 190 .domainInfos(Lists.newArrayList(
177 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
178 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
179 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 191 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  192 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  193 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
180 )) 194 ))
  195 + .mobileInfos(Collections.emptyList())
181 .clientRegistrations(firstGroup) 196 .clientRegistrations(firstGroup)
182 .build(), 197 .build(),
183 - OAuth2ClientsDomainParams.builder() 198 + OAuth2ParamsInfo.builder()
184 .domainInfos(Lists.newArrayList( 199 .domainInfos(Lists.newArrayList(
185 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),  
186 - DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() 200 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
  201 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
187 )) 202 ))
  203 + .mobileInfos(Collections.emptyList())
188 .clientRegistrations(secondGroup) 204 .clientRegistrations(secondGroup)
189 .build(), 205 .build(),
190 - OAuth2ClientsDomainParams.builder() 206 + OAuth2ParamsInfo.builder()
191 .domainInfos(Lists.newArrayList( 207 .domainInfos(Lists.newArrayList(
192 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),  
193 - DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build() 208 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
  209 + OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
194 )) 210 ))
  211 + .mobileInfos(Collections.emptyList())
195 .clientRegistrations(thirdGroup) 212 .clientRegistrations(thirdGroup)
196 .build() 213 .build()
197 )); 214 ));
198 215
199 - oAuth2Service.saveOAuth2Params(clientsParams);  
200 - OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();  
201 - Assert.assertNotNull(foundClientsParams);  
202 - Assert.assertEquals(clientsParams, foundClientsParams); 216 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  217 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  218 + Assert.assertNotNull(foundOAuth2Info);
  219 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
203 220
204 List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream() 221 List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream()
205 - .map(clientRegistrationDto -> new OAuth2ClientInfo(  
206 - clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) 222 + .map(registrationInfo -> new OAuth2ClientInfo(
  223 + registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
207 .collect(Collectors.toList()); 224 .collect(Collectors.toList());
208 List<OAuth2ClientInfo> secondGroupClientInfos = secondGroup.stream() 225 List<OAuth2ClientInfo> secondGroupClientInfos = secondGroup.stream()
209 - .map(clientRegistrationDto -> new OAuth2ClientInfo(  
210 - clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) 226 + .map(registrationInfo -> new OAuth2ClientInfo(
  227 + registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
211 .collect(Collectors.toList()); 228 .collect(Collectors.toList());
212 List<OAuth2ClientInfo> thirdGroupClientInfos = thirdGroup.stream() 229 List<OAuth2ClientInfo> thirdGroupClientInfos = thirdGroup.stream()
213 - .map(clientRegistrationDto -> new OAuth2ClientInfo(  
214 - clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) 230 + .map(registrationInfo -> new OAuth2ClientInfo(
  231 + registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
215 .collect(Collectors.toList()); 232 .collect(Collectors.toList());
216 233
217 - List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain"); 234 + List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null);
218 Assert.assertTrue(nonExistentDomainClients.isEmpty()); 235 Assert.assertTrue(nonExistentDomainClients.isEmpty());
219 236
220 - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain"); 237 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null);
221 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); 238 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
222 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 239 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
223 Assert.assertTrue( 240 Assert.assertTrue(
@@ -227,10 +244,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -227,10 +244,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
227 ); 244 );
228 }); 245 });
229 246
230 - List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain"); 247 + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null);
231 Assert.assertTrue(firstDomainHttpsClients.isEmpty()); 248 Assert.assertTrue(firstDomainHttpsClients.isEmpty());
232 249
233 - List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain"); 250 + List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null);
234 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size()); 251 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size());
235 secondGroupClientInfos.forEach(secondGroupClientInfo -> { 252 secondGroupClientInfos.forEach(secondGroupClientInfo -> {
236 Assert.assertTrue( 253 Assert.assertTrue(
@@ -239,7 +256,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -239,7 +256,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
239 && clientInfo.getName().equals(secondGroupClientInfo.getName())) 256 && clientInfo.getName().equals(secondGroupClientInfo.getName()))
240 ); 257 );
241 }); 258 });
242 - List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain"); 259 + List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null);
243 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size()); 260 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size());
244 secondGroupClientInfos.forEach(secondGroupClientInfo -> { 261 secondGroupClientInfos.forEach(secondGroupClientInfo -> {
245 Assert.assertTrue( 262 Assert.assertTrue(
@@ -249,7 +266,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -249,7 +266,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
249 ); 266 );
250 }); 267 });
251 268
252 - List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain"); 269 + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null);
253 Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size()); 270 Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size());
254 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 271 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
255 Assert.assertTrue( 272 Assert.assertTrue(
@@ -266,7 +283,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -266,7 +283,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
266 ); 283 );
267 }); 284 });
268 285
269 - List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain"); 286 + List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null);
270 Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size()); 287 Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size());
271 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 288 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
272 Assert.assertTrue( 289 Assert.assertTrue(
@@ -286,34 +303,35 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -286,34 +303,35 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
286 303
287 @Test 304 @Test
288 public void testGetOAuth2ClientsForHttpAndHttps() { 305 public void testGetOAuth2ClientsForHttpAndHttps() {
289 - List<ClientRegistrationDto> firstGroup = Lists.newArrayList(  
290 - validClientRegistrationDto(),  
291 - validClientRegistrationDto(),  
292 - validClientRegistrationDto(),  
293 - validClientRegistrationDto() 306 + List<OAuth2RegistrationInfo> firstGroup = Lists.newArrayList(
  307 + validRegistrationInfo(),
  308 + validRegistrationInfo(),
  309 + validRegistrationInfo(),
  310 + validRegistrationInfo()
294 ); 311 );
295 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
296 - OAuth2ClientsDomainParams.builder() 312 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  313 + OAuth2ParamsInfo.builder()
297 .domainInfos(Lists.newArrayList( 314 .domainInfos(Lists.newArrayList(
298 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
299 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
300 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build() 315 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  316 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  317 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build()
301 )) 318 ))
  319 + .mobileInfos(Collections.emptyList())
302 .clientRegistrations(firstGroup) 320 .clientRegistrations(firstGroup)
303 .build() 321 .build()
304 )); 322 ));
305 323
306 - oAuth2Service.saveOAuth2Params(clientsParams);  
307 - OAuth2ClientsParams foundClientsParams = oAuth2Service.findOAuth2Params();  
308 - Assert.assertNotNull(foundClientsParams);  
309 - Assert.assertEquals(clientsParams, foundClientsParams); 324 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  325 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  326 + Assert.assertNotNull(foundOAuth2Info);
  327 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
310 328
311 List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream() 329 List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream()
312 - .map(clientRegistrationDto -> new OAuth2ClientInfo(  
313 - clientRegistrationDto.getLoginButtonLabel(), clientRegistrationDto.getLoginButtonIcon(), null)) 330 + .map(registrationInfo -> new OAuth2ClientInfo(
  331 + registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
314 .collect(Collectors.toList()); 332 .collect(Collectors.toList());
315 333
316 - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain"); 334 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null);
317 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); 335 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
318 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 336 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
319 Assert.assertTrue( 337 Assert.assertTrue(
@@ -323,7 +341,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -323,7 +341,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
323 ); 341 );
324 }); 342 });
325 343
326 - List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain"); 344 + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null);
327 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size()); 345 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size());
328 firstGroupClientInfos.forEach(firstGroupClientInfo -> { 346 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
329 Assert.assertTrue( 347 Assert.assertTrue(
@@ -336,166 +354,220 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { @@ -336,166 +354,220 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
336 354
337 @Test 355 @Test
338 public void testGetDisabledOAuth2Clients() { 356 public void testGetDisabledOAuth2Clients() {
339 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
340 - OAuth2ClientsDomainParams.builder() 357 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  358 + OAuth2ParamsInfo.builder()
341 .domainInfos(Lists.newArrayList( 359 .domainInfos(Lists.newArrayList(
342 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
343 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
344 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 360 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  361 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  362 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
345 )) 363 ))
346 .clientRegistrations(Lists.newArrayList( 364 .clientRegistrations(Lists.newArrayList(
347 - validClientRegistrationDto(),  
348 - validClientRegistrationDto(),  
349 - validClientRegistrationDto() 365 + validRegistrationInfo(),
  366 + validRegistrationInfo(),
  367 + validRegistrationInfo()
350 )) 368 ))
351 .build(), 369 .build(),
352 - OAuth2ClientsDomainParams.builder() 370 + OAuth2ParamsInfo.builder()
353 .domainInfos(Lists.newArrayList( 371 .domainInfos(Lists.newArrayList(
354 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),  
355 - DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() 372 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
  373 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
356 )) 374 ))
357 .clientRegistrations(Lists.newArrayList( 375 .clientRegistrations(Lists.newArrayList(
358 - validClientRegistrationDto(),  
359 - validClientRegistrationDto() 376 + validRegistrationInfo(),
  377 + validRegistrationInfo()
360 )) 378 ))
361 .build() 379 .build()
362 )); 380 ));
363 381
364 - oAuth2Service.saveOAuth2Params(clientsParams); 382 + oAuth2Service.saveOAuth2Info(oAuth2Info);
365 383
366 - List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain"); 384 + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null);
367 Assert.assertEquals(5, secondDomainHttpClients.size()); 385 Assert.assertEquals(5, secondDomainHttpClients.size());
368 386
369 - clientsParams.setEnabled(false);  
370 - oAuth2Service.saveOAuth2Params(clientsParams); 387 + oAuth2Info.setEnabled(false);
  388 + oAuth2Service.saveOAuth2Info(oAuth2Info);
371 389
372 - List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain"); 390 + List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null);
373 Assert.assertEquals(0, secondDomainHttpDisabledClients.size()); 391 Assert.assertEquals(0, secondDomainHttpDisabledClients.size());
374 } 392 }
375 393
376 @Test 394 @Test
377 - public void testFindAllClientRegistrationInfos() {  
378 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
379 - OAuth2ClientsDomainParams.builder() 395 + public void testFindAllRegistrations() {
  396 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  397 + OAuth2ParamsInfo.builder()
380 .domainInfos(Lists.newArrayList( 398 .domainInfos(Lists.newArrayList(
381 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
382 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
383 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 399 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  400 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  401 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
384 )) 402 ))
385 .clientRegistrations(Lists.newArrayList( 403 .clientRegistrations(Lists.newArrayList(
386 - validClientRegistrationDto(),  
387 - validClientRegistrationDto(),  
388 - validClientRegistrationDto() 404 + validRegistrationInfo(),
  405 + validRegistrationInfo(),
  406 + validRegistrationInfo()
389 )) 407 ))
390 .build(), 408 .build(),
391 - OAuth2ClientsDomainParams.builder() 409 + OAuth2ParamsInfo.builder()
392 .domainInfos(Lists.newArrayList( 410 .domainInfos(Lists.newArrayList(
393 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),  
394 - DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() 411 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
  412 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
395 )) 413 ))
396 .clientRegistrations(Lists.newArrayList( 414 .clientRegistrations(Lists.newArrayList(
397 - validClientRegistrationDto(),  
398 - validClientRegistrationDto() 415 + validRegistrationInfo(),
  416 + validRegistrationInfo()
399 )) 417 ))
400 .build(), 418 .build(),
401 - OAuth2ClientsDomainParams.builder() 419 + OAuth2ParamsInfo.builder()
402 .domainInfos(Lists.newArrayList( 420 .domainInfos(Lists.newArrayList(
403 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),  
404 - DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build() 421 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
  422 + OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
405 )) 423 ))
406 .clientRegistrations(Lists.newArrayList( 424 .clientRegistrations(Lists.newArrayList(
407 - validClientRegistrationDto() 425 + validRegistrationInfo()
408 )) 426 ))
409 .build() 427 .build()
410 )); 428 ));
411 429
412 - oAuth2Service.saveOAuth2Params(clientsParams);  
413 - List<OAuth2ClientRegistrationInfo> foundClientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos();  
414 - Assert.assertEquals(6, foundClientRegistrationInfos.size());  
415 - clientsParams.getDomainsParams().stream()  
416 - .flatMap(domainParams -> domainParams.getClientRegistrations().stream())  
417 - .forEach(clientRegistrationDto -> 430 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  431 + List<OAuth2Registration> foundRegistrations = oAuth2Service.findAllRegistrations();
  432 + Assert.assertEquals(6, foundRegistrations.size());
  433 + oAuth2Info.getOauth2ParamsInfos().stream()
  434 + .flatMap(paramsInfo -> paramsInfo.getClientRegistrations().stream())
  435 + .forEach(registrationInfo ->
418 Assert.assertTrue( 436 Assert.assertTrue(
419 - foundClientRegistrationInfos.stream()  
420 - .anyMatch(clientRegistrationInfo -> clientRegistrationInfo.getClientId().equals(clientRegistrationDto.getClientId())) 437 + foundRegistrations.stream()
  438 + .anyMatch(registration -> registration.getClientId().equals(registrationInfo.getClientId()))
421 ) 439 )
422 ); 440 );
423 } 441 }
424 442
425 @Test 443 @Test
426 - public void testFindClientRegistrationById() {  
427 - OAuth2ClientsParams clientsParams = new OAuth2ClientsParams(true, Lists.newArrayList(  
428 - OAuth2ClientsDomainParams.builder() 444 + public void testFindRegistrationById() {
  445 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  446 + OAuth2ParamsInfo.builder()
429 .domainInfos(Lists.newArrayList( 447 .domainInfos(Lists.newArrayList(
430 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
431 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
432 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 448 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  449 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  450 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
433 )) 451 ))
434 .clientRegistrations(Lists.newArrayList( 452 .clientRegistrations(Lists.newArrayList(
435 - validClientRegistrationDto(),  
436 - validClientRegistrationDto(),  
437 - validClientRegistrationDto() 453 + validRegistrationInfo(),
  454 + validRegistrationInfo(),
  455 + validRegistrationInfo()
438 )) 456 ))
439 .build(), 457 .build(),
440 - OAuth2ClientsDomainParams.builder() 458 + OAuth2ParamsInfo.builder()
441 .domainInfos(Lists.newArrayList( 459 .domainInfos(Lists.newArrayList(
442 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),  
443 - DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() 460 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
  461 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
444 )) 462 ))
445 .clientRegistrations(Lists.newArrayList( 463 .clientRegistrations(Lists.newArrayList(
446 - validClientRegistrationDto(),  
447 - validClientRegistrationDto() 464 + validRegistrationInfo(),
  465 + validRegistrationInfo()
448 )) 466 ))
449 .build(), 467 .build(),
450 - OAuth2ClientsDomainParams.builder() 468 + OAuth2ParamsInfo.builder()
451 .domainInfos(Lists.newArrayList( 469 .domainInfos(Lists.newArrayList(
452 - DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),  
453 - DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build() 470 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
  471 + OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
454 )) 472 ))
455 .clientRegistrations(Lists.newArrayList( 473 .clientRegistrations(Lists.newArrayList(
456 - validClientRegistrationDto() 474 + validRegistrationInfo()
457 )) 475 ))
458 .build() 476 .build()
459 )); 477 ));
460 478
461 - oAuth2Service.saveOAuth2Params(clientsParams);  
462 - List<OAuth2ClientRegistrationInfo> clientRegistrationInfos = oAuth2Service.findAllClientRegistrationInfos();  
463 - clientRegistrationInfos.forEach(clientRegistrationInfo -> {  
464 - OAuth2ClientRegistrationInfo foundClientRegistrationInfo = oAuth2Service.findClientRegistrationInfo(clientRegistrationInfo.getUuidId());  
465 - Assert.assertEquals(clientRegistrationInfo, foundClientRegistrationInfo); 479 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  480 + List<OAuth2Registration> foundRegistrations = oAuth2Service.findAllRegistrations();
  481 + foundRegistrations.forEach(registration -> {
  482 + OAuth2Registration foundRegistration = oAuth2Service.findRegistration(registration.getUuidId());
  483 + Assert.assertEquals(registration, foundRegistration);
466 }); 484 });
467 } 485 }
468 486
469 - private OAuth2ClientsParams createDefaultClientsParams() {  
470 - return new OAuth2ClientsParams(true, Lists.newArrayList(  
471 - OAuth2ClientsDomainParams.builder() 487 + @Test
  488 + public void testFindCallbackUrlScheme() {
  489 + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList(
  490 + OAuth2ParamsInfo.builder()
  491 + .domainInfos(Lists.newArrayList(
  492 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  493 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  494 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
  495 + ))
  496 + .mobileInfos(Lists.newArrayList(
  497 + OAuth2MobileInfo.builder().pkgName("com.test.pkg1").callbackUrlScheme("testPkg1Callback").build(),
  498 + OAuth2MobileInfo.builder().pkgName("com.test.pkg2").callbackUrlScheme("testPkg2Callback").build()
  499 + ))
  500 + .clientRegistrations(Lists.newArrayList(
  501 + validRegistrationInfo(),
  502 + validRegistrationInfo(),
  503 + validRegistrationInfo()
  504 + ))
  505 + .build(),
  506 + OAuth2ParamsInfo.builder()
  507 + .domainInfos(Lists.newArrayList(
  508 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
  509 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
  510 + ))
  511 + .mobileInfos(Collections.emptyList())
  512 + .clientRegistrations(Lists.newArrayList(
  513 + validRegistrationInfo(),
  514 + validRegistrationInfo()
  515 + ))
  516 + .build()
  517 + ));
  518 + oAuth2Service.saveOAuth2Info(oAuth2Info);
  519 +
  520 + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
  521 + Assert.assertEquals(oAuth2Info, foundOAuth2Info);
  522 +
  523 + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1");
  524 + Assert.assertEquals(3, firstDomainHttpClients.size());
  525 + for (OAuth2ClientInfo clientInfo : firstDomainHttpClients) {
  526 + String[] segments = clientInfo.getUrl().split("/");
  527 + String registrationId = segments[segments.length-1];
  528 + String callbackUrlScheme = oAuth2Service.findCallbackUrlScheme(UUID.fromString(registrationId), "com.test.pkg1");
  529 + Assert.assertNotNull(callbackUrlScheme);
  530 + Assert.assertEquals("testPkg1Callback", callbackUrlScheme);
  531 + callbackUrlScheme = oAuth2Service.findCallbackUrlScheme(UUID.fromString(registrationId), "com.test.pkg2");
  532 + Assert.assertNotNull(callbackUrlScheme);
  533 + Assert.assertEquals("testPkg2Callback", callbackUrlScheme);
  534 + callbackUrlScheme = oAuth2Service.findCallbackUrlScheme(UUID.fromString(registrationId), "com.test.pkg3");
  535 + Assert.assertNull(callbackUrlScheme);
  536 + }
  537 + }
  538 +
  539 + private OAuth2Info createDefaultOAuth2Info() {
  540 + return new OAuth2Info(true, Lists.newArrayList(
  541 + OAuth2ParamsInfo.builder()
472 .domainInfos(Lists.newArrayList( 542 .domainInfos(Lists.newArrayList(
473 - DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),  
474 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
475 - DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() 543 + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
  544 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  545 + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
476 )) 546 ))
  547 + .mobileInfos(Collections.emptyList())
477 .clientRegistrations(Lists.newArrayList( 548 .clientRegistrations(Lists.newArrayList(
478 - validClientRegistrationDto(),  
479 - validClientRegistrationDto(),  
480 - validClientRegistrationDto(),  
481 - validClientRegistrationDto() 549 + validRegistrationInfo(),
  550 + validRegistrationInfo(),
  551 + validRegistrationInfo(),
  552 + validRegistrationInfo()
482 )) 553 ))
483 .build(), 554 .build(),
484 - OAuth2ClientsDomainParams.builder() 555 + OAuth2ParamsInfo.builder()
485 .domainInfos(Lists.newArrayList( 556 .domainInfos(Lists.newArrayList(
486 - DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),  
487 - DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() 557 + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
  558 + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
488 )) 559 ))
  560 + .mobileInfos(Collections.emptyList())
489 .clientRegistrations(Lists.newArrayList( 561 .clientRegistrations(Lists.newArrayList(
490 - validClientRegistrationDto(),  
491 - validClientRegistrationDto() 562 + validRegistrationInfo(),
  563 + validRegistrationInfo()
492 )) 564 ))
493 .build() 565 .build()
494 )); 566 ));
495 } 567 }
496 568
497 - private ClientRegistrationDto validClientRegistrationDto() {  
498 - return ClientRegistrationDto.builder() 569 + private OAuth2RegistrationInfo validRegistrationInfo() {
  570 + return OAuth2RegistrationInfo.builder()
499 .clientId(UUID.randomUUID().toString()) 571 .clientId(UUID.randomUUID().toString())
500 .clientSecret(UUID.randomUUID().toString()) 572 .clientSecret(UUID.randomUUID().toString())
501 .authorizationUri(UUID.randomUUID().toString()) 573 .authorizationUri(UUID.randomUUID().toString())
@@ -24,9 +24,13 @@ DROP TABLE IF EXISTS dashboard; @@ -24,9 +24,13 @@ DROP TABLE IF EXISTS dashboard;
24 DROP TABLE IF EXISTS rule_node_state; 24 DROP TABLE IF EXISTS rule_node_state;
25 DROP TABLE IF EXISTS rule_node; 25 DROP TABLE IF EXISTS rule_node;
26 DROP TABLE IF EXISTS rule_chain; 26 DROP TABLE IF EXISTS rule_chain;
  27 +DROP TABLE IF EXISTS oauth2_mobile;
  28 +DROP TABLE IF EXISTS oauth2_domain;
  29 +DROP TABLE IF EXISTS oauth2_registration;
  30 +DROP TABLE IF EXISTS oauth2_params;
  31 +DROP TABLE IF EXISTS oauth2_client_registration_template;
27 DROP TABLE IF EXISTS oauth2_client_registration; 32 DROP TABLE IF EXISTS oauth2_client_registration;
28 DROP TABLE IF EXISTS oauth2_client_registration_info; 33 DROP TABLE IF EXISTS oauth2_client_registration_info;
29 -DROP TABLE IF EXISTS oauth2_client_registration_template;  
30 DROP TABLE IF EXISTS api_usage_state; 34 DROP TABLE IF EXISTS api_usage_state;
31 DROP TABLE IF EXISTS resource; 35 DROP TABLE IF EXISTS resource;
32 DROP TABLE IF EXISTS ota_package; 36 DROP TABLE IF EXISTS ota_package;
@@ -25,9 +25,13 @@ DROP TABLE IF EXISTS rule_node_state; @@ -25,9 +25,13 @@ DROP TABLE IF EXISTS rule_node_state;
25 DROP TABLE IF EXISTS rule_node; 25 DROP TABLE IF EXISTS rule_node;
26 DROP TABLE IF EXISTS rule_chain; 26 DROP TABLE IF EXISTS rule_chain;
27 DROP TABLE IF EXISTS tb_schema_settings; 27 DROP TABLE IF EXISTS tb_schema_settings;
  28 +DROP TABLE IF EXISTS oauth2_mobile;
  29 +DROP TABLE IF EXISTS oauth2_domain;
  30 +DROP TABLE IF EXISTS oauth2_registration;
  31 +DROP TABLE IF EXISTS oauth2_params;
  32 +DROP TABLE IF EXISTS oauth2_client_registration_template;
28 DROP TABLE IF EXISTS oauth2_client_registration; 33 DROP TABLE IF EXISTS oauth2_client_registration;
29 DROP TABLE IF EXISTS oauth2_client_registration_info; 34 DROP TABLE IF EXISTS oauth2_client_registration_info;
30 -DROP TABLE IF EXISTS oauth2_client_registration_template;  
31 DROP TABLE IF EXISTS api_usage_state; 35 DROP TABLE IF EXISTS api_usage_state;
32 DROP TABLE IF EXISTS resource; 36 DROP TABLE IF EXISTS resource;
33 DROP TABLE IF EXISTS firmware; 37 DROP TABLE IF EXISTS firmware;
@@ -103,7 +103,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; @@ -103,7 +103,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
103 import org.thingsboard.server.common.data.kv.TsKvEntry; 103 import org.thingsboard.server.common.data.kv.TsKvEntry;
104 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; 104 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
105 import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; 105 import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate;
106 -import org.thingsboard.server.common.data.oauth2.OAuth2ClientsParams; 106 +import org.thingsboard.server.common.data.oauth2.OAuth2Info;
107 import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; 107 import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
108 import org.thingsboard.server.common.data.ota.OtaPackageType; 108 import org.thingsboard.server.common.data.ota.OtaPackageType;
109 import org.thingsboard.server.common.data.page.PageData; 109 import org.thingsboard.server.common.data.page.PageData;
@@ -142,7 +142,6 @@ import java.util.HashMap; @@ -142,7 +142,6 @@ import java.util.HashMap;
142 import java.util.List; 142 import java.util.List;
143 import java.util.Map; 143 import java.util.Map;
144 import java.util.Optional; 144 import java.util.Optional;
145 -import java.util.UUID;  
146 import java.util.concurrent.ConcurrentHashMap; 145 import java.util.concurrent.ConcurrentHashMap;
147 import java.util.concurrent.ExecutorService; 146 import java.util.concurrent.ExecutorService;
148 import java.util.concurrent.Future; 147 import java.util.concurrent.Future;
@@ -1773,21 +1772,28 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1773,21 +1772,28 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1773 }).getBody(); 1772 }).getBody();
1774 } 1773 }
1775 1774
1776 - public List<OAuth2ClientInfo> getOAuth2Clients() { 1775 + public List<OAuth2ClientInfo> getOAuth2Clients(String pkgName) {
  1776 + Map<String, String> params = new HashMap<>();
  1777 + StringBuilder urlBuilder = new StringBuilder(baseURL);
  1778 + urlBuilder.append("/api/noauth/oauth2Clients");
  1779 + if (pkgName != null) {
  1780 + urlBuilder.append("?pkgName={pkgName}");
  1781 + params.put("pkgName", pkgName);
  1782 + }
1777 return restTemplate.exchange( 1783 return restTemplate.exchange(
1778 - baseURL + "/api/noauth/oauth2Clients", 1784 + urlBuilder.toString(),
1779 HttpMethod.POST, 1785 HttpMethod.POST,
1780 HttpEntity.EMPTY, 1786 HttpEntity.EMPTY,
1781 new ParameterizedTypeReference<List<OAuth2ClientInfo>>() { 1787 new ParameterizedTypeReference<List<OAuth2ClientInfo>>() {
1782 - }).getBody(); 1788 + }, params).getBody();
1783 } 1789 }
1784 1790
1785 - public OAuth2ClientsParams getCurrentOAuth2Params() {  
1786 - return restTemplate.getForEntity(baseURL + "/api/oauth2/config", OAuth2ClientsParams.class).getBody(); 1791 + public OAuth2Info getCurrentOAuth2Info() {
  1792 + return restTemplate.getForEntity(baseURL + "/api/oauth2/config", OAuth2Info.class).getBody();
1787 } 1793 }
1788 1794
1789 - public OAuth2ClientsParams saveOAuth2Params(OAuth2ClientsParams oauth2Params) {  
1790 - return restTemplate.postForEntity(baseURL + "/api/oauth2/config", oauth2Params, OAuth2ClientsParams.class).getBody(); 1795 + public OAuth2Info saveOAuth2Info(OAuth2Info oauth2Info) {
  1796 + return restTemplate.postForEntity(baseURL + "/api/oauth2/config", oauth2Info, OAuth2Info.class).getBody();
1791 } 1797 }
1792 1798
1793 public String getLoginProcessingUrl() { 1799 public String getLoginProcessingUrl() {
@@ -45,7 +45,7 @@ import { ActionNotificationShow } from '@core/notification/notification.actions' @@ -45,7 +45,7 @@ import { ActionNotificationShow } from '@core/notification/notification.actions'
45 import { MatDialog, MatDialogConfig } from '@angular/material/dialog'; 45 import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
46 import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component'; 46 import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component';
47 import { OAuth2ClientInfo } from '@shared/models/oauth2.models'; 47 import { OAuth2ClientInfo } from '@shared/models/oauth2.models';
48 -import { isMobileApp } from '@core/utils'; 48 +import { isDefinedAndNotNull, isMobileApp } from '@core/utils';
49 49
50 @Injectable({ 50 @Injectable({
51 providedIn: 'root' 51 providedIn: 'root'
@@ -204,8 +204,12 @@ export class AuthService { @@ -204,8 +204,12 @@ export class AuthService {
204 } 204 }
205 } 205 }
206 206
207 - public loadOAuth2Clients(): Observable<Array<OAuth2ClientInfo>> {  
208 - return this.http.post<Array<OAuth2ClientInfo>>(`/api/noauth/oauth2Clients`, 207 + public loadOAuth2Clients(pkgName?: string): Observable<Array<OAuth2ClientInfo>> {
  208 + let url = '/api/noauth/oauth2Clients';
  209 + if (isDefinedAndNotNull(pkgName)) {
  210 + url += `?pkgName=${pkgName}`;
  211 + }
  212 + return this.http.post<Array<OAuth2ClientInfo>>(url,
209 null, defaultHttpOptions()).pipe( 213 null, defaultHttpOptions()).pipe(
210 catchError(err => of([])), 214 catchError(err => of([])),
211 tap((OAuth2Clients) => { 215 tap((OAuth2Clients) => {
@@ -18,7 +18,7 @@ import { Injectable } from '@angular/core'; @@ -18,7 +18,7 @@ import { Injectable } from '@angular/core';
18 import { HttpClient } from '@angular/common/http'; 18 import { HttpClient } from '@angular/common/http';
19 import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils'; 19 import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
20 import { Observable } from 'rxjs'; 20 import { Observable } from 'rxjs';
21 -import { OAuth2ClientRegistrationTemplate, OAuth2ClientsParams } from '@shared/models/oauth2.models'; 21 +import { OAuth2ClientRegistrationTemplate, OAuth2Info } from '@shared/models/oauth2.models';
22 22
23 @Injectable({ 23 @Injectable({
24 providedIn: 'root' 24 providedIn: 'root'
@@ -29,16 +29,16 @@ export class OAuth2Service { @@ -29,16 +29,16 @@ export class OAuth2Service {
29 private http: HttpClient 29 private http: HttpClient
30 ) { } 30 ) { }
31 31
32 - public getOAuth2Settings(config?: RequestConfig): Observable<OAuth2ClientsParams> {  
33 - return this.http.get<OAuth2ClientsParams>(`/api/oauth2/config`, defaultHttpOptionsFromConfig(config)); 32 + public getOAuth2Settings(config?: RequestConfig): Observable<OAuth2Info> {
  33 + return this.http.get<OAuth2Info>(`/api/oauth2/config`, defaultHttpOptionsFromConfig(config));
34 } 34 }
35 35
36 public getOAuth2Template(config?: RequestConfig): Observable<Array<OAuth2ClientRegistrationTemplate>> { 36 public getOAuth2Template(config?: RequestConfig): Observable<Array<OAuth2ClientRegistrationTemplate>> {
37 return this.http.get<Array<OAuth2ClientRegistrationTemplate>>(`/api/oauth2/config/template`, defaultHttpOptionsFromConfig(config)); 37 return this.http.get<Array<OAuth2ClientRegistrationTemplate>>(`/api/oauth2/config/template`, defaultHttpOptionsFromConfig(config));
38 } 38 }
39 39
40 - public saveOAuth2Settings(OAuth2Setting: OAuth2ClientsParams, config?: RequestConfig): Observable<OAuth2ClientsParams> {  
41 - return this.http.post<OAuth2ClientsParams>('/api/oauth2/config', OAuth2Setting, 40 + public saveOAuth2Settings(OAuth2Setting: OAuth2Info, config?: RequestConfig): Observable<OAuth2Info> {
  41 + return this.http.post<OAuth2Info>('/api/oauth2/config', OAuth2Setting,
42 defaultHttpOptionsFromConfig(config)); 42 defaultHttpOptionsFromConfig(config));
43 } 43 }
44 44
@@ -34,19 +34,19 @@ @@ -34,19 +34,19 @@
34 {{ 'admin.oauth2.enable' | translate }} 34 {{ 'admin.oauth2.enable' | translate }}
35 </mat-checkbox> 35 </mat-checkbox>
36 <section *ngIf="oauth2SettingsForm.get('enabled').value" style="margin-top: 1em;"> 36 <section *ngIf="oauth2SettingsForm.get('enabled').value" style="margin-top: 1em;">
37 - <ng-container formArrayName="domainsParams"> 37 + <ng-container formArrayName="oauth2ParamsInfos">
38 <div class="container"> 38 <div class="container">
39 <mat-accordion multi> 39 <mat-accordion multi>
40 - <ng-container *ngFor="let domain of domainsParams.controls; let i = index; trackBy: trackByParams"> 40 + <ng-container *ngFor="let oauth2ParamsInfo of oauth2ParamsInfos.controls; let i = index; trackBy: trackByParams">
41 <mat-expansion-panel [formGroupName]="i"> 41 <mat-expansion-panel [formGroupName]="i">
42 <mat-expansion-panel-header> 42 <mat-expansion-panel-header>
43 <mat-panel-title fxLayoutAlign="start center"> 43 <mat-panel-title fxLayoutAlign="start center">
44 - {{ domainListTittle(domain) }} 44 + {{ domainListTittle(oauth2ParamsInfo) }}
45 </mat-panel-title> 45 </mat-panel-title>
46 <mat-panel-description fxLayoutAlign="end center"> 46 <mat-panel-description fxLayoutAlign="end center">
47 <button mat-icon-button 47 <button mat-icon-button
48 type="button" 48 type="button"
49 - (click)="deleteDomain($event, i)" 49 + (click)="deleteOAuth2ParamsInfo($event, i)"
50 matTooltip="{{ 'action.delete' | translate }}" 50 matTooltip="{{ 'action.delete' | translate }}"
51 matTooltipPosition="above"> 51 matTooltipPosition="above">
52 <mat-icon>delete</mat-icon> 52 <mat-icon>delete</mat-icon>
@@ -55,83 +55,133 @@ @@ -55,83 +55,133 @@
55 </mat-expansion-panel-header> 55 </mat-expansion-panel-header>
56 56
57 <ng-template matExpansionPanelContent> 57 <ng-template matExpansionPanelContent>
58 - <ng-container formArrayName="domainInfos">  
59 - <section *ngFor="let domainInfo of clientDomainInfos(domain).controls; let n = index; trackBy: trackByParams"  
60 - class="domains-list">  
61 - <div [formGroupName]="n" fxLayout="row" fxLayoutGap="8px">  
62 - <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px">  
63 - <div fxLayout="column" fxFlex.sm="60" fxFlex.gt-sm="50">  
64 - <div fxLayout="row" fxLayout.xs="column" fxLayout.md="column" fxLayoutGap="8px" fxLayoutGap.md="0px">  
65 - <mat-form-field fxFlex="30" fxFlex.md fxFlex.xs class="mat-block">  
66 - <mat-label translate>admin.oauth2.protocol</mat-label>  
67 - <mat-select formControlName="scheme">  
68 - <mat-option *ngFor="let protocol of protocols" [value]="protocol">  
69 - {{ domainSchemaTranslations.get(protocol) | translate | uppercase }}  
70 - </mat-option>  
71 - </mat-select>  
72 - </mat-form-field>  
73 - <mat-form-field fxFlex class="mat-block">  
74 - <mat-label translate>admin.domain-name</mat-label>  
75 - <input matInput formControlName="name" required>  
76 - <mat-error *ngIf="domainInfo.get('name').hasError('pattern')">  
77 - {{ 'admin.error-verification-url' | translate }} 58 + <mat-tab-group dynamicHeight>
  59 + <mat-tab label="{{ 'admin.oauth2.domains' | translate }}">
  60 + <ng-container formArrayName="domainInfos">
  61 + <div style="padding-top: 16px;"></div>
  62 + <section *ngFor="let domainInfo of domainInfos(oauth2ParamsInfo).controls; let n = index; trackBy: trackByParams"
  63 + class="domains-list">
  64 + <div [formGroupName]="n" fxLayout="row" fxLayoutGap="8px">
  65 + <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px">
  66 + <div fxLayout="column" fxFlex.sm="60" fxFlex.gt-sm="50">
  67 + <div fxLayout="row" fxLayout.xs="column" fxLayout.md="column" fxLayoutGap="8px" fxLayoutGap.md="0px">
  68 + <mat-form-field fxFlex="30" fxFlex.md fxFlex.xs class="mat-block">
  69 + <mat-label translate>admin.oauth2.protocol</mat-label>
  70 + <mat-select formControlName="scheme">
  71 + <mat-option *ngFor="let protocol of protocols" [value]="protocol">
  72 + {{ domainSchemaTranslations.get(protocol) | translate | uppercase }}
  73 + </mat-option>
  74 + </mat-select>
  75 + </mat-form-field>
  76 + <mat-form-field fxFlex class="mat-block">
  77 + <mat-label translate>admin.domain-name</mat-label>
  78 + <input matInput formControlName="name" required>
  79 + <mat-error *ngIf="domainInfo.get('name').hasError('pattern')">
  80 + {{ 'admin.error-verification-url' | translate }}
  81 + </mat-error>
  82 + </mat-form-field>
  83 + </div>
  84 + <mat-error *ngIf="domainInfo.hasError('unique')">
  85 + {{ 'admin.domain-name-unique' | translate }}
78 </mat-error> 86 </mat-error>
79 - </mat-form-field> 87 + </div>
  88 +
  89 + <div fxFlex fxLayout="column">
  90 + <mat-form-field fxFlex class="mat-block">
  91 + <mat-label translate>admin.oauth2.redirect-uri-template</mat-label>
  92 + <input matInput [value]="redirectURI(domainInfo)" readonly>
  93 + <button mat-icon-button color="primary" matSuffix type="button"
  94 + ngxClipboard cbContent="{{ redirectURI(domainInfo) }}"
  95 + matTooltip="{{ 'admin.oauth2.copy-redirect-uri' | translate }}"
  96 + matTooltipPosition="above">
  97 + <mat-icon class="material-icons" svgIcon="mdi:clipboard-arrow-left"></mat-icon>
  98 + </button>
  99 + </mat-form-field>
  100 +
  101 + <mat-form-field fxFlex *ngIf="domainInfo.get('scheme').value === 'MIXED'" class="mat-block">
  102 + <mat-label></mat-label>
  103 + <input matInput [value]="redirectURIMixed(domainInfo)" readonly>
  104 + <button mat-icon-button color="primary" matSuffix type="button"
  105 + ngxClipboard cbContent="{{ redirectURIMixed(domainInfo) }}"
  106 + matTooltip="{{ 'admin.oauth2.copy-redirect-uri' | translate }}"
  107 + matTooltipPosition="above">
  108 + <mat-icon class="material-icons" svgIcon="mdi:clipboard-arrow-left"></mat-icon>
  109 + </button>
  110 + </mat-form-field>
  111 + </div>
80 </div> 112 </div>
81 - <mat-error *ngIf="domainInfo.hasError('unique')">  
82 - {{ 'admin.domain-name-unique' | translate }}  
83 - </mat-error>  
84 - </div>  
85 113
86 - <div fxFlex fxLayout="column">  
87 - <mat-form-field fxFlex class="mat-block">  
88 - <mat-label translate>admin.oauth2.redirect-uri-template</mat-label>  
89 - <input matInput [value]="redirectURI(domainInfo)" readonly>  
90 - <button mat-icon-button color="primary" matSuffix type="button"  
91 - ngxClipboard cbContent="{{ redirectURI(domainInfo) }}"  
92 - matTooltip="{{ 'admin.oauth2.copy-redirect-uri' | translate }}" 114 + <div fxLayout="column" fxLayoutAlign="center start">
  115 + <button type="button" mat-icon-button color="primary"
  116 + (click)="removeDomainInfo($event, oauth2ParamsInfo, n)"
  117 + [disabled]="domainInfos(oauth2ParamsInfo).controls.length < 2"
  118 + matTooltip="{{ 'admin.oauth2.delete-domain' | translate }}"
93 matTooltipPosition="above"> 119 matTooltipPosition="above">
94 - <mat-icon class="material-icons" svgIcon="mdi:clipboard-arrow-left"></mat-icon> 120 + <mat-icon>close</mat-icon>
95 </button> 121 </button>
96 - </mat-form-field>  
97 -  
98 - <mat-form-field fxFlex *ngIf="domainInfo.get('scheme').value === 'MIXED'" class="mat-block">  
99 - <mat-label></mat-label>  
100 - <input matInput [value]="redirectURIMixed(domainInfo)" readonly>  
101 - <button mat-icon-button color="primary" matSuffix type="button"  
102 - ngxClipboard cbContent="{{ redirectURIMixed(domainInfo) }}"  
103 - matTooltip="{{ 'admin.oauth2.copy-redirect-uri' | translate }}" 122 + </div>
  123 + </div>
  124 + </section>
  125 + <div fxLayout="row" fxLayoutAlign="end center" style="margin-bottom: 1.25em">
  126 + <button mat-button mat-raised-button color="primary"
  127 + [disabled]="(isLoading$ | async)"
  128 + (click)="addDomainInfo(oauth2ParamsInfo)"
  129 + type="button">
  130 + {{'admin.oauth2.add-domain' | translate}}
  131 + </button>
  132 + </div>
  133 + </ng-container>
  134 + </mat-tab>
  135 + <mat-tab label="{{ 'admin.oauth2.mobile-apps' | translate }}">
  136 + <ng-container formArrayName="mobileInfos">
  137 + <div style="padding-top: 16px;"></div>
  138 + <div *ngIf="mobileInfos(oauth2ParamsInfo).length === 0">
  139 + <span fxLayoutAlign="center center"
  140 + class="tb-prompt" translate>admin.oauth2.no-mobile-apps</span>
  141 + </div>
  142 + <section *ngFor="let mobileInfo of mobileInfos(oauth2ParamsInfo).controls; let n = index; trackBy: trackByParams"
  143 + class="apps-list">
  144 + <div [formGroupName]="n" fxLayout="row" fxLayoutGap="8px">
  145 + <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px">
  146 + <div fxFlex fxLayout="column">
  147 + <mat-form-field fxFlex class="mat-block">
  148 + <mat-label translate>admin.oauth2.mobile-package</mat-label>
  149 + <input matInput formControlName="pkgName" required>
  150 + </mat-form-field>
  151 + <mat-error *ngIf="mobileInfo.hasError('unique')">
  152 + {{ 'admin.oauth2.mobile-package-unique' | translate }}
  153 + </mat-error>
  154 + </div>
  155 + <mat-form-field fxFlex class="mat-block">
  156 + <mat-label translate>admin.oauth2.mobile-callback-url-scheme</mat-label>
  157 + <input matInput formControlName="callbackUrlScheme" required>
  158 + </mat-form-field>
  159 + </div>
  160 + <div fxLayout="column" fxLayoutAlign="center start">
  161 + <button type="button" mat-icon-button color="primary"
  162 + (click)="removeMobileInfo($event, oauth2ParamsInfo, n)"
  163 + matTooltip="{{ 'admin.oauth2.delete-mobile-app' | translate }}"
104 matTooltipPosition="above"> 164 matTooltipPosition="above">
105 - <mat-icon class="material-icons" svgIcon="mdi:clipboard-arrow-left"></mat-icon> 165 + <mat-icon>close</mat-icon>
106 </button> 166 </button>
107 - </mat-form-field> 167 + </div>
108 </div> 168 </div>
109 - </div>  
110 -  
111 - <div fxLayout="column" fxLayoutAlign="center start">  
112 - <button type="button" mat-icon-button color="primary"  
113 - (click)="removeDomain($event, domain, n)"  
114 - [disabled]="clientDomainInfos(domain).controls.length < 2"  
115 - matTooltip="{{ 'admin.oauth2.delete-domain' | translate }}"  
116 - matTooltipPosition="above">  
117 - <mat-icon>close</mat-icon> 169 + </section>
  170 + <div fxLayout="row" fxLayoutAlign="end center" style="margin-bottom: 1.25em">
  171 + <button mat-button mat-raised-button color="primary"
  172 + [disabled]="(isLoading$ | async)"
  173 + (click)="addMobileInfo(oauth2ParamsInfo)"
  174 + type="button">
  175 + {{'admin.oauth2.add-mobile-app' | translate}}
118 </button> 176 </button>
119 </div> 177 </div>
120 - </div>  
121 - </section>  
122 - <div fxLayout="row" fxLayoutAlign="end center" style="margin-bottom: 1.25em">  
123 - <button mat-button mat-raised-button color="primary"  
124 - [disabled]="(isLoading$ | async)"  
125 - (click)="addDomainInfo(domain)"  
126 - type="button">  
127 - {{'admin.oauth2.add-domain' | translate}}  
128 - </button>  
129 - </div>  
130 - </ng-container>  
131 - 178 + </ng-container>
  179 + </mat-tab>
  180 + </mat-tab-group>
  181 + <div class="mat-h3" translate>admin.oauth2.providers</div>
132 <ng-container formArrayName="clientRegistrations"> 182 <ng-container formArrayName="clientRegistrations">
133 <div class="container"> 183 <div class="container">
134 - <mat-expansion-panel *ngFor="let registration of clientDomainProviders(domain).controls; let j = index; trackBy: trackByParams" 184 + <mat-expansion-panel *ngFor="let registration of clientRegistrations(oauth2ParamsInfo).controls; let j = index; trackBy: trackByParams"
135 class="registration-card mat-elevation-z0"> 185 class="registration-card mat-elevation-z0">
136 <mat-expansion-panel-header> 186 <mat-expansion-panel-header>
137 <mat-panel-title fxLayoutAlign="start center"> 187 <mat-panel-title fxLayoutAlign="start center">
@@ -140,8 +190,8 @@ @@ -140,8 +190,8 @@
140 <mat-panel-description fxLayoutAlign="end center"> 190 <mat-panel-description fxLayoutAlign="end center">
141 <button mat-icon-button 191 <button mat-icon-button
142 type="button" 192 type="button"
143 - [disabled]="clientDomainProviders(domain).controls.length < 2"  
144 - (click)="deleteProvider($event, domain, j)" 193 + [disabled]="clientRegistrations(oauth2ParamsInfo).controls.length < 2"
  194 + (click)="deleteRegistration($event, oauth2ParamsInfo, j)"
145 matTooltip="{{ 'admin.oauth2.delete-provider' | translate }}" 195 matTooltip="{{ 'admin.oauth2.delete-provider' | translate }}"
146 matTooltipPosition="above"> 196 matTooltipPosition="above">
147 <mat-icon>delete</mat-icon> 197 <mat-icon>delete</mat-icon>
@@ -449,7 +499,7 @@ @@ -449,7 +499,7 @@
449 <div fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="8px"> 499 <div fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="8px">
450 <button mat-button mat-raised-button color="primary" 500 <button mat-button mat-raised-button color="primary"
451 [disabled]="(isLoading$ | async)" 501 [disabled]="(isLoading$ | async)"
452 - (click)="addProvider(domain)" 502 + (click)="addRegistration(oauth2ParamsInfo)"
453 type="button"> 503 type="button">
454 {{'admin.oauth2.add-provider' | translate}} 504 {{'admin.oauth2.add-provider' | translate}}
455 </button> 505 </button>
@@ -467,7 +517,7 @@ @@ -467,7 +517,7 @@
467 <button type="button" mat-raised-button color="primary" 517 <button type="button" mat-raised-button color="primary"
468 [disabled]="isLoading$ | async" 518 [disabled]="isLoading$ | async"
469 *ngIf="oauth2SettingsForm.get('enabled').value" 519 *ngIf="oauth2SettingsForm.get('enabled').value"
470 - (click)="addDomain()"> 520 + (click)="addOAuth2ParamsInfo()">
471 <mat-icon>add</mat-icon> 521 <mat-icon>add</mat-icon>
472 <span translate>action.add</span> 522 <span translate>action.add</span>
473 </button> 523 </button>
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 } 62 }
63 } 63 }
64 } 64 }
65 - .domains-list{ 65 + .domains-list, .apps-list {
66 margin-bottom: 1.5em; 66 margin-bottom: 1.5em;
67 .mat-form-field-suffix .mat-icon-button .mat-icon{ 67 .mat-form-field-suffix .mat-icon-button .mat-icon{
68 font-size: 24px; 68 font-size: 24px;
@@ -18,8 +18,6 @@ import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; @@ -18,8 +18,6 @@ import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
18 import { AbstractControl, FormArray, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms'; 18 import { AbstractControl, FormArray, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms';
19 import { 19 import {
20 ClientAuthenticationMethod, 20 ClientAuthenticationMethod,
21 - ClientRegistration,  
22 - DomainInfo,  
23 DomainSchema, 21 DomainSchema,
24 domainSchemaTranslations, 22 domainSchemaTranslations,
25 MapperConfig, 23 MapperConfig,
@@ -27,8 +25,10 @@ import { @@ -27,8 +25,10 @@ import {
27 MapperConfigCustom, 25 MapperConfigCustom,
28 MapperConfigType, 26 MapperConfigType,
29 OAuth2ClientRegistrationTemplate, 27 OAuth2ClientRegistrationTemplate,
30 - OAuth2ClientsDomainParams,  
31 - OAuth2ClientsParams, 28 + OAuth2DomainInfo,
  29 + OAuth2Info, OAuth2MobileInfo,
  30 + OAuth2ParamsInfo,
  31 + OAuth2RegistrationInfo,
32 TenantNameStrategy 32 TenantNameStrategy
33 } from '@shared/models/oauth2.models'; 33 } from '@shared/models/oauth2.models';
34 import { Store } from '@ngrx/store'; 34 import { Store } from '@ngrx/store';
@@ -52,6 +52,20 @@ import { ActivatedRoute } from '@angular/router'; @@ -52,6 +52,20 @@ import { ActivatedRoute } from '@angular/router';
52 }) 52 })
53 export class OAuth2SettingsComponent extends PageComponent implements OnInit, HasConfirmForm, OnDestroy { 53 export class OAuth2SettingsComponent extends PageComponent implements OnInit, HasConfirmForm, OnDestroy {
54 54
  55 + constructor(protected store: Store<AppState>,
  56 + private route: ActivatedRoute,
  57 + private oauth2Service: OAuth2Service,
  58 + private fb: FormBuilder,
  59 + private dialogService: DialogService,
  60 + private translate: TranslateService,
  61 + @Inject(WINDOW) private window: Window) {
  62 + super(store);
  63 + }
  64 +
  65 + get oauth2ParamsInfos(): FormArray {
  66 + return this.oauth2SettingsForm.get('oauth2ParamsInfos') as FormArray;
  67 + }
  68 +
55 private URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.,?+=&%@\-/]*)?$/; 69 private URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.,?+=&%@\-/]*)?$/;
56 private DOMAIN_AND_PORT_REGEXP = /^(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?$/; 70 private DOMAIN_AND_PORT_REGEXP = /^(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?$/;
57 private subscriptions: Subscription[] = []; 71 private subscriptions: Subscription[] = [];
@@ -77,7 +91,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -77,7 +91,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
77 readonly separatorKeysCodes: number[] = [ENTER, COMMA]; 91 readonly separatorKeysCodes: number[] = [ENTER, COMMA];
78 92
79 oauth2SettingsForm: FormGroup; 93 oauth2SettingsForm: FormGroup;
80 - auth2ClientsParams: OAuth2ClientsParams; 94 + oauth2Info: OAuth2Info;
81 95
82 clientAuthenticationMethods = Object.keys(ClientAuthenticationMethod); 96 clientAuthenticationMethods = Object.keys(ClientAuthenticationMethod);
83 mapperConfigType = MapperConfigType; 97 mapperConfigType = MapperConfigType;
@@ -90,14 +104,14 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -90,14 +104,14 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
90 104
91 private loginProcessingUrl: string = this.route.snapshot.data.loginProcessingUrl; 105 private loginProcessingUrl: string = this.route.snapshot.data.loginProcessingUrl;
92 106
93 - constructor(protected store: Store<AppState>,  
94 - private route: ActivatedRoute,  
95 - private oauth2Service: OAuth2Service,  
96 - private fb: FormBuilder,  
97 - private dialogService: DialogService,  
98 - private translate: TranslateService,  
99 - @Inject(WINDOW) private window: Window) {  
100 - super(store); 107 + private static validateScope(control: AbstractControl): ValidationErrors | null {
  108 + const scope: string[] = control.value;
  109 + if (!scope || !scope.length) {
  110 + return {
  111 + required: true
  112 + };
  113 + }
  114 + return null;
101 } 115 }
102 116
103 ngOnInit(): void { 117 ngOnInit(): void {
@@ -106,10 +120,10 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -106,10 +120,10 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
106 this.oauth2Service.getOAuth2Template(), 120 this.oauth2Service.getOAuth2Template(),
107 this.oauth2Service.getOAuth2Settings() 121 this.oauth2Service.getOAuth2Settings()
108 ]).subscribe( 122 ]).subscribe(
109 - ([templates, auth2ClientsParams]) => { 123 + ([templates, oauth2Info]) => {
110 this.initTemplates(templates); 124 this.initTemplates(templates);
111 - this.auth2ClientsParams = auth2ClientsParams;  
112 - this.initOAuth2Settings(this.auth2ClientsParams); 125 + this.oauth2Info = oauth2Info;
  126 + this.initOAuth2Settings(this.oauth2Info);
113 } 127 }
114 ); 128 );
115 } 129 }
@@ -130,11 +144,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -130,11 +144,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
130 this.templateProvider.sort(); 144 this.templateProvider.sort();
131 } 145 }
132 146
133 - get domainsParams(): FormArray {  
134 - return this.oauth2SettingsForm.get('domainsParams') as FormArray;  
135 - }  
136 -  
137 - private formBasicGroup(type: MapperConfigType, mapperConfigBasic?: MapperConfigBasic): FormGroup { 147 + private formBasicGroup(mapperConfigBasic?: MapperConfigBasic): FormGroup {
138 let tenantNamePattern; 148 let tenantNamePattern;
139 if (mapperConfigBasic?.tenantNamePattern) { 149 if (mapperConfigBasic?.tenantNamePattern) {
140 tenantNamePattern = mapperConfigBasic.tenantNamePattern; 150 tenantNamePattern = mapperConfigBasic.tenantNamePattern;
@@ -173,16 +183,16 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -173,16 +183,16 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
173 183
174 private buildOAuth2SettingsForm(): void { 184 private buildOAuth2SettingsForm(): void {
175 this.oauth2SettingsForm = this.fb.group({ 185 this.oauth2SettingsForm = this.fb.group({
176 - domainsParams: this.fb.array([]), 186 + oauth2ParamsInfos: this.fb.array([]),
177 enabled: [false] 187 enabled: [false]
178 }); 188 });
179 } 189 }
180 190
181 - private initOAuth2Settings(auth2ClientsParams: OAuth2ClientsParams): void {  
182 - if (auth2ClientsParams) {  
183 - this.oauth2SettingsForm.patchValue({enabled: auth2ClientsParams.enabled}, {emitEvent: false});  
184 - auth2ClientsParams.domainsParams.forEach((domain) => {  
185 - this.domainsParams.push(this.buildDomainsForm(domain)); 191 + private initOAuth2Settings(oauth2Info: OAuth2Info): void {
  192 + if (oauth2Info) {
  193 + this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled}, {emitEvent: false});
  194 + oauth2Info.oauth2ParamsInfos.forEach((oauth2ParamsInfo) => {
  195 + this.oauth2ParamsInfos.push(this.buildOAuth2ParamsInfoForm(oauth2ParamsInfo));
186 }); 196 });
187 } 197 }
188 } 198 }
@@ -201,8 +211,20 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -201,8 +211,20 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
201 return null; 211 return null;
202 } 212 }
203 213
  214 + private uniquePkgNameValidator(control: FormGroup): { [key: string]: boolean } | null {
  215 + if (control.parent?.value) {
  216 + const pkgName = control.value.pkgName;
  217 + const mobileInfosList = control.parent.getRawValue()
  218 + .filter((mobileInfo) => mobileInfo.pkgName === pkgName);
  219 + if (mobileInfosList.length > 1) {
  220 + return {unique: true};
  221 + }
  222 + }
  223 + return null;
  224 + }
  225 +
204 public domainListTittle(control: AbstractControl): string { 226 public domainListTittle(control: AbstractControl): string {
205 - const domainInfos = control.get('domainInfos').value as DomainInfo[]; 227 + const domainInfos = control.get('domainInfos').value as OAuth2DomainInfo[];
206 if (domainInfos.length) { 228 if (domainInfos.length) {
207 const domainList = new Set<string>(); 229 const domainList = new Set<string>();
208 domainInfos.forEach((domain) => { 230 domainInfos.forEach((domain) => {
@@ -213,41 +235,51 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -213,41 +235,51 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
213 return this.translate.instant('admin.oauth2.new-domain'); 235 return this.translate.instant('admin.oauth2.new-domain');
214 } 236 }
215 237
216 - private buildDomainsForm(auth2ClientsDomainParams?: OAuth2ClientsDomainParams): FormGroup {  
217 - const formDomain = this.fb.group({ 238 + private buildOAuth2ParamsInfoForm(oauth2ParamsInfo?: OAuth2ParamsInfo): FormGroup {
  239 + const formOAuth2Params = this.fb.group({
218 domainInfos: this.fb.array([], Validators.required), 240 domainInfos: this.fb.array([], Validators.required),
  241 + mobileInfos: this.fb.array([]),
219 clientRegistrations: this.fb.array([], Validators.required) 242 clientRegistrations: this.fb.array([], Validators.required)
220 }); 243 });
221 244
222 - if (auth2ClientsDomainParams) {  
223 - auth2ClientsDomainParams.domainInfos.forEach((domain) => {  
224 - this.clientDomainInfos(formDomain).push(this.buildDomainForm(domain)); 245 + if (oauth2ParamsInfo) {
  246 + oauth2ParamsInfo.domainInfos.forEach((domain) => {
  247 + this.domainInfos(formOAuth2Params).push(this.buildDomainInfoForm(domain));
  248 + });
  249 + oauth2ParamsInfo.mobileInfos.forEach((mobile) => {
  250 + this.mobileInfos(formOAuth2Params).push(this.buildMobileInfoForm(mobile));
225 }); 251 });
226 - auth2ClientsDomainParams.clientRegistrations.forEach((registration) => {  
227 - this.clientDomainProviders(formDomain).push(this.buildProviderForm(registration)); 252 + oauth2ParamsInfo.clientRegistrations.forEach((registration) => {
  253 + this.clientRegistrations(formOAuth2Params).push(this.buildRegistrationForm(registration));
228 }); 254 });
229 } else { 255 } else {
230 - this.clientDomainProviders(formDomain).push(this.buildProviderForm());  
231 - this.clientDomainInfos(formDomain).push(this.buildDomainForm()); 256 + this.clientRegistrations(formOAuth2Params).push(this.buildRegistrationForm());
  257 + this.domainInfos(formOAuth2Params).push(this.buildDomainInfoForm());
232 } 258 }
233 259
234 - return formDomain; 260 + return formOAuth2Params;
235 } 261 }
236 262
237 - private buildDomainForm(domainInfo?: DomainInfo): FormGroup {  
238 - const domain = this.fb.group({ 263 + private buildDomainInfoForm(domainInfo?: OAuth2DomainInfo): FormGroup {
  264 + return this.fb.group({
239 name: [domainInfo ? domainInfo.name : this.window.location.hostname, [ 265 name: [domainInfo ? domainInfo.name : this.window.location.hostname, [
240 Validators.required, 266 Validators.required,
241 Validators.pattern(this.DOMAIN_AND_PORT_REGEXP)]], 267 Validators.pattern(this.DOMAIN_AND_PORT_REGEXP)]],
242 scheme: [domainInfo?.scheme ? domainInfo.scheme : DomainSchema.HTTPS, Validators.required] 268 scheme: [domainInfo?.scheme ? domainInfo.scheme : DomainSchema.HTTPS, Validators.required]
243 }, {validators: this.uniqueDomainValidator}); 269 }, {validators: this.uniqueDomainValidator});
244 - return domain;  
245 } 270 }
246 271
247 - private buildProviderForm(clientRegistration?: ClientRegistration): FormGroup { 272 + private buildMobileInfoForm(mobileInfo?: OAuth2MobileInfo): FormGroup {
  273 + return this.fb.group({
  274 + pkgName: [mobileInfo?.pkgName, [Validators.required]],
  275 + callbackUrlScheme: [mobileInfo?.callbackUrlScheme, [Validators.required]],
  276 + }, {validators: this.uniquePkgNameValidator});
  277 + }
  278 +
  279 + private buildRegistrationForm(registration?: OAuth2RegistrationInfo): FormGroup {
248 let additionalInfo = null; 280 let additionalInfo = null;
249 - if (isDefinedAndNotNull(clientRegistration?.additionalInfo)) {  
250 - additionalInfo = clientRegistration.additionalInfo; 281 + if (isDefinedAndNotNull(registration?.additionalInfo)) {
  282 + additionalInfo = registration.additionalInfo;
251 if (this.templateProvider.indexOf(additionalInfo.providerName) === -1) { 283 if (this.templateProvider.indexOf(additionalInfo.providerName) === -1) {
252 additionalInfo.providerName = 'Custom'; 284 additionalInfo.providerName = 'Custom';
253 } 285 }
@@ -261,43 +293,43 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -261,43 +293,43 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
261 additionalInfo: this.fb.group({ 293 additionalInfo: this.fb.group({
262 providerName: [additionalInfo?.providerName ? additionalInfo?.providerName : defaultProviderName, Validators.required] 294 providerName: [additionalInfo?.providerName ? additionalInfo?.providerName : defaultProviderName, Validators.required]
263 }), 295 }),
264 - loginButtonLabel: [clientRegistration?.loginButtonLabel ? clientRegistration.loginButtonLabel : null, Validators.required],  
265 - loginButtonIcon: [clientRegistration?.loginButtonIcon ? clientRegistration.loginButtonIcon : null],  
266 - clientId: [clientRegistration?.clientId ? clientRegistration.clientId : '', Validators.required],  
267 - clientSecret: [clientRegistration?.clientSecret ? clientRegistration.clientSecret : '', Validators.required],  
268 - accessTokenUri: [clientRegistration?.accessTokenUri ? clientRegistration.accessTokenUri : '', 296 + loginButtonLabel: [registration?.loginButtonLabel ? registration.loginButtonLabel : null, Validators.required],
  297 + loginButtonIcon: [registration?.loginButtonIcon ? registration.loginButtonIcon : null],
  298 + clientId: [registration?.clientId ? registration.clientId : '', Validators.required],
  299 + clientSecret: [registration?.clientSecret ? registration.clientSecret : '', Validators.required],
  300 + accessTokenUri: [registration?.accessTokenUri ? registration.accessTokenUri : '',
269 [Validators.required, 301 [Validators.required,
270 Validators.pattern(this.URL_REGEXP)]], 302 Validators.pattern(this.URL_REGEXP)]],
271 - authorizationUri: [clientRegistration?.authorizationUri ? clientRegistration.authorizationUri : '', 303 + authorizationUri: [registration?.authorizationUri ? registration.authorizationUri : '',
272 [Validators.required, 304 [Validators.required,
273 Validators.pattern(this.URL_REGEXP)]], 305 Validators.pattern(this.URL_REGEXP)]],
274 - scope: this.fb.array(clientRegistration?.scope ? clientRegistration.scope : [], this.validateScope),  
275 - jwkSetUri: [clientRegistration?.jwkSetUri ? clientRegistration.jwkSetUri : '', Validators.pattern(this.URL_REGEXP)],  
276 - userInfoUri: [clientRegistration?.userInfoUri ? clientRegistration.userInfoUri : '', 306 + scope: this.fb.array(registration?.scope ? registration.scope : [], OAuth2SettingsComponent.validateScope),
  307 + jwkSetUri: [registration?.jwkSetUri ? registration.jwkSetUri : '', Validators.pattern(this.URL_REGEXP)],
  308 + userInfoUri: [registration?.userInfoUri ? registration.userInfoUri : '',
277 [Validators.required, 309 [Validators.required,
278 Validators.pattern(this.URL_REGEXP)]], 310 Validators.pattern(this.URL_REGEXP)]],
279 clientAuthenticationMethod: [ 311 clientAuthenticationMethod: [
280 - clientRegistration?.clientAuthenticationMethod ? clientRegistration.clientAuthenticationMethod : ClientAuthenticationMethod.POST, 312 + registration?.clientAuthenticationMethod ? registration.clientAuthenticationMethod : ClientAuthenticationMethod.POST,
281 Validators.required], 313 Validators.required],
282 userNameAttributeName: [ 314 userNameAttributeName: [
283 - clientRegistration?.userNameAttributeName ? clientRegistration.userNameAttributeName : 'email', Validators.required], 315 + registration?.userNameAttributeName ? registration.userNameAttributeName : 'email', Validators.required],
284 mapperConfig: this.fb.group({ 316 mapperConfig: this.fb.group({
285 allowUserCreation: [ 317 allowUserCreation: [
286 - isDefinedAndNotNull(clientRegistration?.mapperConfig?.allowUserCreation) ?  
287 - clientRegistration.mapperConfig.allowUserCreation : true 318 + isDefinedAndNotNull(registration?.mapperConfig?.allowUserCreation) ?
  319 + registration.mapperConfig.allowUserCreation : true
288 ], 320 ],
289 activateUser: [ 321 activateUser: [
290 - isDefinedAndNotNull(clientRegistration?.mapperConfig?.activateUser) ? clientRegistration.mapperConfig.activateUser : false 322 + isDefinedAndNotNull(registration?.mapperConfig?.activateUser) ? registration.mapperConfig.activateUser : false
291 ], 323 ],
292 type: [ 324 type: [
293 - clientRegistration?.mapperConfig?.type ? clientRegistration.mapperConfig.type : MapperConfigType.BASIC, Validators.required 325 + registration?.mapperConfig?.type ? registration.mapperConfig.type : MapperConfigType.BASIC, Validators.required
294 ] 326 ]
295 } 327 }
296 ) 328 )
297 }); 329 });
298 330
299 - if (clientRegistration) {  
300 - this.changeMapperConfigType(clientRegistrationFormGroup, clientRegistration.mapperConfig.type, clientRegistration.mapperConfig); 331 + if (registration) {
  332 + this.changeMapperConfigType(clientRegistrationFormGroup, registration.mapperConfig.type, registration.mapperConfig);
301 } else { 333 } else {
302 this.changeMapperConfigType(clientRegistrationFormGroup, MapperConfigType.BASIC); 334 this.changeMapperConfigType(clientRegistrationFormGroup, MapperConfigType.BASIC);
303 this.setProviderDefaultValue(defaultProviderName, clientRegistrationFormGroup); 335 this.setProviderDefaultValue(defaultProviderName, clientRegistrationFormGroup);
@@ -315,16 +347,6 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -315,16 +347,6 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
315 return clientRegistrationFormGroup; 347 return clientRegistrationFormGroup;
316 } 348 }
317 349
318 - private validateScope(control: AbstractControl): ValidationErrors | null {  
319 - const scope: string[] = control.value;  
320 - if (!scope || !scope.length) {  
321 - return {  
322 - required: true  
323 - };  
324 - }  
325 - return null;  
326 - }  
327 -  
328 private setProviderDefaultValue(provider: string, clientRegistration: FormGroup) { 350 private setProviderDefaultValue(provider: string, clientRegistration: FormGroup) {
329 if (provider === 'Custom') { 351 if (provider === 'Custom') {
330 clientRegistration.reset(this.defaultProvider, {emitEvent: false}); 352 clientRegistration.reset(this.defaultProvider, {emitEvent: false});
@@ -355,7 +377,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -355,7 +377,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
355 } else { 377 } else {
356 mapperConfig.removeControl('custom'); 378 mapperConfig.removeControl('custom');
357 if (!mapperConfig.get('basic')) { 379 if (!mapperConfig.get('basic')) {
358 - mapperConfig.addControl('basic', this.formBasicGroup(type, predefinedValue?.basic)); 380 + mapperConfig.addControl('basic', this.formBasicGroup(predefinedValue?.basic));
359 } 381 }
360 if (type === MapperConfigType.GITHUB) { 382 if (type === MapperConfigType.GITHUB) {
361 mapperConfig.get('basic.emailAttributeKey').disable(); 383 mapperConfig.get('basic.emailAttributeKey').disable();
@@ -370,7 +392,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -370,7 +392,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
370 const setting = this.oauth2SettingsForm.getRawValue(); 392 const setting = this.oauth2SettingsForm.getRawValue();
371 this.oauth2Service.saveOAuth2Settings(setting).subscribe( 393 this.oauth2Service.saveOAuth2Settings(setting).subscribe(
372 (oauth2Settings) => { 394 (oauth2Settings) => {
373 - this.auth2ClientsParams = oauth2Settings; 395 + this.oauth2Info = oauth2Settings;
374 this.oauth2SettingsForm.patchValue(this.oauth2SettingsForm, {emitEvent: false}); 396 this.oauth2SettingsForm.patchValue(this.oauth2SettingsForm, {emitEvent: false});
375 this.oauth2SettingsForm.markAsUntouched(); 397 this.oauth2SettingsForm.markAsUntouched();
376 this.oauth2SettingsForm.markAsPristine(); 398 this.oauth2SettingsForm.markAsPristine();
@@ -403,58 +425,62 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -403,58 +425,62 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
403 controller.markAsDirty(); 425 controller.markAsDirty();
404 } 426 }
405 427
406 - addDomain(): void {  
407 - this.domainsParams.push(this.buildDomainsForm()); 428 + addOAuth2ParamsInfo(): void {
  429 + this.oauth2ParamsInfos.push(this.buildOAuth2ParamsInfoForm());
408 } 430 }
409 431
410 - deleteDomain($event: Event, index: number): void { 432 + deleteOAuth2ParamsInfo($event: Event, index: number): void {
411 if ($event) { 433 if ($event) {
412 $event.stopPropagation(); 434 $event.stopPropagation();
413 $event.preventDefault(); 435 $event.preventDefault();
414 } 436 }
415 437
416 - const domainName = this.domainListTittle(this.domainsParams.at(index)); 438 + const domainName = this.domainListTittle(this.oauth2ParamsInfos.at(index));
417 this.dialogService.confirm( 439 this.dialogService.confirm(
418 this.translate.instant('admin.oauth2.delete-domain-title', {domainName: domainName || ''}), 440 this.translate.instant('admin.oauth2.delete-domain-title', {domainName: domainName || ''}),
419 this.translate.instant('admin.oauth2.delete-domain-text'), null, 441 this.translate.instant('admin.oauth2.delete-domain-text'), null,
420 this.translate.instant('action.delete') 442 this.translate.instant('action.delete')
421 ).subscribe((data) => { 443 ).subscribe((data) => {
422 if (data) { 444 if (data) {
423 - this.domainsParams.removeAt(index);  
424 - this.domainsParams.markAsTouched();  
425 - this.domainsParams.markAsDirty(); 445 + this.oauth2ParamsInfos.removeAt(index);
  446 + this.oauth2ParamsInfos.markAsTouched();
  447 + this.oauth2ParamsInfos.markAsDirty();
426 } 448 }
427 }); 449 });
428 } 450 }
429 451
430 - clientDomainProviders(control: AbstractControl): FormArray { 452 + clientRegistrations(control: AbstractControl): FormArray {
431 return control.get('clientRegistrations') as FormArray; 453 return control.get('clientRegistrations') as FormArray;
432 } 454 }
433 455
434 - clientDomainInfos(control: AbstractControl): FormArray { 456 + domainInfos(control: AbstractControl): FormArray {
435 return control.get('domainInfos') as FormArray; 457 return control.get('domainInfos') as FormArray;
436 } 458 }
437 459
438 - addProvider(control: AbstractControl): void {  
439 - this.clientDomainProviders(control).push(this.buildProviderForm()); 460 + mobileInfos(control: AbstractControl): FormArray {
  461 + return control.get('mobileInfos') as FormArray;
440 } 462 }
441 463
442 - deleteProvider($event: Event, control: AbstractControl, index: number): void { 464 + addRegistration(control: AbstractControl): void {
  465 + this.clientRegistrations(control).push(this.buildRegistrationForm());
  466 + }
  467 +
  468 + deleteRegistration($event: Event, control: AbstractControl, index: number): void {
443 if ($event) { 469 if ($event) {
444 $event.stopPropagation(); 470 $event.stopPropagation();
445 $event.preventDefault(); 471 $event.preventDefault();
446 } 472 }
447 473
448 - const providerName = this.clientDomainProviders(control).at(index).get('additionalInfo.providerName').value; 474 + const providerName = this.clientRegistrations(control).at(index).get('additionalInfo.providerName').value;
449 this.dialogService.confirm( 475 this.dialogService.confirm(
450 this.translate.instant('admin.oauth2.delete-registration-title', {name: providerName || ''}), 476 this.translate.instant('admin.oauth2.delete-registration-title', {name: providerName || ''}),
451 this.translate.instant('admin.oauth2.delete-registration-text'), null, 477 this.translate.instant('admin.oauth2.delete-registration-text'), null,
452 this.translate.instant('action.delete') 478 this.translate.instant('action.delete')
453 ).subscribe((data) => { 479 ).subscribe((data) => {
454 if (data) { 480 if (data) {
455 - this.clientDomainProviders(control).removeAt(index);  
456 - this.clientDomainProviders(control).markAsTouched();  
457 - this.clientDomainProviders(control).markAsDirty(); 481 + this.clientRegistrations(control).removeAt(index);
  482 + this.clientRegistrations(control).markAsTouched();
  483 + this.clientRegistrations(control).markAsDirty();
458 } 484 }
459 }); 485 });
460 } 486 }
@@ -480,24 +506,41 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha @@ -480,24 +506,41 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
480 } 506 }
481 507
482 addDomainInfo(control: AbstractControl): void { 508 addDomainInfo(control: AbstractControl): void {
483 - this.clientDomainInfos(control).push(this.buildDomainForm({ 509 + this.domainInfos(control).push(this.buildDomainInfoForm({
484 name: '', 510 name: '',
485 scheme: DomainSchema.HTTPS 511 scheme: DomainSchema.HTTPS
486 })); 512 }));
487 } 513 }
488 514
489 - removeDomain($event: Event, control: AbstractControl, index: number): void { 515 + removeDomainInfo($event: Event, control: AbstractControl, index: number): void {
  516 + if ($event) {
  517 + $event.stopPropagation();
  518 + $event.preventDefault();
  519 + }
  520 + this.domainInfos(control).removeAt(index);
  521 + this.domainInfos(control).markAsTouched();
  522 + this.domainInfos(control).markAsDirty();
  523 + }
  524 +
  525 + addMobileInfo(control: AbstractControl): void {
  526 + this.mobileInfos(control).push(this.buildMobileInfoForm({
  527 + pkgName: '',
  528 + callbackUrlScheme: ''
  529 + }));
  530 + }
  531 +
  532 + removeMobileInfo($event: Event, control: AbstractControl, index: number): void {
490 if ($event) { 533 if ($event) {
491 $event.stopPropagation(); 534 $event.stopPropagation();
492 $event.preventDefault(); 535 $event.preventDefault();
493 } 536 }
494 - this.clientDomainInfos(control).removeAt(index);  
495 - this.clientDomainInfos(control).markAsTouched();  
496 - this.clientDomainInfos(control).markAsDirty(); 537 + this.mobileInfos(control).removeAt(index);
  538 + this.mobileInfos(control).markAsTouched();
  539 + this.mobileInfos(control).markAsDirty();
497 } 540 }
498 541
499 redirectURI(control: AbstractControl, schema?: DomainSchema): string { 542 redirectURI(control: AbstractControl, schema?: DomainSchema): string {
500 - const domainInfo = control.value as DomainInfo; 543 + const domainInfo = control.value as OAuth2DomainInfo;
501 if (domainInfo.name !== '') { 544 if (domainInfo.name !== '') {
502 let protocol; 545 let protocol;
503 if (isDefined(schema)) { 546 if (isDefined(schema)) {
@@ -16,21 +16,27 @@ @@ -16,21 +16,27 @@
16 16
17 import { HasUUID } from '@shared/models/id/has-uuid'; 17 import { HasUUID } from '@shared/models/id/has-uuid';
18 18
19 -export interface OAuth2ClientsParams { 19 +export interface OAuth2Info {
20 enabled: boolean; 20 enabled: boolean;
21 - domainsParams: OAuth2ClientsDomainParams[]; 21 + oauth2ParamsInfos: OAuth2ParamsInfo[];
22 } 22 }
23 23
24 -export interface OAuth2ClientsDomainParams {  
25 - clientRegistrations: ClientRegistration[];  
26 - domainInfos: DomainInfo[]; 24 +export interface OAuth2ParamsInfo {
  25 + clientRegistrations: OAuth2RegistrationInfo[];
  26 + domainInfos: OAuth2DomainInfo[];
  27 + mobileInfos: OAuth2MobileInfo[];
27 } 28 }
28 29
29 -export interface DomainInfo { 30 +export interface OAuth2DomainInfo {
30 name: string; 31 name: string;
31 scheme: DomainSchema; 32 scheme: DomainSchema;
32 } 33 }
33 34
  35 +export interface OAuth2MobileInfo {
  36 + pkgName: string;
  37 + callbackUrlScheme: string;
  38 +}
  39 +
34 export enum DomainSchema{ 40 export enum DomainSchema{
35 HTTP = 'HTTP', 41 HTTP = 'HTTP',
36 HTTPS = 'HTTPS', 42 HTTPS = 'HTTPS',
@@ -57,7 +63,7 @@ export enum TenantNameStrategy{ @@ -57,7 +63,7 @@ export enum TenantNameStrategy{
57 CUSTOM = 'CUSTOM' 63 CUSTOM = 'CUSTOM'
58 } 64 }
59 65
60 -export interface OAuth2ClientRegistrationTemplate extends ClientRegistration{ 66 +export interface OAuth2ClientRegistrationTemplate extends OAuth2RegistrationInfo{
61 comment: string; 67 comment: string;
62 createdTime: number; 68 createdTime: number;
63 helpLink: string; 69 helpLink: string;
@@ -66,7 +72,7 @@ export interface OAuth2ClientRegistrationTemplate extends ClientRegistration{ @@ -66,7 +72,7 @@ export interface OAuth2ClientRegistrationTemplate extends ClientRegistration{
66 id: HasUUID; 72 id: HasUUID;
67 } 73 }
68 74
69 -export interface ClientRegistration { 75 +export interface OAuth2RegistrationInfo {
70 loginButtonLabel: string; 76 loginButtonLabel: string;
71 loginButtonIcon: string; 77 loginButtonIcon: string;
72 clientId: string; 78 clientId: string;
@@ -219,7 +219,16 @@ @@ -219,7 +219,16 @@
219 "domain-schema-http": "HTTP", 219 "domain-schema-http": "HTTP",
220 "domain-schema-https": "HTTPS", 220 "domain-schema-https": "HTTPS",
221 "domain-schema-mixed": "HTTP+HTTPS", 221 "domain-schema-mixed": "HTTP+HTTPS",
222 - "enable": "Enable OAuth2 settings" 222 + "enable": "Enable OAuth2 settings",
  223 + "domains": "Domains",
  224 + "mobile-apps": "Mobile applications",
  225 + "no-mobile-apps": "No applications configured",
  226 + "mobile-package": "Application package",
  227 + "mobile-package-unique": "Application package must be unique.",
  228 + "mobile-callback-url-scheme": "Callback URL scheme",
  229 + "add-mobile-app": "Add application",
  230 + "delete-mobile-app": "Delete application info",
  231 + "providers": "Providers"
223 } 232 }
224 }, 233 },
225 "alarm": { 234 "alarm": {