added transient structured value to system scope, added scope matcher function to scope service
parent
1ef18a3a93
commit
72f0ab631d
|
@ -28,6 +28,7 @@ import javax.persistence.Id;
|
|||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* @author jricher
|
||||
|
@ -49,6 +50,7 @@ public class SystemScope {
|
|||
private boolean defaultScope = false; // is this a default scope for newly-registered clients?
|
||||
private boolean structured = false; // is this a default scope for newly-registered clients?
|
||||
private String structuredParamDescription;
|
||||
private String structuredValue;
|
||||
|
||||
/**
|
||||
* Make a blank system scope with no value
|
||||
|
@ -64,6 +66,7 @@ public class SystemScope {
|
|||
public SystemScope(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
|
@ -161,8 +164,11 @@ public class SystemScope {
|
|||
return structured;
|
||||
}
|
||||
|
||||
public void setIsStructured(boolean isStructured) {
|
||||
this.structured = isStructured;
|
||||
/**
|
||||
* @param structured the structured to set
|
||||
*/
|
||||
public void setStructured(boolean structured) {
|
||||
this.structured = structured;
|
||||
}
|
||||
|
||||
@Basic
|
||||
|
@ -179,81 +185,117 @@ public class SystemScope {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the structuredValue
|
||||
*/
|
||||
@Transient // we don't save the value of a system scope separately
|
||||
public String getStructuredValue() {
|
||||
return structuredValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param structuredValue the structuredValue to set
|
||||
*/
|
||||
public void setStructuredValue(String structuredValue) {
|
||||
this.structuredValue = structuredValue;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (allowDynReg ? 1231 : 1237);
|
||||
result = prime * result + (defaultScope ? 1231 : 1237);
|
||||
result = prime * result + (structured ? 1231 : 1237);
|
||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||
result = prime * result + ((icon == null) ? 0 : icon.hashCode());
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (allowDynReg ? 1231 : 1237);
|
||||
result = prime * result + (defaultScope ? 1231 : 1237);
|
||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||
result = prime * result + ((icon == null) ? 0 : icon.hashCode());
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
result = prime * result + (structured ? 1231 : 1237);
|
||||
result = prime * result + ((structuredParamDescription == null) ? 0 : structuredParamDescription.hashCode());
|
||||
result = prime * result + ((structuredValue == null) ? 0 : structuredValue.hashCode());
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SystemScope other = (SystemScope) obj;
|
||||
if (allowDynReg != other.allowDynReg) {
|
||||
return false;
|
||||
}
|
||||
if (defaultScope != other.defaultScope) {
|
||||
return false;
|
||||
}
|
||||
if (structured != other.structured) {
|
||||
return false;
|
||||
}
|
||||
if (description == null) {
|
||||
if (other.description != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!description.equals(other.description)) {
|
||||
return false;
|
||||
}
|
||||
if (icon == null) {
|
||||
if (other.icon != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!icon.equals(other.icon)) {
|
||||
return false;
|
||||
}
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (value == null) {
|
||||
if (other.value != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!value.equals(other.value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof SystemScope)) {
|
||||
return false;
|
||||
}
|
||||
SystemScope other = (SystemScope) obj;
|
||||
if (allowDynReg != other.allowDynReg) {
|
||||
return false;
|
||||
}
|
||||
if (defaultScope != other.defaultScope) {
|
||||
return false;
|
||||
}
|
||||
if (description == null) {
|
||||
if (other.description != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!description.equals(other.description)) {
|
||||
return false;
|
||||
}
|
||||
if (icon == null) {
|
||||
if (other.icon != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!icon.equals(other.icon)) {
|
||||
return false;
|
||||
}
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (structured != other.structured) {
|
||||
return false;
|
||||
}
|
||||
if (structuredParamDescription == null) {
|
||||
if (other.structuredParamDescription != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!structuredParamDescription.equals(other.structuredParamDescription)) {
|
||||
return false;
|
||||
}
|
||||
if (structuredValue == null) {
|
||||
if (other.structuredValue != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!structuredValue.equals(other.structuredValue)) {
|
||||
return false;
|
||||
}
|
||||
if (value == null) {
|
||||
if (other.value != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!value.equals(other.value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SystemScope [value=" + value + ", description=" + description + ", icon=" + icon + ", allowDynReg=" + allowDynReg + ", defaultScope=" + defaultScope + ", isStructured=" + structured + "]";
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SystemScope [id=" + id + ", value=" + value + ", description=" + description + ", icon=" + icon + ", allowDynReg=" + allowDynReg + ", defaultScope=" + defaultScope + ", structured=" + structured + ", structuredParamDescription=" + structuredParamDescription + ", structuredValue="
|
||||
+ structuredValue + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,10 +66,13 @@ public interface SystemScopeService {
|
|||
*/
|
||||
public Set<String> toStrings(Set<SystemScope> scope);
|
||||
|
||||
public String baseScopeString(String value);
|
||||
|
||||
public Map<String, String> structuredScopeParameters(Set<String> scope);
|
||||
|
||||
public SystemScope toStructuredScope(String s);
|
||||
|
||||
/**
|
||||
* Test whether the scopes in both sets are compatible, with special
|
||||
* processing for structured scopes. All scopes in "actual" must exist in
|
||||
* "expected". If a scope in "expected" is structured and has a value, it
|
||||
* must be matched exactly by its corresponding scope in "actual". If a
|
||||
* scope in "expected" is structured but has no value, it may be matched by
|
||||
* a scope with or without a value in "actual".
|
||||
*/
|
||||
public boolean scopesMatch(Set<String> expected, Set<String> actual);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,9 @@
|
|||
*/
|
||||
package org.mitre.oauth2.service.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.mitre.oauth2.model.SystemScope;
|
||||
import org.mitre.oauth2.repository.SystemScopeRepository;
|
||||
|
@ -35,8 +33,9 @@ import com.google.common.base.Function;
|
|||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
|
@ -67,18 +66,26 @@ public class DefaultSystemScopeService implements SystemScopeService {
|
|||
private Function<String, SystemScope> stringToSystemScope = new Function<String, SystemScope>() {
|
||||
@Override
|
||||
public SystemScope apply(String input) {
|
||||
input = baseScopeString(input);
|
||||
if (input == null) {
|
||||
if (Strings.isNullOrEmpty(input)) {
|
||||
return null;
|
||||
} else {
|
||||
SystemScope s = getByValue(input);
|
||||
if (s != null) {
|
||||
// get the real scope if it's available
|
||||
return s;
|
||||
} else {
|
||||
List<String> parts = parseStructuredScopeValue(input);
|
||||
String base = parts.get(0); // the first part is the base
|
||||
// get the real scope if it's available
|
||||
SystemScope s = getByValue(base);
|
||||
if (s == null) {
|
||||
// make a fake one otherwise
|
||||
return new SystemScope(input);
|
||||
s = new SystemScope(base);
|
||||
if (parts.size() > 1) {
|
||||
s.setStructured(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (s.isStructured() && parts.size() > 1) {
|
||||
s.setStructuredValue(parts.get(1));
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -175,52 +182,48 @@ public class DefaultSystemScopeService implements SystemScopeService {
|
|||
}
|
||||
}
|
||||
|
||||
private String[] scopeParts(String value){
|
||||
return Iterables.toArray(
|
||||
Splitter.on(":").split(value),
|
||||
String.class);
|
||||
// parse a structured scope string into its components
|
||||
private List<String> parseStructuredScopeValue(String value) {
|
||||
return Lists.newArrayList(Splitter.on(":").split(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String baseScopeString(String value) {
|
||||
SystemScope s = toStructuredScope(value);
|
||||
if (s != null) {
|
||||
return s.getValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.mitre.oauth2.service.SystemScopeService#scopesMatch(java.util.Set, java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public boolean scopesMatch(Set<String> expected, Set<String> actual) {
|
||||
|
||||
@Override
|
||||
public SystemScope toStructuredScope(String value) {
|
||||
String[] scopeParts = scopeParts(value);
|
||||
String baseScope = value;
|
||||
if (scopeParts.length == 2) {
|
||||
baseScope = scopeParts[0];
|
||||
}
|
||||
SystemScope s = repository.getByValue(baseScope);
|
||||
if (s != null && s.isStructured()) {
|
||||
return s;
|
||||
}
|
||||
Set<SystemScope> ex = fromStrings(expected);
|
||||
Set<SystemScope> act = fromStrings(actual);
|
||||
|
||||
return null;
|
||||
}
|
||||
for (SystemScope actScope : act) {
|
||||
// first check to see if there's an exact match
|
||||
if (!ex.contains(actScope)) {
|
||||
// we didn't find an exact match
|
||||
if (actScope.isStructured() && !Strings.isNullOrEmpty(actScope.getStructuredValue())) {
|
||||
// if we didn't get an exact match but the actual scope is structured, we need to check further
|
||||
|
||||
@Override
|
||||
public Map<String, String> structuredScopeParameters(Set<String> scopes) {
|
||||
HashMap<String, String> ret = new HashMap<String, String>();
|
||||
// first, find the "base" scope for this
|
||||
SystemScope base = getByValue(actScope.getValue());
|
||||
if (!ex.contains(base)) {
|
||||
// if the expected doesn't contain the base scope, fail
|
||||
return false;
|
||||
} else {
|
||||
// we did find an exact match, need to check the rest
|
||||
}
|
||||
} else {
|
||||
// the scope wasn't structured, fail now
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// if we did find an exact match, we need to check the rest
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : scopes){
|
||||
SystemScope structured = toStructuredScope(s);
|
||||
if (structured != null){
|
||||
String[] scopeParts = scopeParts(s);
|
||||
if (scopeParts.length == 2){
|
||||
ret.put(scopeParts[0], scopeParts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we got all the way down here, the setup passed
|
||||
return true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ import org.mitre.oauth2.repository.SystemScopeRepository;
|
|||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
@ -147,4 +149,43 @@ public class TestDefaultSystemScopeService {
|
|||
assertThat(service.toStrings(allScopes), equalTo(allScopeStrings));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scopesMatch() {
|
||||
|
||||
Set<String> expected = Sets.newHashSet("foo", "bar", "baz");
|
||||
Set<String> actualGood = Sets.newHashSet("foo", "baz", "bar");
|
||||
Set<String> actualGood2 = Sets.newHashSet("foo", "bar");
|
||||
Set<String> actualBad = Sets.newHashSet("foo", "bob", "bar");
|
||||
|
||||
// same scopes, different order
|
||||
assertThat(service.scopesMatch(expected, actualGood), is(true));
|
||||
|
||||
// subset
|
||||
assertThat(service.scopesMatch(expected, actualGood2), is(true));
|
||||
|
||||
// extra scope (fail)
|
||||
assertThat(service.scopesMatch(expected, actualBad), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scopesMatch_structured() {
|
||||
Set<String> expected = Sets.newHashSet("foo", "bar", "baz");
|
||||
Set<String> actualGood = Sets.newHashSet("foo:value", "baz", "bar");
|
||||
Set<String> actualBad = Sets.newHashSet("foo:value", "bar:value");
|
||||
|
||||
// note: we have to use "thenAnswer" here to mimic the repository not serializing the structuredValue field
|
||||
Mockito.when(repository.getByValue("foo")).thenAnswer(new Answer<SystemScope>() {
|
||||
@Override
|
||||
public SystemScope answer(InvocationOnMock invocation) throws Throwable {
|
||||
SystemScope foo = new SystemScope("foo");
|
||||
foo.setStructured(true);
|
||||
return foo;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
assertThat(service.scopesMatch(expected, actualGood), is(true));
|
||||
|
||||
assertThat(service.scopesMatch(expected, actualBad), is(false));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue