Commit cc531daaeee9f4ff2f38b3f2dcaa25f5854358a6
1 parent
8e4f8594
Add platform type filter for oauth2 registrations.
Showing
22 changed files
with
187 additions
and
44 deletions
... | ... | @@ -96,6 +96,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration ( |
96 | 96 | authorization_uri varchar(255), |
97 | 97 | token_uri varchar(255), |
98 | 98 | scope varchar(255), |
99 | + platforms varchar(255), | |
99 | 100 | user_info_uri varchar(255), |
100 | 101 | user_name_attribute_name varchar(255), |
101 | 102 | jwk_set_uri varchar(255), | ... | ... |
... | ... | @@ -26,9 +26,11 @@ import org.springframework.web.bind.annotation.RequestParam; |
26 | 26 | import org.springframework.web.bind.annotation.ResponseBody; |
27 | 27 | import org.springframework.web.bind.annotation.ResponseStatus; |
28 | 28 | import org.springframework.web.bind.annotation.RestController; |
29 | +import org.thingsboard.server.common.data.StringUtils; | |
29 | 30 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
30 | 31 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; |
31 | 32 | import org.thingsboard.server.common.data.oauth2.OAuth2Info; |
33 | +import org.thingsboard.server.common.data.oauth2.PlatformType; | |
32 | 34 | import org.thingsboard.server.dao.oauth2.OAuth2Configuration; |
33 | 35 | import org.thingsboard.server.queue.util.TbCoreComponent; |
34 | 36 | import org.thingsboard.server.service.security.permission.Operation; |
... | ... | @@ -51,7 +53,8 @@ public class OAuth2Controller extends BaseController { |
51 | 53 | @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST) |
52 | 54 | @ResponseBody |
53 | 55 | public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request, |
54 | - @RequestParam(required = false) String pkgName) throws ThingsboardException { | |
56 | + @RequestParam(required = false) String pkgName, | |
57 | + @RequestParam(required = false) String platform) throws ThingsboardException { | |
55 | 58 | try { |
56 | 59 | if (log.isDebugEnabled()) { |
57 | 60 | log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort()); |
... | ... | @@ -61,7 +64,13 @@ public class OAuth2Controller extends BaseController { |
61 | 64 | log.debug("Header: {} {}", header, request.getHeader(header)); |
62 | 65 | } |
63 | 66 | } |
64 | - return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName); | |
67 | + PlatformType platformType = null; | |
68 | + if (StringUtils.isNotEmpty(platform)) { | |
69 | + try { | |
70 | + platformType = PlatformType.valueOf(platform); | |
71 | + } catch (Exception e) {} | |
72 | + } | |
73 | + return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName, platformType); | |
65 | 74 | } catch (Exception e) { |
66 | 75 | throw handleException(e); |
67 | 76 | } | ... | ... |
... | ... | @@ -199,6 +199,7 @@ public class ThingsboardInstallService { |
199 | 199 | databaseEntitiesUpgradeService.upgradeDatabase("3.2.2"); |
200 | 200 | |
201 | 201 | dataUpdateService.updateData("3.2.2"); |
202 | + systemDataLoaderService.createOAuth2Templates(); | |
202 | 203 | |
203 | 204 | log.info("Updating system data..."); |
204 | 205 | systemDataLoaderService.updateSystemWidgets(); | ... | ... |
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.oauth2; |
18 | 18 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; |
19 | 19 | import org.thingsboard.server.common.data.oauth2.OAuth2Info; |
20 | 20 | import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
21 | +import org.thingsboard.server.common.data.oauth2.PlatformType; | |
21 | 22 | import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientRegistrationInfo; |
22 | 23 | import org.thingsboard.server.common.data.oauth2.deprecated.OAuth2ClientsParams; |
23 | 24 | |
... | ... | @@ -25,7 +26,7 @@ import java.util.List; |
25 | 26 | import java.util.UUID; |
26 | 27 | |
27 | 28 | public interface OAuth2Service { |
28 | - List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName, String pkgName); | |
29 | + List<OAuth2ClientInfo> getOAuth2Clients(String domainScheme, String domainName, String pkgName, PlatformType platformType); | |
29 | 30 | |
30 | 31 | @Deprecated |
31 | 32 | void saveOAuth2Params(OAuth2ClientsParams oauth2Params); | ... | ... |
... | ... | @@ -46,6 +46,7 @@ public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2 |
46 | 46 | private String clientAuthenticationMethod; |
47 | 47 | private String loginButtonLabel; |
48 | 48 | private String loginButtonIcon; |
49 | + private List<PlatformType> platforms; | |
49 | 50 | |
50 | 51 | public OAuth2Registration(OAuth2Registration registration) { |
51 | 52 | super(registration); |
... | ... | @@ -62,6 +63,7 @@ public class OAuth2Registration extends SearchTextBasedWithAdditionalInfo<OAuth2 |
62 | 63 | this.clientAuthenticationMethod = registration.clientAuthenticationMethod; |
63 | 64 | this.loginButtonLabel = registration.loginButtonLabel; |
64 | 65 | this.loginButtonIcon = registration.loginButtonIcon; |
66 | + this.platforms = registration.platforms; | |
65 | 67 | } |
66 | 68 | |
67 | 69 | @Override | ... | ... |
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 | +public enum PlatformType { | |
19 | + WEB, ANDROID, IOS | |
20 | +} | ... | ... |
... | ... | @@ -433,6 +433,7 @@ public class ModelConstants { |
433 | 433 | public static final String OAUTH2_AUTHORIZATION_URI_PROPERTY = "authorization_uri"; |
434 | 434 | public static final String OAUTH2_TOKEN_URI_PROPERTY = "token_uri"; |
435 | 435 | public static final String OAUTH2_SCOPE_PROPERTY = "scope"; |
436 | + public static final String OAUTH2_PLATFORMS_PROPERTY = "platforms"; | |
436 | 437 | public static final String OAUTH2_USER_INFO_URI_PROPERTY = "user_info_uri"; |
437 | 438 | public static final String OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY = "user_name_attribute_name"; |
438 | 439 | public static final String OAUTH2_JWK_SET_URI_PROPERTY = "jwk_set_uri"; | ... | ... |
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | package org.thingsboard.server.dao.model.sql; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import io.micrometer.core.instrument.util.StringUtils; | |
19 | 20 | import lombok.Data; |
20 | 21 | import lombok.EqualsAndHashCode; |
21 | 22 | import org.hibernate.annotations.Type; |
... | ... | @@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig; |
27 | 28 | import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; |
28 | 29 | import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; |
29 | 30 | import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
31 | +import org.thingsboard.server.common.data.oauth2.PlatformType; | |
30 | 32 | import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType; |
31 | 33 | import org.thingsboard.server.dao.model.BaseSqlEntity; |
32 | 34 | import org.thingsboard.server.dao.model.ModelConstants; |
... | ... | @@ -38,7 +40,9 @@ import javax.persistence.EnumType; |
38 | 40 | import javax.persistence.Enumerated; |
39 | 41 | import javax.persistence.Table; |
40 | 42 | import java.util.Arrays; |
43 | +import java.util.Collections; | |
41 | 44 | import java.util.UUID; |
45 | +import java.util.stream.Collectors; | |
42 | 46 | |
43 | 47 | @Data |
44 | 48 | @EqualsAndHashCode(callSuper = true) |
... | ... | @@ -59,6 +63,8 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> |
59 | 63 | private String tokenUri; |
60 | 64 | @Column(name = ModelConstants.OAUTH2_SCOPE_PROPERTY) |
61 | 65 | private String scope; |
66 | + @Column(name = ModelConstants.OAUTH2_PLATFORMS_PROPERTY) | |
67 | + private String platforms; | |
62 | 68 | @Column(name = ModelConstants.OAUTH2_USER_INFO_URI_PROPERTY) |
63 | 69 | private String userInfoUri; |
64 | 70 | @Column(name = ModelConstants.OAUTH2_USER_NAME_ATTRIBUTE_NAME_PROPERTY) |
... | ... | @@ -125,6 +131,7 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> |
125 | 131 | this.authorizationUri = registration.getAuthorizationUri(); |
126 | 132 | this.tokenUri = registration.getAccessTokenUri(); |
127 | 133 | this.scope = registration.getScope().stream().reduce((result, element) -> result + "," + element).orElse(""); |
134 | + this.platforms = registration.getPlatforms() != null ? registration.getPlatforms().stream().map(Enum::name).reduce((result, element) -> result + "," + element).orElse("") : ""; | |
128 | 135 | this.userInfoUri = registration.getUserInfoUri(); |
129 | 136 | this.userNameAttributeName = registration.getUserNameAttributeName(); |
130 | 137 | this.jwkSetUri = registration.getJwkSetUri(); |
... | ... | @@ -201,6 +208,8 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> |
201 | 208 | registration.setAuthorizationUri(authorizationUri); |
202 | 209 | registration.setAccessTokenUri(tokenUri); |
203 | 210 | registration.setScope(Arrays.asList(scope.split(","))); |
211 | + registration.setPlatforms(StringUtils.isNotEmpty(platforms) ? Arrays.stream(platforms.split(",")) | |
212 | + .map(str -> PlatformType.valueOf(str)).collect(Collectors.toList()) : Collections.emptyList()); | |
204 | 213 | registration.setUserInfoUri(userInfoUri); |
205 | 214 | registration.setUserNameAttributeName(userNameAttributeName); |
206 | 215 | registration.setJwkSetUri(jwkSetUri); | ... | ... |
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | package org.thingsboard.server.dao.oauth2; |
17 | 17 | |
18 | 18 | import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
19 | +import org.thingsboard.server.common.data.oauth2.PlatformType; | |
19 | 20 | import org.thingsboard.server.common.data.oauth2.SchemeType; |
20 | 21 | import org.thingsboard.server.dao.Dao; |
21 | 22 | |
... | ... | @@ -24,7 +25,7 @@ import java.util.UUID; |
24 | 25 | |
25 | 26 | public interface OAuth2RegistrationDao extends Dao<OAuth2Registration> { |
26 | 27 | |
27 | - List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgName(List<SchemeType> domainSchemes, String domainName, String pkgName); | |
28 | + List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(List<SchemeType> domainSchemes, String domainName, String pkgName, PlatformType platformType); | |
28 | 29 | |
29 | 30 | List<OAuth2Registration> findByOAuth2ParamsId(UUID oauth2ParamsId); |
30 | 31 | ... | ... |
... | ... | @@ -65,8 +65,8 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se |
65 | 65 | private OAuth2MobileDao oauth2MobileDao; |
66 | 66 | |
67 | 67 | @Override |
68 | - public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName) { | |
69 | - log.trace("Executing getOAuth2Clients [{}://{}]", domainSchemeStr, domainName); | |
68 | + public List<OAuth2ClientInfo> getOAuth2Clients(String domainSchemeStr, String domainName, String pkgName, PlatformType platformType) { | |
69 | + log.trace("Executing getOAuth2Clients [{}://{}] pkgName=[{}] platformType=[{}]", domainSchemeStr, domainName, pkgName, platformType); | |
70 | 70 | if (domainSchemeStr == null) { |
71 | 71 | throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); |
72 | 72 | } |
... | ... | @@ -77,7 +77,9 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se |
77 | 77 | throw new IncorrectParameterException(INCORRECT_DOMAIN_SCHEME); |
78 | 78 | } |
79 | 79 | validateString(domainName, INCORRECT_DOMAIN_NAME + domainName); |
80 | - return oauth2RegistrationDao.findEnabledByDomainSchemesDomainNameAndPkgName(Arrays.asList(domainScheme, SchemeType.MIXED), domainName, pkgName).stream() | |
80 | + return oauth2RegistrationDao.findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType( | |
81 | + Arrays.asList(domainScheme, SchemeType.MIXED), domainName, pkgName, platformType) | |
82 | + .stream() | |
81 | 83 | .map(OAuth2Utils::toClientInfo) |
82 | 84 | .collect(Collectors.toList()); |
83 | 85 | } | ... | ... |
... | ... | @@ -127,6 +127,7 @@ public class OAuth2Utils { |
127 | 127 | .authorizationUri(registration.getAuthorizationUri()) |
128 | 128 | .accessTokenUri(registration.getAccessTokenUri()) |
129 | 129 | .scope(registration.getScope()) |
130 | + .platforms(registration.getPlatforms()) | |
130 | 131 | .userInfoUri(registration.getUserInfoUri()) |
131 | 132 | .userNameAttributeName(registration.getUserNameAttributeName()) |
132 | 133 | .jwkSetUri(registration.getJwkSetUri()) |
... | ... | @@ -167,6 +168,7 @@ public class OAuth2Utils { |
167 | 168 | registration.setAuthorizationUri(registrationInfo.getAuthorizationUri()); |
168 | 169 | registration.setAccessTokenUri(registrationInfo.getAccessTokenUri()); |
169 | 170 | registration.setScope(registrationInfo.getScope()); |
171 | + registration.setPlatforms(registrationInfo.getPlatforms()); | |
170 | 172 | registration.setUserInfoUri(registrationInfo.getUserInfoUri()); |
171 | 173 | registration.setUserNameAttributeName(registrationInfo.getUserNameAttributeName()); |
172 | 174 | registration.setJwkSetUri(registrationInfo.getJwkSetUri()); |
... | ... | @@ -224,6 +226,7 @@ public class OAuth2Utils { |
224 | 226 | .loginButtonLabel(clientRegistrationDto.getLoginButtonLabel()) |
225 | 227 | .loginButtonIcon(clientRegistrationDto.getLoginButtonIcon()) |
226 | 228 | .additionalInfo(clientRegistrationDto.getAdditionalInfo()) |
229 | + .platforms(Collections.emptyList()) | |
227 | 230 | .build(); |
228 | 231 | } |
229 | 232 | ... | ... |
... | ... | @@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; |
19 | 19 | import org.springframework.data.repository.CrudRepository; |
20 | 20 | import org.springframework.stereotype.Component; |
21 | 21 | import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
22 | +import org.thingsboard.server.common.data.oauth2.PlatformType; | |
22 | 23 | import org.thingsboard.server.common.data.oauth2.SchemeType; |
23 | 24 | import org.thingsboard.server.dao.DaoUtil; |
24 | 25 | import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity; |
... | ... | @@ -45,8 +46,9 @@ public class JpaOAuth2RegistrationDao extends JpaAbstractDao<OAuth2RegistrationE |
45 | 46 | } |
46 | 47 | |
47 | 48 | @Override |
48 | - public List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgName(List<SchemeType> domainSchemes, String domainName, String pkgName) { | |
49 | - return DaoUtil.convertDataList(repository.findAllEnabledByDomainSchemesNameAndPkgName(domainSchemes, domainName, pkgName)); | |
49 | + public List<OAuth2Registration> findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(List<SchemeType> domainSchemes, String domainName, String pkgName, PlatformType platformType) { | |
50 | + return DaoUtil.convertDataList(repository.findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(domainSchemes, domainName, pkgName, | |
51 | + platformType != null ? "%" + platformType.name() + "%" : null)); | |
50 | 52 | } |
51 | 53 | |
52 | 54 | @Override | ... | ... |
... | ... | @@ -30,14 +30,15 @@ public interface OAuth2RegistrationRepository extends CrudRepository<OAuth2Regis |
30 | 30 | "FROM OAuth2RegistrationEntity reg " + |
31 | 31 | "LEFT JOIN OAuth2ParamsEntity params on reg.oauth2ParamsId = params.id " + |
32 | 32 | "LEFT JOIN OAuth2DomainEntity domain on reg.oauth2ParamsId = domain.oauth2ParamsId " + |
33 | - "LEFT JOIN OAuth2MobileEntity mobile on reg.oauth2ParamsId = mobile.oauth2ParamsId " + | |
34 | 33 | "WHERE params.enabled = true " + |
35 | 34 | "AND domain.domainName = :domainName " + |
36 | 35 | "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); | |
36 | + "AND (:pkgName IS NULL OR EXISTS (SELECT mobile FROM OAuth2MobileEntity mobile WHERE mobile.oauth2ParamsId = reg.oauth2ParamsId AND mobile.pkgName = :pkgName)) " + | |
37 | + "AND (:platformFilter IS NULL OR reg.platforms IS NULL OR reg.platforms = '' OR reg.platforms LIKE :platformFilter)") | |
38 | + List<OAuth2RegistrationEntity> findEnabledByDomainSchemesDomainNameAndPkgNameAndPlatformType(@Param("domainSchemes") List<SchemeType> domainSchemes, | |
39 | + @Param("domainName") String domainName, | |
40 | + @Param("pkgName") String pkgName, | |
41 | + @Param("platformFilter") String platformFilter); | |
41 | 42 | |
42 | 43 | List<OAuth2RegistrationEntity> findByOauth2ParamsId(UUID oauth2ParamsId); |
43 | 44 | ... | ... |
... | ... | @@ -391,6 +391,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration ( |
391 | 391 | authorization_uri varchar(255), |
392 | 392 | token_uri varchar(255), |
393 | 393 | scope varchar(255), |
394 | + platforms varchar(255), | |
394 | 395 | user_info_uri varchar(255), |
395 | 396 | user_name_attribute_name varchar(255), |
396 | 397 | jwk_set_uri varchar(255), | ... | ... |
... | ... | @@ -428,6 +428,7 @@ CREATE TABLE IF NOT EXISTS oauth2_registration ( |
428 | 428 | authorization_uri varchar(255), |
429 | 429 | token_uri varchar(255), |
430 | 430 | scope varchar(255), |
431 | + platforms varchar(255), | |
431 | 432 | user_info_uri varchar(255), |
432 | 433 | user_name_attribute_name varchar(255), |
433 | 434 | jwk_set_uri varchar(255), | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.dao.service; |
17 | 17 | |
18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | |
18 | 19 | import com.google.common.collect.Lists; |
19 | 20 | import org.junit.After; |
20 | 21 | import org.junit.Assert; |
... | ... | @@ -31,6 +32,7 @@ import org.thingsboard.server.common.data.oauth2.OAuth2MobileInfo; |
31 | 32 | import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo; |
32 | 33 | import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
33 | 34 | import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo; |
35 | +import org.thingsboard.server.common.data.oauth2.PlatformType; | |
34 | 36 | import org.thingsboard.server.common.data.oauth2.SchemeType; |
35 | 37 | import org.thingsboard.server.dao.exception.DataValidationException; |
36 | 38 | import org.thingsboard.server.dao.oauth2.OAuth2Service; |
... | ... | @@ -231,10 +233,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
231 | 233 | registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null)) |
232 | 234 | .collect(Collectors.toList()); |
233 | 235 | |
234 | - List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null); | |
236 | + List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null, null); | |
235 | 237 | Assert.assertTrue(nonExistentDomainClients.isEmpty()); |
236 | 238 | |
237 | - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null); | |
239 | + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null); | |
238 | 240 | Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); |
239 | 241 | firstGroupClientInfos.forEach(firstGroupClientInfo -> { |
240 | 242 | Assert.assertTrue( |
... | ... | @@ -244,10 +246,10 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
244 | 246 | ); |
245 | 247 | }); |
246 | 248 | |
247 | - List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null); | |
249 | + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null); | |
248 | 250 | Assert.assertTrue(firstDomainHttpsClients.isEmpty()); |
249 | 251 | |
250 | - List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null); | |
252 | + List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null, null); | |
251 | 253 | Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size()); |
252 | 254 | secondGroupClientInfos.forEach(secondGroupClientInfo -> { |
253 | 255 | Assert.assertTrue( |
... | ... | @@ -256,7 +258,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
256 | 258 | && clientInfo.getName().equals(secondGroupClientInfo.getName())) |
257 | 259 | ); |
258 | 260 | }); |
259 | - List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null); | |
261 | + List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null, null); | |
260 | 262 | Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size()); |
261 | 263 | secondGroupClientInfos.forEach(secondGroupClientInfo -> { |
262 | 264 | Assert.assertTrue( |
... | ... | @@ -266,7 +268,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
266 | 268 | ); |
267 | 269 | }); |
268 | 270 | |
269 | - List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null); | |
271 | + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null); | |
270 | 272 | Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size()); |
271 | 273 | firstGroupClientInfos.forEach(firstGroupClientInfo -> { |
272 | 274 | Assert.assertTrue( |
... | ... | @@ -283,7 +285,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
283 | 285 | ); |
284 | 286 | }); |
285 | 287 | |
286 | - List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null); | |
288 | + List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null, null); | |
287 | 289 | Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size()); |
288 | 290 | firstGroupClientInfos.forEach(firstGroupClientInfo -> { |
289 | 291 | Assert.assertTrue( |
... | ... | @@ -331,7 +333,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
331 | 333 | registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null)) |
332 | 334 | .collect(Collectors.toList()); |
333 | 335 | |
334 | - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null); | |
336 | + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null); | |
335 | 337 | Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size()); |
336 | 338 | firstGroupClientInfos.forEach(firstGroupClientInfo -> { |
337 | 339 | Assert.assertTrue( |
... | ... | @@ -341,7 +343,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
341 | 343 | ); |
342 | 344 | }); |
343 | 345 | |
344 | - List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null); | |
346 | + List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null); | |
345 | 347 | Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size()); |
346 | 348 | firstGroupClientInfos.forEach(firstGroupClientInfo -> { |
347 | 349 | Assert.assertTrue( |
... | ... | @@ -381,13 +383,13 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
381 | 383 | |
382 | 384 | oAuth2Service.saveOAuth2Info(oAuth2Info); |
383 | 385 | |
384 | - List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null); | |
386 | + List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null); | |
385 | 387 | Assert.assertEquals(5, secondDomainHttpClients.size()); |
386 | 388 | |
387 | 389 | oAuth2Info.setEnabled(false); |
388 | 390 | oAuth2Service.saveOAuth2Info(oAuth2Info); |
389 | 391 | |
390 | - List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null); | |
392 | + List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null); | |
391 | 393 | Assert.assertEquals(0, secondDomainHttpDisabledClients.size()); |
392 | 394 | } |
393 | 395 | |
... | ... | @@ -520,7 +522,7 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
520 | 522 | OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info(); |
521 | 523 | Assert.assertEquals(oAuth2Info, foundOAuth2Info); |
522 | 524 | |
523 | - List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1"); | |
525 | + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null); | |
524 | 526 | Assert.assertEquals(3, firstDomainHttpClients.size()); |
525 | 527 | for (OAuth2ClientInfo clientInfo : firstDomainHttpClients) { |
526 | 528 | String[] segments = clientInfo.getUrl().split("/"); |
... | ... | @@ -536,6 +538,56 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
536 | 538 | } |
537 | 539 | } |
538 | 540 | |
541 | + @Test | |
542 | + public void testFindClientsByPackageAndPlatform() { | |
543 | + OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( | |
544 | + OAuth2ParamsInfo.builder() | |
545 | + .domainInfos(Lists.newArrayList( | |
546 | + OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), | |
547 | + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(), | |
548 | + OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build() | |
549 | + )) | |
550 | + .mobileInfos(Lists.newArrayList( | |
551 | + OAuth2MobileInfo.builder().pkgName("com.test.pkg1").callbackUrlScheme("testPkg1Callback").build(), | |
552 | + OAuth2MobileInfo.builder().pkgName("com.test.pkg2").callbackUrlScheme("testPkg2Callback").build() | |
553 | + )) | |
554 | + .clientRegistrations(Lists.newArrayList( | |
555 | + validRegistrationInfo("Google", Arrays.asList(PlatformType.WEB, PlatformType.ANDROID)), | |
556 | + validRegistrationInfo("Facebook", Arrays.asList(PlatformType.IOS)), | |
557 | + validRegistrationInfo("GitHub", Collections.emptyList()) | |
558 | + )) | |
559 | + .build(), | |
560 | + OAuth2ParamsInfo.builder() | |
561 | + .domainInfos(Lists.newArrayList( | |
562 | + OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(), | |
563 | + OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build() | |
564 | + )) | |
565 | + .mobileInfos(Collections.emptyList()) | |
566 | + .clientRegistrations(Lists.newArrayList( | |
567 | + validRegistrationInfo(), | |
568 | + validRegistrationInfo() | |
569 | + )) | |
570 | + .build() | |
571 | + )); | |
572 | + oAuth2Service.saveOAuth2Info(oAuth2Info); | |
573 | + | |
574 | + OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info(); | |
575 | + Assert.assertEquals(oAuth2Info, foundOAuth2Info); | |
576 | + | |
577 | + List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null); | |
578 | + Assert.assertEquals(3, firstDomainHttpClients.size()); | |
579 | + List<OAuth2ClientInfo> pkg1Clients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null); | |
580 | + Assert.assertEquals(3, pkg1Clients.size()); | |
581 | + List<OAuth2ClientInfo> pkg1AndroidClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.ANDROID); | |
582 | + Assert.assertEquals(2, pkg1AndroidClients.size()); | |
583 | + Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("Google"))); | |
584 | + Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("GitHub"))); | |
585 | + List<OAuth2ClientInfo> pkg1IOSClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.IOS); | |
586 | + Assert.assertEquals(2, pkg1IOSClients.size()); | |
587 | + Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("Facebook"))); | |
588 | + Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("GitHub"))); | |
589 | + } | |
590 | + | |
539 | 591 | private OAuth2Info createDefaultOAuth2Info() { |
540 | 592 | return new OAuth2Info(true, Lists.newArrayList( |
541 | 593 | OAuth2ParamsInfo.builder() |
... | ... | @@ -567,17 +619,22 @@ public class BaseOAuth2ServiceTest extends AbstractServiceTest { |
567 | 619 | } |
568 | 620 | |
569 | 621 | private OAuth2RegistrationInfo validRegistrationInfo() { |
622 | + return validRegistrationInfo(null, Collections.emptyList()); | |
623 | + } | |
624 | + | |
625 | + private OAuth2RegistrationInfo validRegistrationInfo(String label, List<PlatformType> platforms) { | |
570 | 626 | return OAuth2RegistrationInfo.builder() |
571 | 627 | .clientId(UUID.randomUUID().toString()) |
572 | 628 | .clientSecret(UUID.randomUUID().toString()) |
573 | 629 | .authorizationUri(UUID.randomUUID().toString()) |
574 | 630 | .accessTokenUri(UUID.randomUUID().toString()) |
575 | 631 | .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString())) |
632 | + .platforms(platforms == null ? Collections.emptyList() : platforms) | |
576 | 633 | .userInfoUri(UUID.randomUUID().toString()) |
577 | 634 | .userNameAttributeName(UUID.randomUUID().toString()) |
578 | 635 | .jwkSetUri(UUID.randomUUID().toString()) |
579 | 636 | .clientAuthenticationMethod(UUID.randomUUID().toString()) |
580 | - .loginButtonLabel(UUID.randomUUID().toString()) | |
637 | + .loginButtonLabel(label != null ? label : UUID.randomUUID().toString()) | |
581 | 638 | .loginButtonIcon(UUID.randomUUID().toString()) |
582 | 639 | .additionalInfo(mapper.createObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString())) |
583 | 640 | .mapperConfig( | ... | ... |
... | ... | @@ -44,7 +44,7 @@ import { AdminService } from '@core/http/admin.service'; |
44 | 44 | 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 | -import { OAuth2ClientInfo } from '@shared/models/oauth2.models'; | |
47 | +import { OAuth2ClientInfo, PlatformType } from '@shared/models/oauth2.models'; | |
48 | 48 | import { isDefinedAndNotNull, isMobileApp } from '@core/utils'; |
49 | 49 | |
50 | 50 | @Injectable({ |
... | ... | @@ -204,11 +204,8 @@ export class AuthService { |
204 | 204 | } |
205 | 205 | } |
206 | 206 | |
207 | - public loadOAuth2Clients(pkgName?: string): Observable<Array<OAuth2ClientInfo>> { | |
208 | - let url = '/api/noauth/oauth2Clients'; | |
209 | - if (isDefinedAndNotNull(pkgName)) { | |
210 | - url += `?pkgName=${pkgName}`; | |
211 | - } | |
207 | + public loadOAuth2Clients(): Observable<Array<OAuth2ClientInfo>> { | |
208 | + const url = '/api/noauth/oauth2Clients?platform=' + PlatformType.WEB; | |
212 | 209 | return this.http.post<Array<OAuth2ClientInfo>>(url, |
213 | 210 | null, defaultHttpOptions()).pipe( |
214 | 211 | catchError(err => of([])), | ... | ... |
... | ... | @@ -201,18 +201,27 @@ |
201 | 201 | |
202 | 202 | <ng-template matExpansionPanelContent> |
203 | 203 | <section [formGroupName]="j"> |
204 | - <section formGroupName="additionalInfo" fxLayout="row"> | |
205 | - <mat-form-field fxFlex class="mat-block"> | |
206 | - <mat-label translate>admin.oauth2.login-provider</mat-label> | |
207 | - <mat-select formControlName="providerName"> | |
208 | - <mat-option *ngFor="let provider of templateProvider" [value]="provider"> | |
209 | - {{ provider }} | |
204 | + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> | |
205 | + <section fxFlex formGroupName="additionalInfo" fxLayout="row"> | |
206 | + <mat-form-field fxFlex class="mat-block"> | |
207 | + <mat-label translate>admin.oauth2.login-provider</mat-label> | |
208 | + <mat-select formControlName="providerName"> | |
209 | + <mat-option *ngFor="let provider of templateProvider" [value]="provider"> | |
210 | + {{ provider }} | |
211 | + </mat-option> | |
212 | + </mat-select> | |
213 | + </mat-form-field> | |
214 | + <div [tb-help]="getHelpLink(registration)" *ngIf="!isCustomProvider(registration)"></div> | |
215 | + </section> | |
216 | + <mat-form-field floatLabel="always" fxFlex class="mat-block"> | |
217 | + <mat-label translate>admin.oauth2.allowed-platforms</mat-label> | |
218 | + <mat-select formControlName="platforms" multiple placeholder="{{ 'admin.oauth2.all-platforms' | translate }}"> | |
219 | + <mat-option *ngFor="let platform of platformTypes" [value]="platform"> | |
220 | + {{ platformTypeTranslations.get(platform) | translate }} | |
210 | 221 | </mat-option> |
211 | 222 | </mat-select> |
212 | 223 | </mat-form-field> |
213 | - <div [tb-help]="getHelpLink(registration)" *ngIf="!isCustomProvider(registration)"></div> | |
214 | - </section> | |
215 | - | |
224 | + </div> | |
216 | 225 | <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
217 | 226 | <mat-form-field fxFlex class="mat-block"> |
218 | 227 | <mat-label translate>admin.oauth2.client-id</mat-label> | ... | ... |
... | ... | @@ -28,7 +28,8 @@ import { |
28 | 28 | OAuth2DomainInfo, |
29 | 29 | OAuth2Info, OAuth2MobileInfo, |
30 | 30 | OAuth2ParamsInfo, |
31 | - OAuth2RegistrationInfo, | |
31 | + OAuth2RegistrationInfo, PlatformType, | |
32 | + platformTypeTranslations, | |
32 | 33 | TenantNameStrategy |
33 | 34 | } from '@shared/models/oauth2.models'; |
34 | 35 | import { Store } from '@ngrx/store'; |
... | ... | @@ -99,6 +100,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha |
99 | 100 | tenantNameStrategies = Object.keys(TenantNameStrategy); |
100 | 101 | protocols = Object.keys(DomainSchema); |
101 | 102 | domainSchemaTranslations = domainSchemaTranslations; |
103 | + platformTypes = Object.keys(PlatformType); | |
104 | + platformTypeTranslations = platformTypeTranslations; | |
102 | 105 | |
103 | 106 | templateProvider = ['Custom']; |
104 | 107 | |
... | ... | @@ -293,6 +296,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha |
293 | 296 | additionalInfo: this.fb.group({ |
294 | 297 | providerName: [additionalInfo?.providerName ? additionalInfo?.providerName : defaultProviderName, Validators.required] |
295 | 298 | }), |
299 | + platforms: [registration?.platforms ? registration.platforms : []], | |
296 | 300 | loginButtonLabel: [registration?.loginButtonLabel ? registration.loginButtonLabel : null, Validators.required], |
297 | 301 | loginButtonIcon: [registration?.loginButtonIcon ? registration.loginButtonIcon : null], |
298 | 302 | clientId: [registration?.clientId ? registration.clientId : '', Validators.required], | ... | ... |
... | ... | @@ -63,6 +63,20 @@ export enum TenantNameStrategy{ |
63 | 63 | CUSTOM = 'CUSTOM' |
64 | 64 | } |
65 | 65 | |
66 | +export enum PlatformType { | |
67 | + WEB = 'WEB', | |
68 | + ANDROID = 'ANDROID', | |
69 | + IOS = 'IOS' | |
70 | +} | |
71 | + | |
72 | +export const platformTypeTranslations = new Map<PlatformType, string>( | |
73 | + [ | |
74 | + [PlatformType.WEB, 'admin.oauth2.platform-web'], | |
75 | + [PlatformType.ANDROID, 'admin.oauth2.platform-android'], | |
76 | + [PlatformType.IOS, 'admin.oauth2.platform-ios'] | |
77 | + ] | |
78 | +); | |
79 | + | |
66 | 80 | export interface OAuth2ClientRegistrationTemplate extends OAuth2RegistrationInfo{ |
67 | 81 | comment: string; |
68 | 82 | createdTime: number; |
... | ... | @@ -80,6 +94,7 @@ export interface OAuth2RegistrationInfo { |
80 | 94 | accessTokenUri: string; |
81 | 95 | authorizationUri: string; |
82 | 96 | scope: string[]; |
97 | + platforms: PlatformType[]; | |
83 | 98 | jwkSetUri?: string; |
84 | 99 | userInfoUri: string; |
85 | 100 | clientAuthenticationMethod: ClientAuthenticationMethod; | ... | ... |
... | ... | @@ -228,7 +228,12 @@ |
228 | 228 | "mobile-callback-url-scheme": "Callback URL scheme", |
229 | 229 | "add-mobile-app": "Add application", |
230 | 230 | "delete-mobile-app": "Delete application info", |
231 | - "providers": "Providers" | |
231 | + "providers": "Providers", | |
232 | + "platform-web": "Web", | |
233 | + "platform-android": "Android", | |
234 | + "platform-ios": "iOS", | |
235 | + "all-platforms": "All platforms", | |
236 | + "allowed-platforms": "Allowed platforms" | |
232 | 237 | } |
233 | 238 | }, |
234 | 239 | "alarm": { | ... | ... |