JAX-RS security role-based (#RolesAllowed) entity filtering - jackson

In a JAX-RS application, some of my resources must be filtered depending on which roles the signed-in user has been assigned to. I'm trying to accomplish this using security annotations (#RolesAllowed, #DenyAll and #PermitAll).
This is what I'm looking for:
public class MyEntity {
public String getPublicString() {
...
}
#RolesAllowed("secretRole")
public String getSecretString() {
...
}
}
#Path("/myResource")
public MyResource {
#GET #Path("/{id}")
public MyEntity get(#PathParam("id") int id) {
...
}
}
Now, everyone (anonymous and logged-in users) can GET MyResource and retrieve MyEntity (per id), but for users in role secretRole, I'd like to see the output (here serialized as JSON):
{
"publicString": "...",
"secretString": "..."
}
And other users (either anonymous or otherwise users not acting on role secretRole) should see just:
{
"publicString": "..."
}
I know Jersey has entity filtering (and an implementation that filters based in security roles).
Unfortunately Liberty (Apache CXF based) has no such feature.
What have I done so far?
Since my solution deals primarily with JSON - using Jackson - I did some work based on Jackson's BeanSerializerModifier. Forget BeanSerializerModifier: it gets called only once per bean type (so the first user defines which properties get serialized for all other users - no, thanks).
Just found another Jackson concept that is applied each time a bean is about to be serialized: PropertyFilter and JsonFilter.
It kind of works, the implementation being very simple:
new SimpleBeanPropertyFilter() {
#Override
protected boolean include(BeanPropertyWriter writer) {
return include((PropertyWriter)writer);
}
#Override
protected boolean include(PropertyWriter writer) {
if (writer.findAnnotation(DenyAll.class) != null) {
return false;
}
RolesAllowed rolesAllowed = writer.findAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
boolean anyMatch = Arrays.stream(rolesAllowed.value())
.anyMatch(role -> securityContext.isUserInRole(role));
if (!anyMatch) {
return false;
}
}
return true;
}
}
And what's missing?
The Achilles' heel in above implementation is the securityContext reference (expecting an instance of SecurityContext).
I couldn't find means to get hold of a reference to the current security context.
Usually securityContext is #Context injected - either as a method parameter or as a field parameter. None of this is available to a BeanSerializerModifier.
I've managed to inject #Context SecurityContext (both by field or by constructor parameter); it happens to be a ThreadLocalSecurityContext in Liberty. BUT its method isUserInRole only works for the first request (when the ObjectMapper is created); then the reference gets stale and any other invocation throws NPE (inside isUserInRole method; the securityContext is still a valid java object reference; though referencing a stale object).
What are my constraints?
Jersey is not an option for me. I'm bound to Liberty (which is Apache CXF based).
I'm already used to Jackson, but it is not a must. JSON and REST are.
EDIT
HOLD ON: I thought the problem was the securityContext, but perhaps it is not the culprit. In time: I've managed to inject #Context SecurityContext (both by field or by constructor parameter); it happens to be a ThreadLocalSecurityContext, so I suppose it will get the actual principal from threadlocal storage.
BUT now I realized that BeanSerializerModifier#changeProperties gets called just once (for each bean), then the list of changed properties gets reused! I'll look closely at the Jackson specs; maybe I'll switch to JSON-B, as pointed by #Andy McCright (if its PropertyVisibilityStrategy doesn't also cache the result).
EDIT 2
Previous implementation with BeanSerializerModifier:
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
return beanProperties.stream()
.filter(property -> {
if (property.findAnnotation(DenyAll.class) != null) {
return false;
}
RolesAllowed rolesAllowed = property.findAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
boolean anyMatch = Arrays.stream(rolesAllowed.value())
.anyMatch(role -> securityContext.isUserInRole(role));
if (!anyMatch) {
return false;
}
}
return true;
})
.collect(toList());
}

I've managed to handle an instance of SecurityContext over a ThreadLocal. To this end I've implemented a ContainerRequestFilter:
static final ThreadLocal<SecurityContext> tlSecurityContext = new ThreadLocal<>();
#Provider
public static class SecurityContextSavingRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
tlSecurityContext.set(requestContext.getSecurityContext());
}
}
Then tlSecurityContext.get() can be used as the current SecurityContext.
I don't know, however, if this is invalid or otherwise not recommended by JAX-RS spec.
Beyond this I've also switched to JSON-B (from Jackson) because:
it has better integration with Liberty (both server and client JAX-RS) by means of feature jsonb-1.0;
property filtering is less verbose (than Jackson's PropertyFilter), although less powerful too.
Full solution follows (with comments):
A ContextResolver<Jsonb> to configure Jsonb:
#Provider
public class JsonbConfigContextResolver implements ContextResolver<Jsonb> {
#Override
public Jsonb getContext(Class<?> type) {
return JsonbBuilder.newBuilder().withConfig(getConfig()).build();
}
private JsonbConfig getConfig() {
return new JsonbConfig().withPropertyVisibilityStrategy(new SecurityPropertyVisibilityStrategy());
}
}
A PropertyVisibilityStrategy to implement filtering proper:
public class SecurityPropertyVisibilityStrategy implements PropertyVisibilityStrategy {
#Override
public boolean isVisible(Field field) {
return false;
}
#Override
public boolean isVisible(Method method) {
if (method.getAnnotation(DenyAll.class) != null) {
return false;
}
RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
boolean anyMatch = Arrays.stream(rolesAllowed.value())
.anyMatch(role -> isUserInRole(role));
if (!anyMatch) {
return false;
}
}
return true;
}
And finally the ThreadLocal hack itself:
private boolean isUserInRole(String role) {
return securityContext.get().isUserInRole(role);
}
private static final ThreadLocal<SecurityContext> securityContext = new ThreadLocal<>();
#Provider
public static class SecurityContextSavingRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
securityContext.set(requestContext.getSecurityContext());
}
}
}

Related

Spring webflux filter: How to get the reactor context after the query execution?

Spring boot 2.1.5
Project Reactor 3.2.9
In my webflux project I extensively use the reactor contexts in order to pass around some values.
I set up a filter and am trying to log things which are in the context and to log different things in case of error/success.
I have checked this documentation: https://projectreactor.io/docs/core/release/reference/#context
I still struggle (especially on the error side) to get it.
Basically, I have this filter:
#Component
public class MdcWebFilter implements WebFilter {
#NotNull
#Override
public Mono<Void> filter(#NotNull ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
Mono<Void> filter = webFilterChain.filter(serverWebExchange);
return filter
.doAfterSuccessOrError(new BiConsumer<Void, Throwable>() {
#Override
public void accept(Void aVoid, Throwable throwable) {
//Here i would like to be able to access to the request's context
System.out.println("doAfterSuccessOrError:" + (throwable==null ? "OK" : throwable.getMessage())+"log the context");
}
})
.doOnEach(new Consumer<Signal<Void>>() {
#Override
public void accept(Signal<Void> voidSignal) {
//Here i have the context but i don't really know if i am in success or error
System.out.println("doOnEach:"+"Log OK/KO and the exception" + voidSignal.getContext());
}
})
.subscriberContext(context -> context.put("somevar", "whatever"));
}
}
I also tried with a flatMap() and a Mono.subscriberContext() but i am not sure how to plug correctly with the filter (especially in error).
What would be the best way to achieve this ?
I'm not sure whether it possible access request reactor context from within WebFilter. WebFilter context exists in another Mono chain.
But it is do possible to assosiate attributes with request and able to fetch these attributes during request life time RequestContextHolder for Reactive Web
Very similar to Servlet API.
Controller:
#GetMapping(path = "/v1/customers/{customerId}")
public Mono<Customer> getCustomerById(
#PathVariable("customerId") String customerId,
ServerWebExchange serverWebExchange)
{
serverWebExchange.getAttributes().put("traceId", "your_trace_id");
return customerService.findById(customerId);
}
WebFilter:
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// ...
String traceId = exchange.getAttributeOrDefault("traceId", "default_value_goes_here");
//...
return chain.filter(exchange);
}
I know this is probably not the cleanest of the solutions, but you could create a container class that would keep the context between your two callbacks.
You would store the context at doOnEach and then you would be able to load it back at doAfterSuccessOrError:
public Mono<Void> filter(#NotNull ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
#lombok.Data
class MyContextContainer {
private Context context;
}
MyContextContainer container = new MyContextContainer();
Mono<Void> filter = webFilterChain.filter(serverWebExchange);
return filter
.doAfterSuccessOrError(new BiConsumer<Void, Throwable>() {
#Override
public void accept(Void aVoid, Throwable throwable) {
// load the context here
Context context = container.getContext();
// then do your stuff here
}
})
.doOnEach(new Consumer<Signal<Void>>() {
#Override
public void accept(Signal<Void> voidSignal) {
// store the context here
container.setContext(voidSignal.getContext());
}
})
.subscriberContext(context -> context.put("somevar", "whatever"));
}
It doesn't need to be a class, really. It could be an AtomicReference, but you get the idea.
Again, this might be just a workaround. I believe there must be a better way to access the context.

