Skip to content

Commit

Permalink
Merge branch 'releases/3.16.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
fhanik committed Apr 21, 2017
2 parents 4491eac + 74e0744 commit b8f1bf1
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 14 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=3.15.0
version=3.16.0
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@

package org.cloudfoundry.identity.uaa.resources.jdbc;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import com.unboundid.scim.sdk.InvalidResourceException;
import com.unboundid.scim.sdk.SCIMException;
import com.unboundid.scim.sdk.SCIMFilter;
import org.apache.commons.logging.Log;
Expand All @@ -29,15 +23,85 @@
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static java.util.Collections.emptyList;
import static java.util.Optional.ofNullable;
import static org.cloudfoundry.identity.uaa.resources.jdbc.SearchQueryConverter.ProcessedFilter.ORDER_BY;

public class SimpleSearchQueryConverter implements SearchQueryConverter {

//LOWER
public static final List<String> VALID_ATTRIBUTE_NAMES = Collections.unmodifiableList(
Arrays.asList(
"id",
"created",
"lastmodified",
"version",
"username",
"password",
"email",
"givenname",
"familyname",
"name.familyname",
"name.givenname",
"active",
"phonenumber",
"verified",
"origin",
"identity_zone_id",
"passwd_lastmodified",
"passwd_change_required",
"last_logon_success_time",
"previous_logon_success_time",
"displayname",
"scope",
"group_id",
"member_id",
"member_type",
"description",
"client_id",
"authorized_grant_types",
"web_server_redirect_uri",
"redirect_uri",
"access_token_validity",
"refresh_token_validity",
"autoapprove",
"show_on_home_page",
"created_by",
"required_user_groups",
"user_id",
"meta.lastmodified",
"meta.created",
"meta.location",
"meta.resourcetype",
"meta.version",
"emails.value",
"groups.display",
"phonenumbers.value",
"gm.external_group",
"gm.origin",
"g.displayname",
"g.id"
)
);

private static Log logger = LogFactory.getLog(SimpleSearchQueryConverter.class);
private AttributeNameMapper mapper = new SimpleAttributeNameMapper(Collections.<String, String> emptyMap());

private boolean dbCaseInsensitive = false;

public SimpleSearchQueryConverter() {
}

public boolean isDbCaseInsensitive() {
return dbCaseInsensitive;
}
Expand Down Expand Up @@ -92,7 +156,7 @@ private String getWhereClause(String filter, String sortBy, boolean ascending, M
}
}

