Skip to content

Commit

Permalink
Add support for feature tags
Browse files Browse the repository at this point in the history
  • Loading branch information
jgrandja committed Jun 17, 2024
1 parent 7d35445 commit ac22e65
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
package org.springframework.security.config.feature;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.lang.Nullable;
import org.springframework.security.config.feature.model.Feature;
Expand All @@ -29,19 +33,24 @@
*/
public final class DefaultFeatureCatalog implements FeatureCatalog {

private final List<Feature> features = new ArrayList<>();
private final Map<Feature, Set<String>> features = new HashMap<>();

public void register(Feature feature) {
register(feature, new HashSet<>());
}

public void register(Feature feature, Set<String> tags) {
Assert.notNull(feature, "feature cannot be null");
this.features.add(feature);
Assert.notNull(tags, "tags cannot be null");
this.features.put(feature, tags);
}

@SuppressWarnings("unchecked")
@Nullable
@Override
public <T extends Feature> T getById(String id) {
Assert.hasText(id, "id cannot be empty");
for (Feature feature : this.features) {
for (Feature feature : this.features.keySet()) {
if (feature.getId().equals(id)) {
return (T) feature;
}
Expand All @@ -51,14 +60,14 @@ public <T extends Feature> T getById(String id) {

@Override
public List<Feature> getAll() {
return List.copyOf(this.features);
return List.copyOf(this.features.keySet());
}

@Override
public List<Feature> filterByType(FeatureType featureType) {
Assert.notNull(featureType, "featureType cannot be null");
List<Feature> features = new ArrayList<>();
for (Feature feature : this.features) {
for (Feature feature : this.features.keySet()) {
if (feature.getFeatureType().equals(featureType)) {
features.add(feature);
}
Expand All @@ -68,7 +77,14 @@ public List<Feature> filterByType(FeatureType featureType) {

@Override
public List<Feature> filterByTag(String tag) {
return null;
Assert.hasText(tag, "tag cannot be empty");
List<Feature> features = new ArrayList<>();
for (Map.Entry<Feature, Set<String>> feature : this.features.entrySet()) {
if (feature.getValue().contains(tag)) {
features.add(feature.getKey());
}
}
return features;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import org.springframework.security.config.feature.model.Feature;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

/**
* @author Joe Grandja
Expand Down Expand Up @@ -51,6 +52,11 @@ public <T extends Feature> Features add(Class<T> featureType) {

@Override
public <T extends Feature> Features addWithTag(String tag) {
Assert.hasText(tag, "tag cannot be empty");
List<Feature> features = this.featureCatalog.filterByTag(tag);
if (!CollectionUtils.isEmpty(features)) {
features.forEach((feature) -> add(feature.getClass()));
}
return this;
}

Expand All @@ -65,6 +71,7 @@ public <T extends Feature, B extends Feature.Builder<T, B>> Features customize(C
if (feature != null) {
B builder = (B) createBuilder(feature);
customizer.accept(builder);
removeFeature(featureType);
this.features.add(builder.build());
}
return this;
Expand Down Expand Up @@ -96,4 +103,8 @@ private <T extends Feature> T findFeature(Class<T> featureType) {
}
}

private <T extends Feature> void removeFeature(Class<T> featureType) {
this.features.removeIf((feature) -> feature.getClass().equals(featureType));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -39,12 +40,22 @@ public class FeatureConfiguration {

@Bean
public FeatureCatalog featureCatalog() {
// @formatter:off
DefaultFeatureCatalog featureCatalog = new DefaultFeatureCatalog();
featureCatalog.register(HttpBasicAuthenticationFeature.builder().build());
featureCatalog.register(CsrfExploitProtectionFeature.builder().build());
featureCatalog.register(UrlAuthorizationFeature.builder().build());
featureCatalog.register(OAuth2ResourceServerFeature.builder().build());
featureCatalog.register(
HttpBasicAuthenticationFeature.builder().build(),
Set.of("jwt-login"));
featureCatalog.register(
CsrfExploitProtectionFeature.builder().build(),
Set.of("jwt-login"));
featureCatalog.register(
UrlAuthorizationFeature.builder().build(),
Set.of("jwt-login"));
featureCatalog.register(
OAuth2ResourceServerFeature.builder().build(),
Set.of("jwt-login"));
return featureCatalog;
// @formatter:on
}

@Bean
Expand All @@ -60,13 +71,11 @@ public List<FeatureConfigurer> featureConfigurers() {
public Features features(FeatureCatalog featureCatalog) {
// @formatter:off
return Features.using(featureCatalog)
.add(HttpBasicAuthenticationFeature.class)
.addWithTag("jwt-login")
.customize(CsrfExploitProtectionFeature.Builder.class,
(builder) -> builder
.ignored(List.of("/token"))
)
.add(UrlAuthorizationFeature.class)
.add(OAuth2ResourceServerFeature.class);
);
// @formatter:on
}

Expand Down

0 comments on commit ac22e65

Please sign in to comment.