Custom action filter unity dependency injection web api 2

I followed this article and got everything working except dependency inject (partially). In my project I am using unity and I am trying to create a custom Transaction attribute the purpose of which is to start a NHibernate transaction before the execution of an action and commit/rollback the transaction after the method execution.
This is the definition of my attribute:-
public class TransactionAttribute : Attribute
{
}
Following is the definition of my TransactionFilter
public class TransactionFilter : IActionFilter
{
private readonly IUnitOfWork _unitOfWork;
public TransactionFilter(IUnitOfWork uow) {
_unitOfWork = uow;
}
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
var transAttribute = actionContext.ActionDescriptor.GetCustomAttributes<TransactionAttribute>().SingleOrDefault();
if (transAttribute == null) {
return continuation();
}
var transaction = uow.BeginTransaction();
return continuation().ContinueWith(t =>
{
try{
transaction.Commit();
return t.Result;
}
catch(Exception e)
{
transaction.Rollback();
return new ExceptionResult(ex, actionContext.ControllerContext.Controller as ApiController).ExecuteAsync(cancellationToken).Result;
}
}
}
}
And I have created a custom filter provider which uses unity to construct this filter.
public class UnityActionFilterProvider
: ActionDescriptorFilterProvider,
IFilterProvider
{
private readonly IUnityContainer container;
public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
{
// TODO: Determine correct FilterScope
yield return new FilterInfo(actionFilter, FilterScope.Global);
}
}
}
I register the UnityActionFilterProvider in UnityWebApiActivator (I am using Unity.AspNet.WebApi package) as follows
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityDependencyResolver(container);
var config = GlobalConfiguration.Configuration;
config.DependencyResolver = resolver;
var providers = config.Services.GetFilterProviders();
var defaultProvider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(IFilterProvider), defaultProvider);
config.Services.Add(typeof(IFilterProvider), new UnityActionFilterProvider(container));
}
The problem is everything works ok for the first request for any action but subsequent requests for the same action doesn't recreate the TransactionFilter which means it doesn't call the constructor to assign a new UOW. I don't think I can disable the action filter caching.
The only option I have got now is to use the service locator pattern and get UOW instance using container inside ExecuteActionFilterAsync which in my opinion kills the purpose of this and I am better off implementing custom ActionFilterAttribute.
Any suggestions ?
As far as I've been able to tell during the years, what happens in web application startup code essentially has Singleton lifetime. That code only runs once.
This means that there's only a single instance of each of your filters. This is good for performance, but doesn't fit your scenario.
The easiest solution to that problem, although a bit of a leaky abstraction, is to inject an Abstract Factory instead of the dependency itself:
public class TransactionFilter : IActionFilter
{
private readonly IFactory<IUnitOfWork> _unitOfWorkFactory;
public TransactionFilter(IFactory<IUnitOfWork> uowFactory) {
_unitOfWorkFactory = uowFactory;
}
// etc...
Then use the factory in the ExecuteActionFilterAsync method:
var transaction = _unitOfWorkFactory.Create().BeginTransaction();
A more elegant solution, in my opinion, would be to use a Decoraptor that Adapts the TransactionFilter, but the above answer is probably easier to understand.

Can I use both the JAX-RS and RAML extensions in Restlet in the same application?

I am preparing a ReSTful service which I would like to have documented using RAML (and perhaps Swagger as well), but it seems that I cannot implement both JAX-RS and RAML in the same application at the same time.
I have created an Application class for JAX-RS as follows:
public class Application extends javax.ws.rs.core.Application {
#Override
public Set<Class<?>> getClasses() {
// Use the reflections library to scan the current package tree for
// classes annotated with javax.ws.rs.Path and add them to the JAX-RS
// application
Reflections reflections = new Reflections(this.getClass().getPackage().getName());
return reflections.getTypesAnnotatedWith(Path.class);
}
}
I attach the JAX-RS Application object as follows:
Component component = new Component();
Server server = new Server(Protocol.HTTP, PORT);
component.getServers().add(server);
JaxRsApplication jaxRsApplication = new JaxRsApplication(component.getContext().createChildContext());
jaxRsApplication.add(new Application());
jaxRsApplication.setObjectFactory(objectFactory);
component.getDefaultHost().attach("/rest", jaxRsApplication);
And I would also like to implement the RAML extension, but it looks like it is tied to the Restlet Router and having it's own Application class. Is there a way to combine the two?
Indeed the RAML extension of Restlet isn't designed to be used within JAXRS application. That said you can define a resource that provide the RAML content based on classes ApplicationIntrospector of Restlet and RamlEmitter of RAML parser, as described below:
public class RamlResource {
private Definition definition;
#Path("/raml")
#GET
public String getRaml() {
return new RamlEmitter().dump(RamlTranslator
.getRaml(getDefinition()));
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (RamlResource.class) {
definition = ApplicationIntrospector.getDefinition(
Application.getCurrent(),
new Reference("/"), null, false);
}
}
return definition;
}
}
It's the way the RAML extension of Restlet works. You could also use such an approach for Swagger but be careful since Swagger 1.2 requires several resources (a main and several sub ones with each categories). It's not the case anymore for Swagger 2.
You can notice that there is a JAX-RS support for Swagger in the extension org.restlet.ext.swagger.
----- Edited
Perhaps can you make a try with this class that corresponds to a port of the class JaxRsApplicationSwaggerSpecificationRestlet to RAML. It's based on the class JaxRsIntrospector which seems relevant for JAX-RS application:
public class JaxRsApplicationRamlSpecificationRestlet extends Restlet {
private Application application;
private String basePath;
private Reference baseRef;
private Definition definition;
public JaxRsApplicationRamlSpecificationRestlet(Application application) {
this(null, application);
}
public JaxRsApplicationRamlSpecificationRestlet(Context context, Application application) {
super(context);
this.application = application;
}
public void attach(Router router) {
attach(router, "/api-docs");
}
public void attach(Router router, String path) {
router.attach(path, this);
router.attach(path + "/{resource}", this);
}
public Representation getApiDeclaration() {
Raml raml = RamlTranslator.getRaml(
getDefinition());
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try {
return new StringRepresentation(
mapper.writeValueAsString(raml),
MediaType.APPLICATION_YAML);
} catch (Exception ex) {
return new StringRepresentation("error");
}
}
public String getBasePath() {
return basePath;
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (JaxRsApplicationRamlSpecificationRestlet.class) {
definition = JaxRsIntrospector.getDefinition(application,
baseRef, false);
}
}
return definition;
}
#Override
public void handle(Request request, Response response) {
super.handle(request, response);
if (Method.GET.equals(request.getMethod())) {
response.setEntity(getApiDeclaration());
} else {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
}
}
public void setApiInboundRoot(Application application) {
this.application = application;
}
public void setApplication(Application application) {
this.application = application;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
// Process basepath and check validity
this.baseRef = basePath != null ? new Reference(basePath) : null;
}
}
You can use this class like this:
JaxRsApplication application
= new JaxRsApplication(component.getContext());
MyApplication app = new MyApplication();
application.add(app);
new JaxRsApplicationRamlSpecificationRestlet(app);
(...)
There is no need for a dedicated resource. Please note that this code is a bit experimental ;-) I could propose it back for a contribution for the extension raml in Restlet...
Hope it helps you,
Thierry