private SCIMFilter scimFilter(String filter) throws SCIMException {
protected SCIMFilter scimFilter(String filter) throws SCIMException {
SCIMFilter scimFilter;
try {
scimFilter = SCIMFilter.parse(filter);
Expand All @@ -101,9 +165,33 @@ private SCIMFilter scimFilter(String filter) throws SCIMException {
filter = filter.replaceAll("'","\"");
scimFilter = SCIMFilter.parse(filter);
}
validateFilterAttributes(scimFilter);
return scimFilter;
}

private void validateFilterAttributes(SCIMFilter filter) throws SCIMException {
List<String> invalidAttributes = new LinkedList<>();
validateFilterAttributes(filter, invalidAttributes);
if (!invalidAttributes.isEmpty()) {
throw new InvalidResourceException("Invalid filter attributes:"+StringUtils.collectionToCommaDelimitedString(invalidAttributes));
}
}

private void validateFilterAttributes(SCIMFilter filter, List<String> invalidAttribues) {
if (filter.getFilterAttribute()!=null && filter.getFilterAttribute().getAttributeName()!=null) {
String name = filter.getFilterAttribute().getAttributeName();
if (filter.getFilterAttribute().getSubAttributeName()!=null) {
name = name + "." + filter.getFilterAttribute().getSubAttributeName();
}
if (!VALID_ATTRIBUTE_NAMES.contains(name.toLowerCase())) {
invalidAttribues.add(name);
}
}
for (SCIMFilter subfilter : ofNullable(filter.getFilterComponents()).orElse(emptyList())) {
validateFilterAttributes(subfilter, invalidAttribues);
}
}

private String createFilter(SCIMFilter filter, Map<String,Object> values, AttributeNameMapper mapper, String paramPrefix) {
switch (filter.getFilterType()) {
case AND:
Expand All @@ -130,7 +218,12 @@ private String createFilter(SCIMFilter filter, Map<String,Object> values, Attrib
return null;
}

protected String comparisonClause(SCIMFilter filter, String comparator, Map<String, Object> values, String valuePrefix, String valueSuffix, String paramPrefix) {
protected String comparisonClause(SCIMFilter filter,
String comparator,
Map<String, Object> values,
String valuePrefix,
String valueSuffix,
String paramPrefix) {
String pName = getParamName(values, paramPrefix);
String paramName = ":"+pName;
if (filter.getFilterValue() == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* ****************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2017] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file.
* ****************************************************************************
*/

package org.cloudfoundry.identity.uaa.resources.jdbc;

import com.unboundid.scim.sdk.InvalidResourceException;
import com.unboundid.scim.sdk.SCIMFilter;
import org.cloudfoundry.identity.uaa.scim.jdbc.ScimSearchQueryConverter;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.util.concurrent.atomic.AtomicInteger;

import static java.util.Collections.emptyList;
import static java.util.Optional.ofNullable;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.startsWith;

public class SimpleSearchQueryConverterTests {

SimpleSearchQueryConverter converter;

String query = "user_id eq \"7e2345e8-8bbf-4eaa-9bc3-ae1ba610f890\"" +
"and " +
"client_id eq \"app\"" +
"and " +
"meta.lastmodified gt \"some-value\"" +
"and " +
"(an/**/invalid/**/attribute/**/and/**/1" + //invalid attribute name
" pr " + //operator (present)
"and "
+ "1 eq 1)" + //invalid attribute name 1
" and " +
"\"1\" eq \"1\"";

String validQuery = "user_id eq \"7e2345e8-8bbf-4eaa-9bc3-ae1ba610f890\"" +
"and " +
"client_id eq \"app\"" +
"and " +
"meta.lastmodified gt \"some-value\"" +
"and " +
"meta.created pr";

@Rule
public ExpectedException exception = ExpectedException.none();

@Before
public void setup() {
converter = new ScimSearchQueryConverter();
}

@Test
public void test_query() throws Exception {
exception.expect(InvalidResourceException.class);
exception.expectMessage(startsWith("Invalid filter attributes"));
exception.expectMessage(containsString("an/**/invalid/**/attribute/**/and/**/1"));
exception.expectMessage(containsString("1"));
exception.expectMessage(containsString("\"1\""));
SCIMFilter filter = converter.scimFilter(query);
}

@Test
public void print_query() throws Exception {
SCIMFilter filter = converter.scimFilter(validQuery);
printFilterAttributes(filter, new AtomicInteger(0));
}

public void printFilterAttributes(SCIMFilter filter, AtomicInteger pos) {
if (filter.getFilterAttribute() != null) {
String name = filter.getFilterAttribute().getAttributeName();
if (filter.getFilterAttribute().getSubAttributeName() != null) {
name = name + "." + filter.getFilterAttribute().getSubAttributeName();
}
System.out.println((pos.incrementAndGet()) + ". Attribute name:" + name);
}
for (SCIMFilter subfilter : ofNullable(filter.getFilterComponents()).orElse(emptyList())) {
printFilterAttributes(subfilter, pos);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public void canConvertValidFilters() throws Exception {
validate(filterProcessor.convert("username pr and emails.value co \".com\"", null, false),"(username IS NOT NULL AND LOWER(email) LIKE LOWER(:__value_0))", 1);
validate(filterProcessor.convert("username eq \"joe\" or emails.value co \".com\"", null, false),"(LOWER(username) = LOWER(:__value_0) OR LOWER(email) LIKE LOWER(:__value_1))", 2);
validate(filterProcessor.convert("active eq true", null, false),"active = :__value_0", 1, Boolean.class);
validate(filterProcessor.convert("test eq 1000000.45", null, false),"test = :__value_0", 1, Double.class);
validate(filterProcessor.convert("test eq 1000000", null, false),"test = :__value_0", 1, Double.class);
validate(filterProcessor.convert("Version eq 1000000.45", null, false),"Version = :__value_0", 1, Double.class);
validate(filterProcessor.convert("meta.VerSion eq 1000000", null, false),"VerSion = :__value_0", 1, Double.class);
}

@Test
Expand All @@ -84,8 +84,8 @@ public void caseInsensitiveDbDoesNotInjectLower() throws Exception {
validate(filterProcessor.convert("username pr and emails.value co \".com\"", null, false),"(username IS NOT NULL AND email LIKE :__value_0)", 1);
validate(filterProcessor.convert("username eq \"joe\" or emails.value co \".com\"", null, false),"(username = :__value_0 OR email LIKE :__value_1)", 2);
validate(filterProcessor.convert("active eq true", null, false),"active = :__value_0", 1, Boolean.class);
validate(filterProcessor.convert("test eq 1000000.45", null, false),"test = :__value_0", 1, Double.class);
validate(filterProcessor.convert("test eq 1000000", null, false),"test = :__value_0", 1, Double.class);
validate(filterProcessor.convert("Version eq 1000000.45", null, false),"Version = :__value_0", 1, Double.class);
validate(filterProcessor.convert("meta.VerSion eq 1000000", null, false),"VerSion = :__value_0", 1, Double.class);
}

@Test
Expand Down

0 comments on commit b8f1bf1

Please sign in to comment.