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 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 143 ALTER TABLE dashboard
83 144 ADD COLUMN IF NOT EXISTS image varchar(1000000);
84 145
... ...
... ... @@ -37,6 +37,8 @@ import org.springframework.util.StringUtils;
37 37 import org.springframework.web.util.UriComponents;
38 38 import org.springframework.web.util.UriComponentsBuilder;
39 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 42 import org.thingsboard.server.utils.MiscUtils;
41 43
42 44 import javax.servlet.http.HttpServletRequest;
... ... @@ -46,12 +48,13 @@ import java.security.NoSuchAlgorithmException;
46 48 import java.util.Base64;
47 49 import java.util.HashMap;
48 50 import java.util.Map;
  51 +import java.util.UUID;
49 52
50 53 @Service
51 54 @Slf4j
52 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 58 private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
56 59 private static final char PATH_DELIMITER = '/';
57 60
... ... @@ -63,6 +66,9 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
63 66 @Autowired
64 67 private ClientRegistrationRepository clientRegistrationRepository;
65 68
  69 + @Autowired
  70 + private OAuth2Service oAuth2Service;
  71 +
66 72 @Autowired(required = false)
67 73 private OAuth2Configuration oauth2Configuration;
68 74
... ... @@ -71,7 +77,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
71 77 public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
72 78 String registrationId = this.resolveRegistrationId(request);
73 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 84 @Override
... ... @@ -80,7 +87,8 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
80 87 return null;
81 88 }
82 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 94 private String getAction(HttpServletRequest request, String defaultAction) {
... ... @@ -91,8 +99,12 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
91 99 return action;
92 100 }
93 101
  102 + private String getAppPackage(HttpServletRequest request) {
  103 + return request.getParameter("pkg");
  104 + }
  105 +
94 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 108 if (registrationId == null) {
97 109 return null;
98 110 }
... ... @@ -104,6 +116,14 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
104 116
105 117 Map<String, Object> attributes = new HashMap<>();
106 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 128 OAuth2AuthorizationRequest.Builder builder;
109 129 if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
... ...
... ... @@ -22,12 +22,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
22 22 import org.springframework.web.bind.annotation.RequestBody;
23 23 import org.springframework.web.bind.annotation.RequestMapping;
24 24 import org.springframework.web.bind.annotation.RequestMethod;
  25 +import org.springframework.web.bind.annotation.RequestParam;
25 26 import org.springframework.web.bind.annotation.ResponseBody;
26 27 import org.springframework.web.bind.annotation.ResponseStatus;
27 28 import org.springframework.web.bind.annotation.RestController;
28 29 import org.thingsboard.server.common.data.exception.ThingsboardException;
29 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 32 import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
32 33 import org.thingsboard.server.queue.util.TbCoreComponent;
33 34 import org.thingsboard.server.service.security.permission.Operation;
... ... @@ -49,7 +50,8 @@ public class OAuth2Controller extends BaseController {
49 50
50 51 @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST)
51 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 55 try {
54 56 if (log.isDebugEnabled()) {
55 57 log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort());
... ... @@ -59,7 +61,7 @@ public class OAuth2Controller extends BaseController {
59 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 65 } catch (Exception e) {
64 66 throw handleException(e);
65 67 }
... ... @@ -68,10 +70,10 @@ public class OAuth2Controller extends BaseController {
68 70 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
69 71 @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json")
70 72 @ResponseBody
71   - public OAuth2ClientsParams getCurrentOAuth2Params() throws ThingsboardException {
  73 + public OAuth2Info getCurrentOAuth2Info() throws ThingsboardException {
72 74 try {
73 75 accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ);
74   - return oAuth2Service.findOAuth2Params();
  76 + return oAuth2Service.findOAuth2Info();
75 77 } catch (Exception e) {
76 78 throw handleException(e);
77 79 }
... ... @@ -80,11 +82,11 @@ public class OAuth2Controller extends BaseController {
80 82 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
81 83 @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST)
82 84 @ResponseStatus(value = HttpStatus.OK)
83   - public OAuth2ClientsParams saveOAuth2Params(@RequestBody OAuth2ClientsParams oauth2Params) throws ThingsboardException {
  85 + public OAuth2Info saveOAuth2Info(@RequestBody OAuth2Info oauth2Info) throws ThingsboardException {
84 86 try {
85 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 90 } catch (Exception e) {
89 91 throw handleException(e);
90 92 }
... ...
... ... @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
23 23 import org.springframework.beans.factory.annotation.Autowired;
24 24 import org.springframework.context.annotation.Profile;
25 25 import org.springframework.stereotype.Service;
  26 +import org.thingsboard.common.util.JacksonUtil;
26 27 import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
27 28 import org.thingsboard.rule.engine.profile.TbDeviceProfileNodeConfiguration;
28 29 import org.thingsboard.server.common.data.EntityView;
... ... @@ -35,6 +36,8 @@ import org.thingsboard.server.common.data.id.TenantId;
35 36 import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
36 37 import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
37 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 41 import org.thingsboard.server.common.data.page.PageData;
39 42 import org.thingsboard.server.common.data.page.PageLink;
40 43 import org.thingsboard.server.common.data.page.TimePageLink;
... ... @@ -45,10 +48,11 @@ import org.thingsboard.server.dao.alarm.AlarmDao;
45 48 import org.thingsboard.server.dao.alarm.AlarmService;
46 49 import org.thingsboard.server.dao.entity.EntityService;
47 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 53 import org.thingsboard.server.dao.rule.RuleChainService;
49 54 import org.thingsboard.server.dao.tenant.TenantService;
50 55 import org.thingsboard.server.dao.timeseries.TimeseriesService;
51   -import org.thingsboard.common.util.JacksonUtil;
52 56 import org.thingsboard.server.service.install.InstallScripts;
53 57
54 58 import java.util.ArrayList;
... ... @@ -88,6 +92,9 @@ public class DefaultDataUpdateService implements DataUpdateService {
88 92 @Autowired
89 93 private AlarmDao alarmDao;
90 94
  95 + @Autowired
  96 + private OAuth2Service oAuth2Service;
  97 +
91 98 @Override
92 99 public void updateData(String fromVersion) throws Exception {
93 100 switch (fromVersion) {
... ... @@ -107,6 +114,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
107 114 log.info("Updating data from version 3.2.2 to 3.3.0 ...");
108 115 tenantsDefaultEdgeRuleChainUpdater.updateEntities(null);
109 116 tenantsAlarmsCustomerUpdater.updateEntities(null);
  117 + updateOAuth2Params();
110 118 break;
111 119 default:
112 120 throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion);
... ... @@ -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 33 import org.thingsboard.server.common.data.id.DashboardId;
34 34 import org.thingsboard.server.common.data.id.IdBased;
35 35 import org.thingsboard.server.common.data.id.TenantId;
36   -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
37 36 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  37 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
38 38 import org.thingsboard.server.common.data.page.PageData;
39 39 import org.thingsboard.server.common.data.page.PageLink;
40 40 import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
... ... @@ -93,9 +93,9 @@ public abstract class AbstractOAuth2ClientMapper {
93 93
94 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 100 UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, oauth2User.getEmail());
101 101
... ... @@ -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 147 user.setAdditionalInfo(additionalInfo);
... ...
... ... @@ -18,8 +18,8 @@ package org.thingsboard.server.service.security.auth.oauth2;
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
20 20 import org.springframework.stereotype.Service;
21   -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
22 21 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  22 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
23 23 import org.thingsboard.server.dao.oauth2.OAuth2User;
24 24 import org.thingsboard.server.service.security.model.SecurityUser;
25 25
... ... @@ -30,12 +30,12 @@ import java.util.Map;
30 30 public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper {
31 31
32 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 35 Map<String, Object> attributes = token.getPrincipal().getAttributes();
36 36 String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey());
37 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 23 import org.springframework.stereotype.Service;
24 24 import org.springframework.util.StringUtils;
25 25 import org.springframework.web.client.RestTemplate;
26   -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
27 26 import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
28 27 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  28 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
29 29 import org.thingsboard.server.dao.oauth2.OAuth2User;
30 30 import org.thingsboard.server.service.security.model.SecurityUser;
31 31
... ... @@ -39,10 +39,10 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
39 39 private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
40 40
41 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 44 OAuth2User oauth2User = getOAuth2User(token, providerAccessToken, config.getCustom());
45   - return getOrCreateSecurityUserFromOAuth2User(oauth2User, clientRegistration);
  45 + return getOrCreateSecurityUserFromOAuth2User(oauth2User, registration);
46 46 }
47 47
48 48 private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, String providerAccessToken, OAuth2CustomMapperConfig custom) {
... ...
... ... @@ -23,8 +23,8 @@ import org.springframework.boot.web.client.RestTemplateBuilder;
23 23 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
24 24 import org.springframework.stereotype.Service;
25 25 import org.springframework.web.client.RestTemplate;
26   -import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo;
27 26 import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
  27 +import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
28 28 import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
29 29 import org.thingsboard.server.dao.oauth2.OAuth2User;
30 30 import org.thingsboard.server.service.security.model.SecurityUser;
... ... @@ -46,13 +46,13 @@ public class GithubOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
46 46 private OAuth2Configuration oAuth2Configuration;
47 47
48 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 51 Map<String, String> githubMapperConfig = oAuth2Configuration.getGithubMapper();
52 52 String email = getEmail(githubMapperConfig.get(EMAIL_URL_KEY), providerAccessToken);
53 53 Map<String, Object> attributes = token.getPrincipal().getAttributes();
54 54 OAuth2User oAuth2User = BasicMapperUtils.getOAuth2User(email, attributes, config);
55   - return getOrCreateSecurityUserFromOAuth2User(oAuth2User, clientRegistration);
  55 + return getOrCreateSecurityUserFromOAuth2User(oAuth2User, registration);
56 56 }
57 57
58 58 private synchronized String getEmail(String emailUrl, String oauth2Token) {
... ...
... ... @@ -16,9 +16,10 @@
16 16 package org.thingsboard.server.service.security.auth.oauth2;
17 17
18 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 21 import org.thingsboard.server.service.security.model.SecurityUser;
21 22
22 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 18 import org.springframework.beans.factory.annotation.Autowired;
19 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
20 20 import org.springframework.security.core.AuthenticationException;
  21 +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
21 22 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
22 23 import org.springframework.stereotype.Component;
  24 +import org.thingsboard.server.common.data.StringUtils;
23 25 import org.thingsboard.server.common.data.id.CustomerId;
24 26 import org.thingsboard.server.common.data.id.EntityId;
25 27 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -51,9 +53,19 @@ public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationF
51 53 public void onAuthenticationFailure(HttpServletRequest request,
52 54 HttpServletResponse response, AuthenticationException exception)
53 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 67 httpCookieOAuth2AuthorizationRequestRepository.removeAuthorizationRequestCookies(request, response);
56   - getRedirectStrategy().sendRedirect(request, response, baseUrl + "/login?loginError=" +
  68 + getRedirectStrategy().sendRedirect(request, response, baseUrl + errorPrefix +
57 69 URLEncoder.encode(exception.getMessage(), StandardCharsets.UTF_8.toString()));
58 70 }
59 71 }
... ...
... ... @@ -20,12 +20,14 @@ import org.springframework.security.core.Authentication;
20 20 import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
21 21 import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
22 22 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
  23 +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
23 24 import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
24 25 import org.springframework.stereotype.Component;
  26 +import org.thingsboard.server.common.data.StringUtils;
25 27 import org.thingsboard.server.common.data.id.CustomerId;
26 28 import org.thingsboard.server.common.data.id.EntityId;
27 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 31 import org.thingsboard.server.common.data.security.model.JwtToken;
30 32 import org.thingsboard.server.dao.oauth2.OAuth2Service;
31 33 import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
... ... @@ -72,17 +74,24 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
72 74 public void onAuthenticationSuccess(HttpServletRequest request,
73 75 HttpServletResponse response,
74 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 85 try {
77 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 89 OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient(
81 90 token.getAuthorizedClientRegistrationId(),
82 91 token.getPrincipal().getName());
83   - OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(clientRegistration.getMapperConfig().getType());
  92 + OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(registration.getMapperConfig().getType());
84 93 SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oAuth2AuthorizedClient.getAccessToken().getTokenValue(),
85   - clientRegistration);
  94 + registration);
86 95
87 96 JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
88 97 JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
... ... @@ -91,7 +100,13 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
91 100 getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken());
92 101 } catch (Exception e) {
93 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 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 16 package org.thingsboard.server.dao.oauth2;
17 17
18 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 24 import java.util.List;
23 25 import java.util.UUID;
24 26
25 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 31 void saveOAuth2Params(OAuth2ClientsParams oauth2Params);
29 32
  33 + @Deprecated
30 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 * See the License for the specific language governing permissions and
14 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 18 import com.fasterxml.jackson.annotation.JsonCreator;
19 19 import com.fasterxml.jackson.annotation.JsonProperty;
  20 +import org.thingsboard.server.common.data.id.UUIDBased;
20 21
21 22 import java.util.UUID;
22 23
  24 +@Deprecated
23 25 public class OAuth2ClientRegistrationId extends UUIDBased {
24 26
25 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 * See the License for the specific language governing permissions and
14 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 18 import com.fasterxml.jackson.annotation.JsonCreator;
19 19 import com.fasterxml.jackson.annotation.JsonProperty;
  20 +import org.thingsboard.server.common.data.id.UUIDBased;
20 21
21 22 import java.util.UUID;
22 23
  24 +@Deprecated
23 25 public class OAuth2ClientRegistrationInfoId extends UUIDBased {
24 26
25 27 @JsonCreator
... ...
... ... @@ -20,10 +20,8 @@ import lombok.EqualsAndHashCode;
20 20 import lombok.NoArgsConstructor;
21 21 import lombok.ToString;
22 22 import org.thingsboard.server.common.data.HasName;
23   -import org.thingsboard.server.common.data.HasTenantId;
24 23 import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
25 24 import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId;
26   -import org.thingsboard.server.common.data.id.TenantId;
27 25
28 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 17
18 18 import com.fasterxml.jackson.databind.JsonNode;
19 19 import lombok.*;
20   -import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationInfoId;
21 20
22 21 import java.util.List;
23 22
... ... @@ -27,7 +26,7 @@ import java.util.List;
27 26 @NoArgsConstructor
28 27 @AllArgsConstructor
29 28 @Builder
30   -public class ClientRegistrationDto {
  29 +public class OAuth2RegistrationInfo {
31 30 private OAuth2MapperConfig mapperConfig;
32 31 private String clientId;
33 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.*;
  19 +import org.thingsboard.server.common.data.oauth2.SchemeType;
19 20
  21 +@Deprecated
20 22 @EqualsAndHashCode
21 23 @Data
22 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 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 24 @EqualsAndHashCode(callSuper = true)
22 25 @Data
23 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20 20 import lombok.NoArgsConstructor;
21 21 import lombok.ToString;
22 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 28 @EqualsAndHashCode(callSuper = true)
27 29 @Data
28 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 13 * See the License for the specific language governing permissions and
14 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 18 import com.fasterxml.jackson.annotation.JsonProperty;
19 19 import lombok.Data;
... ... @@ -22,10 +22,12 @@ import lombok.NoArgsConstructor;
22 22 import lombok.ToString;
23 23 import org.thingsboard.server.common.data.HasName;
24 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 28 import java.util.List;
28 29
  30 +@Deprecated
29 31 @EqualsAndHashCode(callSuper = true)
30 32 @Data
31 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 * See the License for the specific language governing permissions and
14 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 18 import lombok.*;
19 19
20 20 import java.util.List;
21   -import java.util.Set;
22 21
  22 +@Deprecated
23 23 @EqualsAndHashCode
24 24 @Data
25 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 * See the License for the specific language governing permissions and
14 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 18 import lombok.*;
19 19
20 20 import java.util.List;
21   -import java.util.Set;
22 21
  22 +@Deprecated
23 23 @EqualsAndHashCode
24 24 @Data
25 25 @ToString
... ...
... ... @@ -408,10 +408,20 @@ public class ModelConstants {
408 408 /**
409 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 423 public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info";
413 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 425 public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template";
416 426 public static final String OAUTH2_ENABLED_PROPERTY = "enabled";
417 427 public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id";
... ... @@ -422,7 +432,6 @@ public class ModelConstants {
422 432 public static final String OAUTH2_CLIENT_SECRET_PROPERTY = "client_secret";
423 433 public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri";
424 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 435 public static final String OAUTH2_SCOPE_PROPERTY = "scope";
427 436 public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri";
428 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 13 * See the License for the specific language governing permissions and
14 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 18 import com.fasterxml.jackson.databind.JsonNode;
19 19 import lombok.Data;
20 20 import lombok.EqualsAndHashCode;
21 21 import org.hibernate.annotations.Type;
22 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 24 import org.thingsboard.server.common.data.oauth2.*;
  25 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo;
25 26 import org.thingsboard.server.dao.model.BaseSqlEntity;
26 27 import org.thingsboard.server.dao.model.ModelConstants;
  28 +import org.thingsboard.server.dao.model.sql.deprecated.OAuth2ClientRegistrationInfoEntity;
27 29 import org.thingsboard.server.dao.util.mapping.JsonStringType;
28 30
29 31 import javax.persistence.*;
30 32 import java.util.Arrays;
31 33
  34 +@Deprecated
32 35 @Data
33 36 @EqualsAndHashCode(callSuper = true)
34 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 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20   -import org.thingsboard.server.common.data.oauth2.ExtendedOAuth2ClientRegistrationInfo;
  20 +import org.thingsboard.server.common.data.oauth2.deprecated.ExtendedOAuth2ClientRegistrationInfo;
21 21 import org.thingsboard.server.common.data.oauth2.SchemeType;
22 22
  23 +@Deprecated
23 24 @Data
24 25 @EqualsAndHashCode(callSuper = true)
25 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20 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 23 import org.thingsboard.server.common.data.oauth2.*;
  24 +import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistration;
24 25 import org.thingsboard.server.dao.model.BaseSqlEntity;
25 26 import org.thingsboard.server.dao.model.ModelConstants;
26 27 import org.thingsboard.server.dao.util.mapping.JsonStringType;
27 28
28 29 import javax.persistence.*;
29   -import java.util.Arrays;
30 30 import java.util.UUID;
31 31
  32 +@Deprecated
32 33 @Data
33 34 @EqualsAndHashCode(callSuper = true)
34 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20 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 22 import org.thingsboard.server.dao.model.ModelConstants;
23 23 import org.thingsboard.server.dao.util.mapping.JsonStringType;
24 24
25 25 import javax.persistence.Entity;
26 26 import javax.persistence.Table;
27 27
  28 +@Deprecated
28 29 @Data
29 30 @EqualsAndHashCode(callSuper = true)
30 31 @Entity
... ...
... ... @@ -21,7 +21,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
21 21 import org.springframework.security.oauth2.core.AuthorizationGrantType;
22 22 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
23 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 26 import java.util.UUID;
27 27
... ... @@ -34,25 +34,25 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
34 34
35 35 @Override
36 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 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 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 56 .redirectUri(defaultRedirectUriTemplate)
57 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 15 */
16 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 19 import org.thingsboard.server.dao.Dao;
20 20
21   -public interface OAuth2ClientRegistrationDao extends Dao<OAuth2ClientRegistration> {
  21 +public interface OAuth2ParamsDao extends Dao<OAuth2Params> {
22 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 19 import org.springframework.beans.factory.annotation.Autowired;
20 20 import org.springframework.stereotype.Service;
21 21 import org.springframework.util.StringUtils;
  22 +import org.thingsboard.server.common.data.BaseData;
22 23 import org.thingsboard.server.common.data.id.TenantId;
23 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 32 import org.thingsboard.server.dao.entity.AbstractEntityService;
25 33 import org.thingsboard.server.dao.exception.DataValidationException;
26 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 38 import javax.transaction.Transactional;
29 39 import java.util.*;
... ... @@ -45,9 +55,17 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
45 55 private OAuth2ClientRegistrationInfoDao clientRegistrationInfoDao;
46 56 @Autowired
47 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 67 @Override
50   - public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName) {
  68 + public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName) {
51 69 log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName);
52 70 if (domainSchemeStr == null) {
53 71 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
... ... @@ -59,12 +77,12 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
59 77 throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME);
60 78 }
61 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 81 .map(OAuth2Utils::toClientInfo)
65 82 .collect(Collectors.toList());
66 83 }
67 84
  85 + @Deprecated
68 86 @Override
69 87 @Transactional
70 88 public void saveOAuth2Params(OAuth2ClientsParams oauth2Params) {
... ... @@ -86,6 +104,33 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
86 104 }
87 105
88 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 134 public OAuth2ClientsParams findOAuth2Params() {
90 135 log.trace("Executing findOAuth2Params");
91 136 List<ExtendedOAuth2ClientRegistrationInfo> extendedInfos = clientRegistrationInfoDao.findAllExtended();
... ... @@ -93,16 +138,42 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se
93 138 }
94 139
95 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 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 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 179 private final Consumer<OAuth2ClientsParams> clientParamsValidator = oauth2Params -> {
... ... @@ -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 15 */
16 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 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 31 import java.util.*;
  32 +import java.util.stream.Collectors;
22 33
23 34 public class OAuth2Utils {
24 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 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 42 return client;
32 43 }
33 44
... ... @@ -99,4 +110,127 @@ public class OAuth2Utils {
99 110 clientRegistration.setDomainScheme(domainScheme);
100 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 13 * See the License for the specific language governing permissions and
14 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 20 import org.thingsboard.server.common.data.oauth2.SchemeType;
21 21 import org.thingsboard.server.dao.Dao;
22 22
23 23 import java.util.List;
24   -import java.util.Set;
25 24
  25 +@Deprecated
26 26 public interface OAuth2ClientRegistrationInfoDao extends Dao<OAuth2ClientRegistrationInfo> {
27 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 16 package org.thingsboard.server.dao.sql.oauth2;
17 17
18 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 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.RequiredArgsConstructor;
19   -import lombok.extern.slf4j.Slf4j;
20 19 import org.springframework.data.repository.CrudRepository;
21 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 24 import org.thingsboard.server.dao.sql.JpaAbstractDao;
26 25
27 26 import java.util.UUID;
28 27
  28 +@Deprecated
29 29 @Component
30 30 @RequiredArgsConstructor
31 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 13 * See the License for the specific language governing permissions and
14 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 18 import lombok.RequiredArgsConstructor;
19 19 import org.springframework.data.repository.CrudRepository;
20 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 23 import org.thingsboard.server.common.data.oauth2.SchemeType;
24 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 27 import org.thingsboard.server.dao.sql.JpaAbstractDao;
28 28
29 29 import java.util.ArrayList;
... ... @@ -31,6 +31,7 @@ import java.util.List;
31 31 import java.util.UUID;
32 32 import java.util.stream.Collectors;
33 33
  34 +@Deprecated
34 35 @Component
35 36 @RequiredArgsConstructor
36 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 13 * See the License for the specific language governing permissions and
14 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 18 import org.springframework.data.jpa.repository.Query;
19 19 import org.springframework.data.repository.CrudRepository;
20 20 import org.springframework.data.repository.query.Param;
21 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 25 import java.util.List;
26 26 import java.util.UUID;
27 27
  28 +@Deprecated
28 29 public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<OAuth2ClientRegistrationInfoEntity, UUID> {
29 30 @Query("SELECT new OAuth2ClientRegistrationInfoEntity(cr_info) " +
30 31 "FROM OAuth2ClientRegistrationInfoEntity cr_info " +
... ... @@ -34,7 +35,7 @@ public interface OAuth2ClientRegistrationInfoRepository extends CrudRepository<O
34 35 List<OAuth2ClientRegistrationInfoEntity> findAllByDomainSchemesAndName(@Param("domainSchemes") List<SchemeType> domainSchemes,
35 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 39 "FROM OAuth2ClientRegistrationInfoEntity cr_info " +
39 40 "LEFT JOIN OAuth2ClientRegistrationEntity cr on cr_info.id = cr.clientRegistrationInfoId ")
40 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 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 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 387 created_time bigint NOT NULL,
381 388 additional_info varchar,
382 389 client_id varchar(255),
... ... @@ -404,15 +411,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
404 411 custom_url varchar(255),
405 412 custom_username varchar(255),
406 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 421 created_time bigint NOT NULL,
413 422 domain_name varchar(255),
414 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 438 CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
... ... @@ -443,6 +463,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
443 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 509 CREATE TABLE IF NOT EXISTS api_usage_state (
447 510 id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY,
448 511 created_time bigint NOT NULL,
... ...
... ... @@ -411,9 +411,16 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary
411 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 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 424 created_time bigint NOT NULL,
418 425 additional_info varchar,
419 426 client_id varchar(255),
... ... @@ -441,15 +448,28 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_info (
441 448 custom_url varchar(255),
442 449 custom_username varchar(255),
443 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 458 created_time bigint NOT NULL,
450 459 domain_name varchar(255),
451 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 475 CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
... ... @@ -480,6 +500,49 @@ CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (
480 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 546 CREATE TABLE IF NOT EXISTS api_usage_state (
484 547 id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY,
485 548 created_time bigint NOT NULL,
... ...
... ... @@ -16,208 +16,225 @@
16 16 package org.thingsboard.server.dao.service;
17 17
18 18 import com.google.common.collect.Lists;
19   -import com.google.common.collect.Sets;
20 19 import org.junit.After;
21 20 import org.junit.Assert;
22 21 import org.junit.Before;
23 22 import org.junit.Test;
24 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 35 import org.thingsboard.server.dao.exception.DataValidationException;
27 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 42 import java.util.stream.Collectors;
31 43
32 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 47 @Autowired
36 48 protected OAuth2Service oAuth2Service;
37 49
38 50 @Before
39 51 public void beforeRun() {
40   - Assert.assertTrue(oAuth2Service.findAllClientRegistrationInfos().isEmpty());
  52 + Assert.assertTrue(oAuth2Service.findAllRegistrations().isEmpty());
41 53 }
42 54
43 55 @After
44 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 62 @Test(expected = DataValidationException.class)
51 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 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 71 .clientRegistrations(Lists.newArrayList(
60   - validClientRegistrationDto(),
61   - validClientRegistrationDto(),
62   - validClientRegistrationDto()
  72 + validRegistrationInfo(),
  73 + validRegistrationInfo(),
  74 + validRegistrationInfo()
63 75 ))
64 76 .build()
65 77 ));
66   - oAuth2Service.saveOAuth2Params(clientsParams);
  78 + oAuth2Service.saveOAuth2Info(oAuth2Info);
67 79 }
68 80
69 81 @Test(expected = DataValidationException.class)
70 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 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 90 .clientRegistrations(Lists.newArrayList(
79   - validClientRegistrationDto(),
80   - validClientRegistrationDto(),
81   - validClientRegistrationDto()
  91 + validRegistrationInfo(),
  92 + validRegistrationInfo(),
  93 + validRegistrationInfo()
82 94 ))
83 95 .build()
84 96 ));
85   - oAuth2Service.saveOAuth2Params(clientsParams);
  97 + oAuth2Service.saveOAuth2Info(oAuth2Info);
86 98 }
87 99
88 100 @Test
89 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 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 110 @Test
99 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 125 @Test
114 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 135 Assert.assertNotNull(foundAfterClearClientsParams);
124 136 Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams);
125 137 }
126 138
127 139 @Test
128 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 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 153 .clientRegistrations(Lists.newArrayList(
141   - validClientRegistrationDto()
  154 + validRegistrationInfo()
142 155 ))
143 156 .build(),
144   - OAuth2ClientsDomainParams.builder()
  157 + OAuth2ParamsInfo.builder()
145 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 162 .clientRegistrations(Lists.newArrayList(
149   - validClientRegistrationDto()
  163 + validRegistrationInfo()
150 164 ))
151 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 173 @Test
160 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 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 196 .clientRegistrations(firstGroup)
182 197 .build(),
183   - OAuth2ClientsDomainParams.builder()
  198 + OAuth2ParamsInfo.builder()
184 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 204 .clientRegistrations(secondGroup)
189 205 .build(),
190   - OAuth2ClientsDomainParams.builder()
  206 + OAuth2ParamsInfo.builder()
191 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 212 .clientRegistrations(thirdGroup)
196 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 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 224 .collect(Collectors.toList());
208 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 228 .collect(Collectors.toList());
212 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 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 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 238 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
222 239 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
223 240 Assert.assertTrue(
... ... @@ -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 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 251 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size());
235 252 secondGroupClientInfos.forEach(secondGroupClientInfo -> {
236 253 Assert.assertTrue(
... ... @@ -239,7 +256,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
239 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 260 Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size());
244 261 secondGroupClientInfos.forEach(secondGroupClientInfo -> {
245 262 Assert.assertTrue(
... ... @@ -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 270 Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size());
254 271 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
255 272 Assert.assertTrue(
... ... @@ -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 287 Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size());
271 288 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
272 289 Assert.assertTrue(
... ... @@ -286,34 +303,35 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
286 303
287 304 @Test
288 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 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 320 .clientRegistrations(firstGroup)
303 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 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 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 335 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
318 336 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
319 337 Assert.assertTrue(
... ... @@ -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 345 Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size());
328 346 firstGroupClientInfos.forEach(firstGroupClientInfo -> {
329 347 Assert.assertTrue(
... ... @@ -336,166 +354,220 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest {
336 354
337 355 @Test
338 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 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 364 .clientRegistrations(Lists.newArrayList(
347   - validClientRegistrationDto(),
348   - validClientRegistrationDto(),
349   - validClientRegistrationDto()
  365 + validRegistrationInfo(),
  366 + validRegistrationInfo(),
  367 + validRegistrationInfo()
350 368 ))
351 369 .build(),
352   - OAuth2ClientsDomainParams.builder()
  370 + OAuth2ParamsInfo.builder()
353 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 375 .clientRegistrations(Lists.newArrayList(
358   - validClientRegistrationDto(),
359   - validClientRegistrationDto()
  376 + validRegistrationInfo(),
  377 + validRegistrationInfo()
360 378 ))
361 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 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 391 Assert.assertEquals(0, secondDomainHttpDisabledClients.size());
374 392 }
375 393
376 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 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 403 .clientRegistrations(Lists.newArrayList(
386   - validClientRegistrationDto(),
387   - validClientRegistrationDto(),
388   - validClientRegistrationDto()
  404 + validRegistrationInfo(),
  405 + validRegistrationInfo(),
  406 + validRegistrationInfo()
389 407 ))
390 408 .build(),
391   - OAuth2ClientsDomainParams.builder()
  409 + OAuth2ParamsInfo.builder()
392 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 414 .clientRegistrations(Lists.newArrayList(
397   - validClientRegistrationDto(),
398   - validClientRegistrationDto()
  415 + validRegistrationInfo(),
  416 + validRegistrationInfo()
399 417 ))
400 418 .build(),
401   - OAuth2ClientsDomainParams.builder()
  419 + OAuth2ParamsInfo.builder()
402 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 424 .clientRegistrations(Lists.newArrayList(
407   - validClientRegistrationDto()
  425 + validRegistrationInfo()
408 426 ))
409 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 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 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 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 452 .clientRegistrations(Lists.newArrayList(
435   - validClientRegistrationDto(),
436   - validClientRegistrationDto(),
437   - validClientRegistrationDto()
  453 + validRegistrationInfo(),
  454 + validRegistrationInfo(),
  455 + validRegistrationInfo()
438 456 ))
439 457 .build(),
440   - OAuth2ClientsDomainParams.builder()
  458 + OAuth2ParamsInfo.builder()
441 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 463 .clientRegistrations(Lists.newArrayList(
446   - validClientRegistrationDto(),
447   - validClientRegistrationDto()
  464 + validRegistrationInfo(),
  465 + validRegistrationInfo()
448 466 ))
449 467 .build(),
450   - OAuth2ClientsDomainParams.builder()
  468 + OAuth2ParamsInfo.builder()
451 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 473 .clientRegistrations(Lists.newArrayList(
456   - validClientRegistrationDto()
  474 + validRegistrationInfo()
457 475 ))
458 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 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 548 .clientRegistrations(Lists.newArrayList(
478   - validClientRegistrationDto(),
479   - validClientRegistrationDto(),
480   - validClientRegistrationDto(),
481   - validClientRegistrationDto()
  549 + validRegistrationInfo(),
  550 + validRegistrationInfo(),
  551 + validRegistrationInfo(),
  552 + validRegistrationInfo()
482 553 ))
483 554 .build(),
484   - OAuth2ClientsDomainParams.builder()
  555 + OAuth2ParamsInfo.builder()
485 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 561 .clientRegistrations(Lists.newArrayList(
490   - validClientRegistrationDto(),
491   - validClientRegistrationDto()
  562 + validRegistrationInfo(),
  563 + validRegistrationInfo()
492 564 ))
493 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 571 .clientId(UUID.randomUUID().toString())
500 572 .clientSecret(UUID.randomUUID().toString())
501 573 .authorizationUri(UUID.randomUUID().toString())
... ...
... ... @@ -24,9 +24,13 @@ DROP TABLE IF EXISTS dashboard;
24 24 DROP TABLE IF EXISTS rule_node_state;
25 25 DROP TABLE IF EXISTS rule_node;
26 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 32 DROP TABLE IF EXISTS oauth2_client_registration;
28 33 DROP TABLE IF EXISTS oauth2_client_registration_info;
29   -DROP TABLE IF EXISTS oauth2_client_registration_template;
30 34 DROP TABLE IF EXISTS api_usage_state;
31 35 DROP TABLE IF EXISTS resource;
32 36 DROP TABLE IF EXISTS ota_package;
... ...
... ... @@ -25,9 +25,13 @@ DROP TABLE IF EXISTS rule_node_state;
25 25 DROP TABLE IF EXISTS rule_node;
26 26 DROP TABLE IF EXISTS rule_chain;
27 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 33 DROP TABLE IF EXISTS oauth2_client_registration;
29 34 DROP TABLE IF EXISTS oauth2_client_registration_info;
30   -DROP TABLE IF EXISTS oauth2_client_registration_template;
31 35 DROP TABLE IF EXISTS api_usage_state;
32 36 DROP TABLE IF EXISTS resource;
33 37 DROP TABLE IF EXISTS firmware;
... ...
... ... @@ -103,7 +103,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
103 103 import org.thingsboard.server.common.data.kv.TsKvEntry;
104 104 import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
105 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 107 import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
108 108 import org.thingsboard.server.common.data.ota.OtaPackageType;
109 109 import org.thingsboard.server.common.data.page.PageData;
... ... @@ -142,7 +142,6 @@ import java.util.HashMap;
142 142 import java.util.List;
143 143 import java.util.Map;
144 144 import java.util.Optional;
145   -import java.util.UUID;
146 145 import java.util.concurrent.ConcurrentHashMap;
147 146 import java.util.concurrent.ExecutorService;
148 147 import java.util.concurrent.Future;
... ... @@ -1773,21 +1772,28 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1773 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 1783 return restTemplate.exchange(
1778   - baseURL + "/api/noauth/oauth2Clients",
  1784 + urlBuilder.toString(),
1779 1785 HttpMethod.POST,
1780 1786 HttpEntity.EMPTY,
1781 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 1799 public String getLoginProcessingUrl() {
... ...
... ... @@ -45,7 +45,7 @@ import { ActionNotificationShow } from '@core/notification/notification.actions'
45 45 import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
46 46 import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component';
47 47 import { OAuth2ClientInfo } from '@shared/models/oauth2.models';
48   -import { isMobileApp } from '@core/utils';
  48 +import { isDefinedAndNotNull, isMobileApp } from '@core/utils';
49 49
50 50 @Injectable({
51 51 providedIn: 'root'
... ... @@ -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 213 null, defaultHttpOptions()).pipe(
210 214 catchError(err => of([])),
211 215 tap((OAuth2Clients) => {
... ...
... ... @@ -18,7 +18,7 @@ import { Injectable } from '@angular/core';
18 18 import { HttpClient } from '@angular/common/http';
19 19 import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
20 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 23 @Injectable({
24 24 providedIn: 'root'
... ... @@ -29,16 +29,16 @@ export class OAuth2Service {
29 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 36 public getOAuth2Template(config?: RequestConfig): Observable<Array<OAuth2ClientRegistrationTemplate>> {
37 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 42 defaultHttpOptionsFromConfig(config));
43 43 }
44 44
... ...
... ... @@ -34,19 +34,19 @@
34 34 {{ 'admin.oauth2.enable' | translate }}
35 35 </mat-checkbox>
36 36 <section *ngIf="oauth2SettingsForm.get('enabled').value" style="margin-top: 1em;">
37   - <ng-container formArrayName="domainsParams">
  37 + <ng-container formArrayName="oauth2ParamsInfos">
38 38 <div class="container">
39 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 41 <mat-expansion-panel [formGroupName]="i">
42 42 <mat-expansion-panel-header>
43 43 <mat-panel-title fxLayoutAlign="start center">
44   - {{ domainListTittle(domain) }}
  44 + {{ domainListTittle(oauth2ParamsInfo) }}
45 45 </mat-panel-title>
46 46 <mat-panel-description fxLayoutAlign="end center">
47 47 <button mat-icon-button
48 48 type="button"
49   - (click)="deleteDomain($event, i)"
  49 + (click)="deleteOAuth2ParamsInfo($event, i)"
50 50 matTooltip="{{ 'action.delete' | translate }}"
51 51 matTooltipPosition="above">
52 52 <mat-icon>delete</mat-icon>
... ... @@ -55,83 +55,133 @@
55 55 </mat-expansion-panel-header>
56 56
57 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 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 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 119 matTooltipPosition="above">
94   - <mat-icon class="material-icons" svgIcon="mdi:clipboard-arrow-left"></mat-icon>
  120 + <mat-icon>close</mat-icon>
95 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 164 matTooltipPosition="above">
105   - <mat-icon class="material-icons" svgIcon="mdi:clipboard-arrow-left"></mat-icon>
  165 + <mat-icon>close</mat-icon>
106 166 </button>
107   - </mat-form-field>
  167 + </div>
108 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 176 </button>
119 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 182 <ng-container formArrayName="clientRegistrations">
133 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 185 class="registration-card mat-elevation-z0">
136 186 <mat-expansion-panel-header>
137 187 <mat-panel-title fxLayoutAlign="start center">
... ... @@ -140,8 +190,8 @@
140 190 <mat-panel-description fxLayoutAlign="end center">
141 191 <button mat-icon-button
142 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 195 matTooltip="{{ 'admin.oauth2.delete-provider' | translate }}"
146 196 matTooltipPosition="above">
147 197 <mat-icon>delete</mat-icon>
... ... @@ -449,7 +499,7 @@
449 499 <div fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="8px">
450 500 <button mat-button mat-raised-button color="primary"
451 501 [disabled]="(isLoading$ | async)"
452   - (click)="addProvider(domain)"
  502 + (click)="addRegistration(oauth2ParamsInfo)"
453 503 type="button">
454 504 {{'admin.oauth2.add-provider' | translate}}
455 505 </button>
... ... @@ -467,7 +517,7 @@
467 517 <button type="button" mat-raised-button color="primary"
468 518 [disabled]="isLoading$ | async"
469 519 *ngIf="oauth2SettingsForm.get('enabled').value"
470   - (click)="addDomain()">
  520 + (click)="addOAuth2ParamsInfo()">
471 521 <mat-icon>add</mat-icon>
472 522 <span translate>action.add</span>
473 523 </button>
... ...
... ... @@ -62,7 +62,7 @@
62 62 }
63 63 }
64 64 }
65   - .domains-list{
  65 + .domains-list, .apps-list {
66 66 margin-bottom: 1.5em;
67 67 .mat-form-field-suffix .mat-icon-button .mat-icon{
68 68 font-size: 24px;
... ...
... ... @@ -18,8 +18,6 @@ import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
18 18 import { AbstractControl, FormArray, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms';
19 19 import {
20 20 ClientAuthenticationMethod,
21   - ClientRegistration,
22   - DomainInfo,
23 21 DomainSchema,
24 22 domainSchemaTranslations,
25 23 MapperConfig,
... ... @@ -27,8 +25,10 @@ import {
27 25 MapperConfigCustom,
28 26 MapperConfigType,
29 27 OAuth2ClientRegistrationTemplate,
30   - OAuth2ClientsDomainParams,
31   - OAuth2ClientsParams,
  28 + OAuth2DomainInfo,
  29 + OAuth2Info, OAuth2MobileInfo,
  30 + OAuth2ParamsInfo,
  31 + OAuth2RegistrationInfo,
32 32 TenantNameStrategy
33 33 } from '@shared/models/oauth2.models';
34 34 import { Store } from '@ngrx/store';
... ... @@ -52,6 +52,20 @@ import { ActivatedRoute } from '@angular/router';
52 52 })
53 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 69 private URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.,?+=&%@\-/]*)?$/;
56 70 private DOMAIN_AND_PORT_REGEXP = /^(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?$/;
57 71 private subscriptions: Subscription[] = [];
... ... @@ -77,7 +91,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
77 91 readonly separatorKeysCodes: number[] = [ENTER, COMMA];
78 92
79 93 oauth2SettingsForm: FormGroup;
80   - auth2ClientsParams: OAuth2ClientsParams;
  94 + oauth2Info: OAuth2Info;
81 95
82 96 clientAuthenticationMethods = Object.keys(ClientAuthenticationMethod);
83 97 mapperConfigType = MapperConfigType;
... ... @@ -90,14 +104,14 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
90 104
91 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 117 ngOnInit(): void {
... ... @@ -106,10 +120,10 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
106 120 this.oauth2Service.getOAuth2Template(),
107 121 this.oauth2Service.getOAuth2Settings()
108 122 ]).subscribe(
109   - ([templates, auth2ClientsParams]) => {
  123 + ([templates, oauth2Info]) => {
110 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 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 148 let tenantNamePattern;
139 149 if (mapperConfigBasic?.tenantNamePattern) {
140 150 tenantNamePattern = mapperConfigBasic.tenantNamePattern;
... ... @@ -173,16 +183,16 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
173 183
174 184 private buildOAuth2SettingsForm(): void {
175 185 this.oauth2SettingsForm = this.fb.group({
176   - domainsParams: this.fb.array([]),
  186 + oauth2ParamsInfos: this.fb.array([]),
177 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 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 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 228 if (domainInfos.length) {
207 229 const domainList = new Set<string>();
208 230 domainInfos.forEach((domain) => {
... ... @@ -213,41 +235,51 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
213 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 240 domainInfos: this.fb.array([], Validators.required),
  241 + mobileInfos: this.fb.array([]),
219 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 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 265 name: [domainInfo ? domainInfo.name : this.window.location.hostname, [
240 266 Validators.required,
241 267 Validators.pattern(this.DOMAIN_AND_PORT_REGEXP)]],
242 268 scheme: [domainInfo?.scheme ? domainInfo.scheme : DomainSchema.HTTPS, Validators.required]
243 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 280 let additionalInfo = null;
249   - if (isDefinedAndNotNull(clientRegistration?.additionalInfo)) {
250   - additionalInfo = clientRegistration.additionalInfo;
  281 + if (isDefinedAndNotNull(registration?.additionalInfo)) {
  282 + additionalInfo = registration.additionalInfo;
251 283 if (this.templateProvider.indexOf(additionalInfo.providerName) === -1) {
252 284 additionalInfo.providerName = 'Custom';
253 285 }
... ... @@ -261,43 +293,43 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
261 293 additionalInfo: this.fb.group({
262 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 301 [Validators.required,
270 302 Validators.pattern(this.URL_REGEXP)]],
271   - authorizationUri: [clientRegistration?.authorizationUri ? clientRegistration.authorizationUri : '',
  303 + authorizationUri: [registration?.authorizationUri ? registration.authorizationUri : '',
272 304 [Validators.required,
273 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 309 [Validators.required,
278 310 Validators.pattern(this.URL_REGEXP)]],
279 311 clientAuthenticationMethod: [
280   - clientRegistration?.clientAuthenticationMethod ? clientRegistration.clientAuthenticationMethod : ClientAuthenticationMethod.POST,
  312 + registration?.clientAuthenticationMethod ? registration.clientAuthenticationMethod : ClientAuthenticationMethod.POST,
281 313 Validators.required],
282 314 userNameAttributeName: [
283   - clientRegistration?.userNameAttributeName ? clientRegistration.userNameAttributeName : 'email', Validators.required],
  315 + registration?.userNameAttributeName ? registration.userNameAttributeName : 'email', Validators.required],
284 316 mapperConfig: this.fb.group({
285 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 321 activateUser: [
290   - isDefinedAndNotNull(clientRegistration?.mapperConfig?.activateUser) ? clientRegistration.mapperConfig.activateUser : false
  322 + isDefinedAndNotNull(registration?.mapperConfig?.activateUser) ? registration.mapperConfig.activateUser : false
291 323 ],
292 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 333 } else {
302 334 this.changeMapperConfigType(clientRegistrationFormGroup, MapperConfigType.BASIC);
303 335 this.setProviderDefaultValue(defaultProviderName, clientRegistrationFormGroup);
... ... @@ -315,16 +347,6 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
315 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 350 private setProviderDefaultValue(provider: string, clientRegistration: FormGroup) {
329 351 if (provider === 'Custom') {
330 352 clientRegistration.reset(this.defaultProvider, {emitEvent: false});
... ... @@ -355,7 +377,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
355 377 } else {
356 378 mapperConfig.removeControl('custom');
357 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 382 if (type === MapperConfigType.GITHUB) {
361 383 mapperConfig.get('basic.emailAttributeKey').disable();
... ... @@ -370,7 +392,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
370 392 const setting = this.oauth2SettingsForm.getRawValue();
371 393 this.oauth2Service.saveOAuth2Settings(setting).subscribe(
372 394 (oauth2Settings) => {
373   - this.auth2ClientsParams = oauth2Settings;
  395 + this.oauth2Info = oauth2Settings;
374 396 this.oauth2SettingsForm.patchValue(this.oauth2SettingsForm, {emitEvent: false});
375 397 this.oauth2SettingsForm.markAsUntouched();
376 398 this.oauth2SettingsForm.markAsPristine();
... ... @@ -403,58 +425,62 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
403 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 433 if ($event) {
412 434 $event.stopPropagation();
413 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 439 this.dialogService.confirm(
418 440 this.translate.instant('admin.oauth2.delete-domain-title', {domainName: domainName || ''}),
419 441 this.translate.instant('admin.oauth2.delete-domain-text'), null,
420 442 this.translate.instant('action.delete')
421 443 ).subscribe((data) => {
422 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 453 return control.get('clientRegistrations') as FormArray;
432 454 }
433 455
434   - clientDomainInfos(control: AbstractControl): FormArray {
  456 + domainInfos(control: AbstractControl): FormArray {
435 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 469 if ($event) {
444 470 $event.stopPropagation();
445 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 475 this.dialogService.confirm(
450 476 this.translate.instant('admin.oauth2.delete-registration-title', {name: providerName || ''}),
451 477 this.translate.instant('admin.oauth2.delete-registration-text'), null,
452 478 this.translate.instant('action.delete')
453 479 ).subscribe((data) => {
454 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 506 }
481 507
482 508 addDomainInfo(control: AbstractControl): void {
483   - this.clientDomainInfos(control).push(this.buildDomainForm({
  509 + this.domainInfos(control).push(this.buildDomainInfoForm({
484 510 name: '',
485 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 533 if ($event) {
491 534 $event.stopPropagation();
492 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 542 redirectURI(control: AbstractControl, schema?: DomainSchema): string {
500   - const domainInfo = control.value as DomainInfo;
  543 + const domainInfo = control.value as OAuth2DomainInfo;
501 544 if (domainInfo.name !== '') {
502 545 let protocol;
503 546 if (isDefined(schema)) {
... ...
... ... @@ -16,21 +16,27 @@
16 16
17 17 import { HasUUID } from '@shared/models/id/has-uuid';
18 18
19   -export interface OAuth2ClientsParams {
  19 +export interface OAuth2Info {
20 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 31 name: string;
31 32 scheme: DomainSchema;
32 33 }
33 34
  35 +export interface OAuth2MobileInfo {
  36 + pkgName: string;
  37 + callbackUrlScheme: string;
  38 +}
  39 +
34 40 export enum DomainSchema{
35 41 HTTP = 'HTTP',
36 42 HTTPS = 'HTTPS',
... ... @@ -57,7 +63,7 @@ export enum TenantNameStrategy{
57 63 CUSTOM = 'CUSTOM'
58 64 }
59 65
60   -export interface OAuth2ClientRegistrationTemplate extends ClientRegistration{
  66 +export interface OAuth2ClientRegistrationTemplate extends OAuth2RegistrationInfo{
61 67 comment: string;
62 68 createdTime: number;
63 69 helpLink: string;
... ... @@ -66,7 +72,7 @@ export interface OAuth2ClientRegistrationTemplate extends ClientRegistration{
66 72 id: HasUUID;
67 73 }
68 74
69   -export interface ClientRegistration {
  75 +export interface OAuth2RegistrationInfo {
70 76 loginButtonLabel: string;
71 77 loginButtonIcon: string;
72 78 clientId: string;
... ...
... ... @@ -219,7 +219,16 @@
219 219 "domain-schema-http": "HTTP",
220 220 "domain-schema-https": "HTTPS",
221 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 234 "alarm": {
... ...