AutoMapper testing and dependency injection for resolvers

Im writing a test for an automapper map. One of the destination members in the map requires a value resolver, and that value resolver has service dependencies which are injected. I want to use the real implementation for the resolver (since thats part of the map im testing) but Id like to use mocks for the dependencies the resolver has.
Ofcourse I want to try to avoid using an ioc container for in my tests, but how do I easily resolve my value resolver's dependencies without one?
This is my rather simplified example, in the real case there are several resolvers with sometimes many dependencies, and I really dont like to basically implement my own dependency resolver in my tests. Should I use a lightweight ioc container?
[TestFixture]
public class MapperTest
{
private IMyService myService;
[SetUp]
public void Setup()
{
Mapper.Initialize(config =>
{
config.ConstructServicesUsing(Resolve);
config.AddProfile<MyProfile>();
});
}
public T Resolve<T>()
{
return (T) Resolve(typeof (T));
}
public object Resolve(Type type)
{
if (type == typeof(MyValueResolver))
return new MyValueResolver(Resolve<IMyService>());
if (type == typeof(IMyService))
return myService;
Assert.Fail("Can not resolve type " + type.AssemblyQualifiedName);
return null;
}
[Test]
public void ShouldConfigureCorrectly()
{
Mapper.AssertConfigurationIsValid();
}
[Test]
public void ShouldMapStuff()
{
var source = new Source() {...};
var child = new Child();
myService = MockRepository.GenerateMock<IMyService>();
myService .Stub(x => x.DoServiceStuff(source)).Return(child);
var result = Mapper.Map<ISource, Destination>(source);
result.Should().Not.Be.Null();
result.Child.Should().Be.SameInstanceAs(child);
}
}
public class MyProfile : Profile
{
protected override void Configure()
{
base.Configure();
CreateMap<ISource, Destination>()
.ForMember(m => m.Child, c => c.ResolveUsing<MyResolver>());
}
}
public class MyResolver: ValueResolver<ISource, Destination>
{
private readonly IMyService _myService;
public MyResolver(IMyService myService)
{
_myService = myService;
}
protected override Child ResolveCore(ISource source)
{
return _myService.DoServiceStuff(source);
}
}
}
Here's one solution, but basically its what iv done already:
http://groups.google.com/group/automapper-users/browse_thread/thread/aea8bbe32b1f590a/f3185d30322d8109
The suggestion is to use a service locator which are set up differently depending on test or real implementation.

