On 12/4/2015 5:36 AM, Marek Posolda wrote:
Why it's bad to do simpler things? :-)
AFAIK filter pattern (or interceptor/chain whatever you call it) is
proven to work in many places. The provider at level X can always decide
if it delegates call to method "getUserByXXX" to next provider (and then
proxy/cache or do whatever according to his logic) or return something
by itself.
I'm also trying to figure out something that is backward compatible with
the current federation SPI
If I understand correctly your proposal, it requires
UserFederationProvider to decide, if it wants to import or just return
InMemoryUserModel . So if we want to support in-memory for LDAP, we will
need to have 2 versions of LDAPFederationProvider (current which imports
into userStorage() and another, which will return InMemoryUserModel
instances ). That's not ideal IMO.
As I mentioned before, there are also 2 additional usecases, which are
important to support IMO:
1) Case when admin changes some user attributes directly in LDAP and he
wants the LDAP data to be immediately visible in Keycloak. This is what
we currently support (see
FederationProvidersIntegrationTest.testDirectLDAPUpdate() ). Maybe I am
missing something with your proposal, but if we hardcode CacheProvider
to be always first, we lost this.
That's what I was afraid of with my proposal. You need to have a proxy
in front of the cached UserModel to load certain attrbutes on-demand.
You would need type of proxy callbacks to the Federation Provider. One
proxy for a cached object and one for writes. Following me?
Currently thats how we do it. If a user has been imported and cached,
we proxy it after it is pulled from cache.
Then assume the session.users().getUserByUsername is called:
1) First delegate is UserFederationManager, so calling
UserFederationManager.getUserByUsername
2) This line
https://github.com/keycloak/keycloak/blob/master/model/api/src/main/java/...
will call getNext().getUserByUsername() and returns null as the user was
not yet looked for this request.
3) Going to federationProviders and call
LDAPFederationProvider.getUserByUsername
4) LDAPFederationProvider query user in LDAP and calls
importUserFromLDAP . This calls session.userStorage().addUser, which
will put user into in-memory provider (I assume that
session.userStorage() will be kept and will always point to the next
delegate after UserFederationManager ). The LDAPFederationProvider will
then return LDAP proxy of UserModel.
I don't see how your proposal can work. As each chain is potentially
different per user and you don't know what the chain is until you locate
the user. Local keycloak would be cache=>JPA-UserModel. One fed
provider might be cache=>In-Memory=>LDAP
--
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com