public class DbCachingRemoteDirectory extends AbstractForwardingDirectory implements RemoteDirectory, SynchronisableDirectory, FastEntityCountProvider, MultiValuesQueriesSupport
RemoteDirectory
that provides LDAP and Crowd integration plus local storage in an internal directory
for LDAP user and group attributes, and local groups for LDAP and Crowd users with local caching of remote data.
The implementation delegates to an Remote directory for the "source of truth" and an internal directory for caching
and some special local storage.
All the attributes for the directory itself (e.g. base DN, other configuration options) are stored on the directory instance.
Terminology used in this class:
Constructor and Description |
---|
DbCachingRemoteDirectory(RemoteDirectory remoteDirectory,
InternalRemoteDirectory internalDirectory,
DirectoryCacheFactory directoryCacheFactory,
CacheRefresherFactory cacheRefresherFactory,
AuditService auditService,
AuditLogUserMapper auditLogUserMapper,
String directoryName,
com.atlassian.event.api.EventPublisher eventPublisher,
DirectoryDao directoryDao,
BatchConfigParser batchConfigParser) |
Modifier and Type | Method and Description |
---|---|
Group |
addGroup(GroupTemplate group)
Adds a
group to the directory store. |
void |
addGroupToGroup(String childGroup,
String parentGroup)
Adds a group as a member of a parent group.
|
UserWithAttributes |
addUser(UserTemplateWithAttributes user,
PasswordCredential credential)
Adds a
user to the directory store. |
void |
addUserToGroup(String username,
String groupName)
Adds a user as a member of a group.
|
User |
authenticate(String name,
PasswordCredential credential)
Authenticates a
user with the directory store. |
protected User |
authenticateAndUpdateInternalUser(String name,
PasswordCredential credential)
Authenticates user and ensures that internal directory contains the
authenticated user.
|
protected void |
checkIfUserCanBeUpdatedWithCurrentGroupFiltering(String username,
Set<String> userRemoteGroupNames) |
void |
expireAllPasswords()
Sets the
UserConstants.REQUIRES_PASSWORD_CHANGE attribute to true for
all users in the directory using bulk operations |
RemoteDirectory |
getAuthoritativeDirectory() |
protected InternalRemoteDirectory |
getDelegate() |
String |
getDescriptiveName()
Returns a descriptive name for the type of directory.
|
long |
getDirectoryId()
Gets the internal unique
directoryId of the directory store. |
long |
getGroupCount() |
Set<String> |
getKeys()
Gets all the keys of the attributes.
|
long |
getUserCount() |
String |
getValue(String name)
Returns any value associated with the given key, returns
null if there is no value. |
Set<String> |
getValues(String name)
Get all the values associated with a given key.
|
boolean |
isEmpty() |
boolean |
isIncrementalSyncEnabled()
Gets the preferred synchronisation mode for this remote directory.
|
boolean |
isRolesDisabled()
Expose whether the directory has roles disabled.
|
void |
removeGroup(String name)
Removes the
group that matches the supplied name . |
void |
removeGroupAttributes(String groupName,
String attributeName)
Removes all the values for a single attribute key for a group.
|
void |
removeGroupFromGroup(String childGroup,
String parentGroup)
Removes a group as a member of a parent group.
|
void |
removeUser(String name)
Removes the
user that matches the supplied name . |
void |
removeUserAttributes(String username,
String attributeName)
Removes all the values for a single attribute key for a user.
|
void |
removeUserFromGroup(String username,
String groupName)
Removes a user as a member of a group.
|
Group |
renameGroup(String oldName,
String newName)
Renames a
group . |
User |
renameUser(String oldName,
String newName)
Renames a
user . |
<T> com.google.common.collect.ListMultimap<String,T> |
searchGroupRelationshipsGroupedByName(MembershipQuery<T> query)
Searches for
groups that match the supplied query criteria. |
void |
setAttributes(Map<String,String> attributes)
When a directory store is loaded, the attributes map will be
set by the Crowd framework.
|
void |
setDirectoryId(long directoryId)
When a directory store is loaded, the
directoryId will be set by the
crowd framework. |
protected boolean |
shouldSyncGroupMembershipAfterUserAuthentication(boolean isNewUser) |
void |
storeGroupAttributes(String groupName,
Map<String,Set<String>> attributes)
Adds or updates a group's attributes with the new Map of attribute values in the directory specified by the passed in
directoryId . |
void |
storeUserAttributes(String username,
Map<String,Set<String>> attributes)
Adds or updates a user's attributes with the new Map of attribute values in the directory specified by the passed in
directoryId . |
boolean |
supportsInactiveAccounts()
This implementation will store the active flag locally in the internal directory if local user status is enabled
and if the active flag cannot be persisted on the underlying remote directory.
|
boolean |
supportsNestedGroups()
Allows us to only display nested-group related UI for directories that support it.
|
boolean |
supportsPasswordExpiration()
Return true if this directory supports manually expiring passwords.
|
boolean |
supportsSettingEncryptedCredential()
If this method returns true, then calling
RemoteDirectory.updateUserCredential(String, PasswordCredential) or
RemoteDirectory.addUser(com.atlassian.crowd.model.user.UserTemplate, com.atlassian.crowd.embedded.api.PasswordCredential)
with a PasswordCredential instance where PasswordCredential.isEncryptedCredential() returns true
and the instance is not equal to PasswordCredential.NONE will succeed; otherwise, it will fail. |
void |
synchroniseCache(SynchronisationMode mode,
SynchronisationStatusManager synchronisationStatusManager)
Requests that this directory should update its cache by synchronising with the remote data.
|
void |
testConnection()
Test if a connection to the directory server can be established.
|
Group |
updateGroup(GroupTemplate group)
Updates the
group . |
protected void |
updateGroupsMembershipOnLogin(User user,
Set<String> userRemoteGroupNames) |
User |
updateUser(UserTemplate user)
Updates the
user . |
protected User |
updateUserAndSetActiveFlag(User remoteUser,
User internalUser) |
void |
updateUserCredential(String username,
PasswordCredential credential)
|
User |
updateUserFromRemoteDirectory(User remoteUser) |
User |
userAuthenticated(String username) |
addUser, countDirectMembersOfGroup, findGroupByName, findGroupWithAttributesByName, findUserByExternalId, findUserByName, findUserWithAttributesByName, getMemberships, getUserAvatarByName, isGroupDirectGroupMember, isUserDirectGroupMember, searchGroupRelationships, searchGroups, searchUsers
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
addUser, countDirectMembersOfGroup, findGroupByName, findGroupWithAttributesByName, findUserByExternalId, findUserByName, findUserWithAttributesByName, getLocallyFilteredGroupNames, getMemberships, getUserAvatarByName, isGroupDirectGroupMember, isUserDirectGroupMember, searchGroupRelationships, searchGroups, searchUsers
searchGroupRelationships
public DbCachingRemoteDirectory(RemoteDirectory remoteDirectory, InternalRemoteDirectory internalDirectory, DirectoryCacheFactory directoryCacheFactory, CacheRefresherFactory cacheRefresherFactory, AuditService auditService, AuditLogUserMapper auditLogUserMapper, String directoryName, com.atlassian.event.api.EventPublisher eventPublisher, DirectoryDao directoryDao, BatchConfigParser batchConfigParser)
public long getDirectoryId()
RemoteDirectory
directoryId
of the directory store.getDirectoryId
in interface RemoteDirectory
getDirectoryId
in class AbstractForwardingDirectory
directoryId
.public void setDirectoryId(long directoryId)
RemoteDirectory
directoryId
will be set by the
crowd framework.setDirectoryId
in interface RemoteDirectory
setDirectoryId
in class AbstractForwardingDirectory
directoryId
- The unique directoryId
of the DirectoryImpl
stored in the database.public String getDescriptiveName()
RemoteDirectory
getDescriptiveName
in interface RemoteDirectory
getDescriptiveName
in class AbstractForwardingDirectory
public void setAttributes(Map<String,String> attributes)
RemoteDirectory
The Map is immutable and implementations are required to maintain immutability.
setAttributes
in interface RemoteDirectory
setAttributes
in class AbstractForwardingDirectory
attributes
- attributes map.public User authenticate(String name, PasswordCredential credential) throws UserNotFoundException, InactiveAccountException, InvalidAuthenticationException, ExpiredCredentialException, OperationFailedException
RemoteDirectory
user
with the directory store.authenticate
in interface RemoteDirectory
authenticate
in class AbstractForwardingDirectory
name
- The name of the user (username).credential
- The supplied credentials (password).UserNotFoundException
- The user with the supplied name does not exist.InactiveAccountException
- The supplied user is inactive.InvalidAuthenticationException
- Authentication with the provided credentials failed.ExpiredCredentialException
- The user's credentials have expired. The user must change their credentials in order to successfully authenticate.OperationFailedException
- underlying directory implementation failed to execute the operation.protected User authenticateAndUpdateInternalUser(String name, PasswordCredential credential) throws UserNotFoundException, InactiveAccountException, InvalidAuthenticationException, ExpiredCredentialException, OperationFailedException
Updates user data (including groups membership) if the user exists in the internal directory. Renames user if necessary. If user does not exists tries to add the user and the user's memberships in the internal directory.
User might not exist in the internal directory yet because the user was added after the latest synchronisation. This happens for example when the remote directory uses delegated authentication, and creates users on successful authentication.
name
- of the usercredential
- credential of the userUserNotFoundException
- if the user does not existExpiredCredentialException
- if the password has expired and the user is required to change their passwordInactiveAccountException
- if the user account is not activeInvalidAuthenticationException
- if the user name/password combination is invalidOperationFailedException
- if the operation failed for any other reasonpublic User updateUserFromRemoteDirectory(@Nonnull User remoteUser) throws OperationFailedException, UserNotFoundException
updateUserFromRemoteDirectory
in interface RemoteDirectory
updateUserFromRemoteDirectory
in class AbstractForwardingDirectory
OperationFailedException
UserNotFoundException
public User userAuthenticated(String username) throws OperationFailedException, UserNotFoundException, InactiveAccountException
userAuthenticated
in interface RemoteDirectory
OperationFailedException
UserNotFoundException
InactiveAccountException
protected void checkIfUserCanBeUpdatedWithCurrentGroupFiltering(String username, Set<String> userRemoteGroupNames) throws OperationFailedException, UserNotFoundException
protected User updateUserAndSetActiveFlag(User remoteUser, User internalUser) throws UserNotFoundException, InvalidUserException, OperationFailedException
protected void updateGroupsMembershipOnLogin(User user, Set<String> userRemoteGroupNames) throws OperationFailedException, UserNotFoundException
public UserWithAttributes addUser(UserTemplateWithAttributes user, PasswordCredential credential) throws InvalidUserException, InvalidCredentialException, UserAlreadyExistsException, OperationFailedException
RemoteDirectory
user
to the directory store.addUser
in interface RemoteDirectory
addUser
in class AbstractForwardingDirectory
user
- template of the user to add.credential
- a password, or PasswordCredential.NONE
for an account that cannot login with any passwordInvalidUserException
- The supplied user is invalid.InvalidCredentialException
- The supplied credential is invalid.UserAlreadyExistsException
- The user already existsOperationFailedException
- underlying directory implementation failed to execute the operation.RemoteDirectory.supportsSettingEncryptedCredential()
public User updateUser(UserTemplate user) throws InvalidUserException, UserNotFoundException, OperationFailedException
RemoteDirectory
user
.updateUser
in interface RemoteDirectory
updateUser
in class AbstractForwardingDirectory
user
- The user to update.InvalidUserException
- the supplied user is invalid.UserNotFoundException
- the user does not exist in the directory store.OperationFailedException
- underlying directory implementation failed to execute the operation.public void updateUserCredential(String username, PasswordCredential credential) throws UserNotFoundException, InvalidCredentialException, OperationFailedException
RemoteDirectory
updateUserCredential
in interface RemoteDirectory
updateUserCredential
in class AbstractForwardingDirectory
username
- The name of the user (username).credential
- The new credential (password).UserNotFoundException
- The user does not exist.InvalidCredentialException
- The supplied credential is invalid.OperationFailedException
- underlying directory implementation failed to execute the operation.RemoteDirectory.supportsSettingEncryptedCredential()
public User renameUser(String oldName, String newName) throws UserNotFoundException, InvalidUserException, OperationFailedException, UserAlreadyExistsException
RemoteDirectory
user
.renameUser
in interface RemoteDirectory
renameUser
in class AbstractForwardingDirectory
oldName
- name of existing user.newName
- desired name of user.UserNotFoundException
- if the user with the existing name does not exist.InvalidUserException
- if the new username is invalid.OperationFailedException
- if the underlying directory implementation failed to execute the operation.UserAlreadyExistsException
- if the newName already exists.public void storeUserAttributes(String username, Map<String,Set<String>> attributes) throws UserNotFoundException, OperationFailedException
RemoteDirectory
directoryId
.
The attributes map represents new or updated attributes and does not replace existing attributes unless the key of an attribute matches the key of an existing
Attributes with values of empty sets are not added (these attributes are effectively removed).
storeUserAttributes
in interface RemoteDirectory
storeUserAttributes
in class AbstractForwardingDirectory
username
- name of user to update.attributes
- new or updated attributes (attributes that don't need changing should not appear in this Map).UserNotFoundException
- user with supplied username does not exist.OperationFailedException
- underlying directory implementation failed to execute the operation.public void removeUserAttributes(String username, String attributeName) throws UserNotFoundException, OperationFailedException
RemoteDirectory
removeUserAttributes
in interface RemoteDirectory
removeUserAttributes
in class AbstractForwardingDirectory
username
- name of the user to update.attributeName
- name of attribute to remove.UserNotFoundException
- user with supplied username does not exist.OperationFailedException
- underlying directory implementation failed to execute the operation.public void removeUser(String name) throws UserNotFoundException, OperationFailedException
RemoteDirectory
user
that matches the supplied name
.removeUser
in interface RemoteDirectory
removeUser
in class AbstractForwardingDirectory
name
- The name of the user (username).UserNotFoundException
- The user does not exist.OperationFailedException
- underlying directory implementation failed to execute the operation.public Group addGroup(GroupTemplate group) throws InvalidGroupException, OperationFailedException
RemoteDirectory
group
to the directory store.addGroup
in interface RemoteDirectory
addGroup
in class AbstractForwardingDirectory
group
- template of the group to add.InvalidGroupException
- The supplied group is invalid or it already exists in the directory.OperationFailedException
- underlying directory implementation failed to execute the operation.public Group updateGroup(GroupTemplate group) throws InvalidGroupException, GroupNotFoundException, OperationFailedException, ReadOnlyGroupException
RemoteDirectory
group
.updateGroup
in interface RemoteDirectory
updateGroup
in class AbstractForwardingDirectory
group
- The group to update.InvalidGroupException
- the supplied group is invalid.GroupNotFoundException
- the group does not exist in the directory store.OperationFailedException
- underlying directory implementation failed to execute the operation.ReadOnlyGroupException
- the group is read-onlypublic Group renameGroup(String oldName, String newName) throws GroupNotFoundException, InvalidGroupException
RemoteDirectory
group
.renameGroup
in interface RemoteDirectory
renameGroup
in class AbstractForwardingDirectory
oldName
- name of existing group.newName
- desired name of group.GroupNotFoundException
- if the group with the existing name does not exist.InvalidGroupException
- if the new group name is invalid or already exists in the directory.public void storeGroupAttributes(String groupName, Map<String,Set<String>> attributes) throws GroupNotFoundException, OperationFailedException
RemoteDirectory
directoryId
.
The attributes map represents new or updated attributes and does not replace existing attributes unless the key of an attribute matches the key of an existing
Attributes with values of empty sets are not added (these attributes are effectively removed).
storeGroupAttributes
in interface RemoteDirectory
storeGroupAttributes
in class AbstractForwardingDirectory
groupName
- name of group to update.attributes
- new or updated attributes (attributes that don't need changing should not appear in this Map).GroupNotFoundException
- group with supplied groupName does not exist.OperationFailedException
- underlying directory implementation failed to execute the operation.public void removeGroupAttributes(String groupName, String attributeName) throws GroupNotFoundException, OperationFailedException
RemoteDirectory
removeGroupAttributes
in interface RemoteDirectory
removeGroupAttributes
in class AbstractForwardingDirectory
groupName
- name of the group to update.attributeName
- name of attribute to remove.GroupNotFoundException
- group with supplied groupName does not exist.OperationFailedException
- underlying directory implementation failed to execute the operation.public void removeGroup(String name) throws GroupNotFoundException, OperationFailedException, ReadOnlyGroupException
RemoteDirectory
group
that matches the supplied name
.removeGroup
in interface RemoteDirectory
removeGroup
in class AbstractForwardingDirectory
name
- The name of the group.GroupNotFoundException
- The group does not exist.OperationFailedException
- underlying directory implementation failed to execute the operation.ReadOnlyGroupException
- if the group is read-only and not allowed to be deleted.public void addUserToGroup(String username, String groupName) throws GroupNotFoundException, UserNotFoundException, OperationFailedException, ReadOnlyGroupException, MembershipAlreadyExistsException
RemoteDirectory
childGroup
will
appear as members of parentGroup
to querying applications.addUserToGroup
in interface RemoteDirectory
addUserToGroup
in class AbstractForwardingDirectory
username
- The user that will become a member of groupName
groupName
- The group that will gain a new member.GroupNotFoundException
- If the group cannot be found.UserNotFoundException
- If the user cannot be found.OperationFailedException
- underlying directory implementation failed to execute the operation.ReadOnlyGroupException
- If the group is read-onlyMembershipAlreadyExistsException
- if the user is already a member of the grouppublic void addGroupToGroup(String childGroup, String parentGroup) throws GroupNotFoundException, InvalidMembershipException, OperationFailedException, ReadOnlyGroupException, MembershipAlreadyExistsException
RemoteDirectory
addGroupToGroup
in interface RemoteDirectory
addGroupToGroup
in class AbstractForwardingDirectory
childGroup
- The group that will become a member of parentGroup
parentGroup
- The group that will gain a new memberGroupNotFoundException
- One or both of the groups cannot be found.InvalidMembershipException
- if the childGroup and parentGroup exist but are of different GroupTypes.OperationFailedException
- underlying directory implementation failed to execute the operation.ReadOnlyGroupException
- if either of the groups are read-onlyMembershipAlreadyExistsException
- if the child group is already a child of the parent grouppublic void removeUserFromGroup(String username, String groupName) throws GroupNotFoundException, UserNotFoundException, MembershipNotFoundException, OperationFailedException, ReadOnlyGroupException
RemoteDirectory
removeUserFromGroup
in interface RemoteDirectory
removeUserFromGroup
in class AbstractForwardingDirectory
username
- The user that will be removed from parentGroup
groupName
- The group that will lose the member.GroupNotFoundException
- If the group cannot be found.UserNotFoundException
- If the user cannot be found.MembershipNotFoundException
- if the user is not a direct member of the group.OperationFailedException
- underlying directory implementation failed to execute the operation.ReadOnlyGroupException
- if the group is read-onlypublic void removeGroupFromGroup(String childGroup, String parentGroup) throws GroupNotFoundException, InvalidMembershipException, MembershipNotFoundException, OperationFailedException, ReadOnlyGroupException
RemoteDirectory
removeGroupFromGroup
in interface RemoteDirectory
removeGroupFromGroup
in class AbstractForwardingDirectory
childGroup
- The group that will be removed from parentGroup
parentGroup
- The group that will lose the member.GroupNotFoundException
- One or both of the groups cannot be found.InvalidMembershipException
- if the childGroup and parentGroup exist but are of different GroupTypes.MembershipNotFoundException
- if the childGroup is not a direct member of the parentGroup.OperationFailedException
- underlying directory implementation failed to execute the operation.ReadOnlyGroupException
- if the groups are read-onlypublic void testConnection() throws OperationFailedException
RemoteDirectory
testConnection
in interface RemoteDirectory
testConnection
in class AbstractForwardingDirectory
OperationFailedException
- underlying directory implementation failed to execute the operation.public boolean supportsInactiveAccounts()
supportsInactiveAccounts
in interface RemoteDirectory
supportsInactiveAccounts
in class AbstractForwardingDirectory
public boolean supportsNestedGroups()
RemoteDirectory
supportsNestedGroups
in interface RemoteDirectory
supportsNestedGroups
in class AbstractForwardingDirectory
public boolean supportsPasswordExpiration()
RemoteDirectory
supportsPasswordExpiration
in interface RemoteDirectory
supportsPasswordExpiration
in class AbstractForwardingDirectory
public boolean supportsSettingEncryptedCredential()
RemoteDirectory
RemoteDirectory.updateUserCredential(String, PasswordCredential)
or
RemoteDirectory.addUser(com.atlassian.crowd.model.user.UserTemplate, com.atlassian.crowd.embedded.api.PasswordCredential)
with a PasswordCredential
instance where PasswordCredential.isEncryptedCredential()
returns true
and the instance is not equal to PasswordCredential.NONE
will succeed; otherwise, it will fail.supportsSettingEncryptedCredential
in interface RemoteDirectory
supportsSettingEncryptedCredential
in class AbstractForwardingDirectory
public boolean isRolesDisabled()
RemoteDirectory
isRolesDisabled
in interface RemoteDirectory
isRolesDisabled
in class AbstractForwardingDirectory
protected boolean shouldSyncGroupMembershipAfterUserAuthentication(boolean isNewUser)
isNewUser
- true if the user was created during authentication (ie. wasn't synced yet, and was created during this authentication)SynchronisableDirectoryProperties.SYNC_GROUP_MEMBERSHIP_AFTER_SUCCESSFUL_USER_AUTH_ENABLED
public Set<String> getValues(String name)
Attributes
getValues
in interface Attributes
getValues
in class AbstractForwardingDirectory
name
- the key to retrieve the values forpublic String getValue(String name)
Attributes
null
if there is no value.getValue
in interface Attributes
getValue
in class AbstractForwardingDirectory
name
- the key to retrieve the value fornull
if there is no valuepublic boolean isEmpty()
isEmpty
in interface Attributes
isEmpty
in class AbstractForwardingDirectory
true
if there are no attributespublic Set<String> getKeys()
Attributes
getKeys
in interface Attributes
getKeys
in class AbstractForwardingDirectory
public boolean isIncrementalSyncEnabled()
SynchronisableDirectory
Gets the preferred synchronisation mode for this remote directory.
Note: some directory implementation don't support incremental sync and will ignore this preference.
isIncrementalSyncEnabled
in interface SynchronisableDirectory
true
if incremental sync is preferred.public void synchroniseCache(SynchronisationMode mode, SynchronisationStatusManager synchronisationStatusManager) throws OperationFailedException
SynchronisableDirectory
synchroniseCache
in interface SynchronisableDirectory
mode
- synchronisation modesynchronisationStatusManager
- listener for synchronisation status change notificationsOperationFailedException
- underlying directory implementation failed to execute the operation.public RemoteDirectory getAuthoritativeDirectory()
getAuthoritativeDirectory
in interface RemoteDirectory
getAuthoritativeDirectory
in class AbstractForwardingDirectory
public void expireAllPasswords() throws OperationFailedException
RemoteDirectory
UserConstants.REQUIRES_PASSWORD_CHANGE
attribute to true for
all users in the directory using bulk operationsexpireAllPasswords
in interface RemoteDirectory
expireAllPasswords
in class AbstractForwardingDirectory
OperationFailedException
public long getUserCount() throws OperationFailedException
getUserCount
in interface FastEntityCountProvider
OperationFailedException
- underlying directory implementation failed to execute the operation.public long getGroupCount() throws OperationFailedException
getGroupCount
in interface FastEntityCountProvider
OperationFailedException
- underlying directory implementation failed to execute the operation.protected InternalRemoteDirectory getDelegate()
getDelegate
in class AbstractForwardingDirectory
public <T> com.google.common.collect.ListMultimap<String,T> searchGroupRelationshipsGroupedByName(MembershipQuery<T> query)
MultiValuesQueriesSupport
groups
that match the supplied query criteria.
This method is similar to MultiValuesQueriesSupport.searchGroupRelationships(MembershipQuery)
, but it additionally groups results
by elements of MembershipQuery.getEntityNamesToMatch()
.
searchGroupRelationshipsGroupedByName
in interface MultiValuesQueriesSupport
query
- EntityQuery for Entity.GROUP.ListMultimap<String, Group>
or ListMultimap<String, String>
of groups/groupnames
matching the search criteria, grouped by MembershipQuery.getEntityNamesToMatch()
.
Results are ordered by entity name, case-insensitive.
An empty ListMultimap
will be returned if no groups matching the criteria are found.Copyright © 2021 Atlassian. All rights reserved.