Ninject, Generic Referential Bindings

I think this falls under the concept of contextual binding, but the Ninject documentation, while very thorough, does not have any examples close enough to my current situation for me to really be certain. I'm still pretty confused.
I basically have classes that represent parameter structures for queries. For instance..
class CurrentUser {
string Email { get; set; }
}
And then an interface that represents its database retrieval (in the data layer)
class CurrentUserQuery : IQueryFor<CurrentUser> {
public CurrentUserQuery(ISession session) {
this.session = session;
}
public Member ExecuteQuery(CurrentUser parameters) {
var member = session.Query<Member>().Where(n => n.Email == CurrentUser.Email);
// validation logic
return member;
}
}
Now then, what I want to do is to establish a simple class that can take a given object and from it get the IQueryFor<T> class, construct it from my Ninject.IKernel (constructor parameter), and perform the ExecuteQuery method on it, passing through the given object.
The only way I have been able to do this was to basically do the following...
Bind<IQueryFor<CurrentUser>>().To<CurrentUserQuery>();
This solves the problem for that one query. But I anticipate there will be a great number of queries... so this method will become not only tedious, but also very prone to redundancy.
I was wondering if there is an inherit way in Ninject to incorporate this kind of behavior.
:-
In the end, my (ideal) way of using this would be ...
class HomeController : Controller {
public HomeController(ITransit transit) {
// injection of the transit service
}
public ActionResult CurrentMember() {
var member = transit.Send(new CurrentUser{ Email = User.Identity.Name });
}
}
Obviously that's not going to work right, since the Send method has no way of knowing the return type.
I've been dissecting Rhino Service Bus extensively and project Alexandria to try and make my light, light, lightweight implementation.
Update
I have been able to get a fairly desired result using .NET 4.0 dynamic objects, such as the following...
dynamic Send<T>(object message);
And then declaring my interface...
public interface IQueryFor<T,K>
{
K Execute(T message);
}
And then its use ...
public class TestCurrentMember
{
public string Email { get; set; }
}
public class TestCurrentMemberQuery : IConsumerFor<TestCurrentMember, Member>
{
private readonly ISession session;
public TestCurrentMemberQuery(ISession session) {
this.session = session;
}
public Member Execute(TestCurrentMember user)
{
// query the session for the current member
var member = session.Query<Member>()
.Where(n => n.Email == user.Email).SingleOrDefault();
return member;
}
}
And then in my Controller...
var member = Transit.Send<TestCurrentMemberQuery>(
new TestCurrentMember {
Email = User.Identity.Name
}
);
effectively using the <T> as my 'Hey, This is what implements the query parameters!'. It does work, but I feel pretty uncomfortable with it. Is this an inappropriate use of the dynamic function of .NET 4.0? Or is this more the reason why it exists in the first place?
Update (2)
For the sake of consistency and keeping this post relative to just the initial question, I'm opening up a different question for the dynamic issue.
Yes, you should be able to handle this with Ninject Conventions. I am just learning the Conventions part of Ninject, and the documentation is sparse; however, the source code for the Conventions extension is quite light and easy to read/navigate, also Remo Gloor is very helpful both here and on the mailing list.
The first thing I would try is a GenericBindingGenerator (changing the filters and scope as needed for your application):
internal class YourModule : NinjectModule
{
public override void Load()
{
Kernel.Scan(a => {
a.From(System.Reflection.Assembly.GetExecutingAssembly());
a.InTransientScope();
a.BindWith(new GenericBindingGenerator(typeof(IQueryFor<>)));
});
}
}
The heart of any BindingGenerator is this interface:
public interface IBindingGenerator
{
void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel);
}
The Default Binding Generator simply checks if the name of the class matches the name of the interface:
public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)
{
if (!type.IsInterface && !type.IsAbstract)
{
Type service = type.GetInterface("I" + type.Name, false);
if (service != null)
{
kernel.Bind(service).To(type).InScope(scopeCallback);
}
}
}
The GenericBindingGenerator takes a type as a constructor argument, and checks interfaces on classes scanned to see if the Generic definitions of those interfaces match the type passed into the constructor:
public GenericBindingGenerator(Type contractType)
{
if (!contractType.IsGenericType && !contractType.ContainsGenericParameters)
{
throw new ArgumentException("The contract must be an open generic type.", "contractType");
}
this._contractType = contractType;
}
public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)
{
Type service = this.ResolveClosingInterface(type);
if (service != null)
{
kernel.Bind(service).To(type).InScope(scopeCallback);
}
}
public Type ResolveClosingInterface(Type targetType)
{
if (!targetType.IsInterface && !targetType.IsAbstract)
{
do
{
foreach (Type type in targetType.GetInterfaces())
{
if (type.IsGenericType && (type.GetGenericTypeDefinition() == this._contractType))
{
return type;
}
}
targetType = targetType.BaseType;
}
while (targetType != TypeOfObject);
}
return null;
}
So, when the Conventions extension scans the class CurrentUserQuery it will see the interface IQueryFor<CurrentUser>. The generic definition of that interface is IQueryFor<>, so it will match and that type should get registered for that interface.
Lastly, there is a RegexBindingGenerator. It tries to match interfaces of the classes scanned to a Regex given as a constructor argument. If you want to see the details of how that operates, you should be able to peruse the source code for it now.
Also, you should be able to write any implementation of IBindingGenerator that you may need, as the contract is quite simple.