Skip to content

Instantly share code, notes, and snippets.

@dularion
Created August 27, 2017 13:18
Show Gist options
  • Save dularion/c4b4fd9970bd6856766e3fd62561aa9f to your computer and use it in GitHub Desktop.
Save dularion/c4b4fd9970bd6856766e3fd62561aa9f to your computer and use it in GitHub Desktop.
package project
import grails.converters.JSON
import grails.plugin.springsecurity.SpringSecurityUtils
import grails.plugin.springsecurity.userdetails.GrailsUser
import grails.plugin.springsecurity.userdetails.GrailsUserDetailsService
import grails.plugin.springsecurity.userdetails.NoStackUsernameNotFoundException
import grails.transaction.Transactional
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.grails.web.json.JSONObject
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException
class DaoLdapUserDetailsService implements GrailsUserDetailsService {
LdapConnectionService ldapConnectionService
protected final Log logger = LogFactory.getLog(getClass());
private static ldapAccountEnabled = true
/**
* Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least
* one role, so we give a user with no granted roles this one which gets
* past that restriction but doesn't grant anything.
*/
static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
UserDetails loadUserByUsername(String username, boolean loadRoles)
throws UsernameNotFoundException {
return loadUserByUsername(username)
}
@Transactional
def updateUserInfo(User user, ldapUser) {
user.nameShort = ldapUser['shortname']
//etc
user.save(failOnError: true, flush: true)
logger.debug('updateUserInfo ' + user.nameShort)
UserInfo userInfo = UserInfo.findByUser(user)
if (!userInfo) {
return
}
user.nameLast = ldapUser['sn']
user.importedId = ldapUser['uidNumber']
user.nameShort = ldapUser['Nutzerkuerzel']
if (user.nameLast != ldapUser['givenName']) {
user.nameFirst = ldapUser['givenName']
}
user.enabled = !user.defaultTenant.deleted
user.deleted = user.defaultTenant.deleted
user.save(flush: true, failOnError: true)
userInfo.metaData = (ldapUser as JSON).toString()
userInfo.save(failOnError: true, flush: true)
}
@Transactional
/**
* fetchTenantsFromLdap
* @return results.tenants List<Tenant>
* @return results.default Tenant
*
*/
Map fetchTenantsFromLdap(ldapUser) {
def result = [:]
result.tenants = []
def ldapRights = ldapUser['Berechtigungen']?.split(',')
// logger.debug('berechtigung ' + ldapRights)
Tenant defaultTenant
ldapRights.each {
if (it.isNumber()) {
Tenant tenant = Tenant.findByExternalId(it)
if (tenant) {
result.tenants.push(tenant)
} else {
logger.error('TENANT not found by externalId for ldapRights it !!' + it)
}
} else {
def tenantId = it.toString().replace('!', '')
if (tenantId.isNumber()) {
result.default = Tenant.findByExternalId(tenantId)
result.tenants.push(result.default)
}
}
}
if (!result.default && result.tenants.size() > 0) {
result.default = result.tenants[0]
}
if (!result.default) {
logger.warn('no tenants found by Berechtigungen user: ' + ldapUser.uid + ' ldapRights: ' + ldapRights
+ ' fallback to LDAP DN')
}
if (!result.default) {
def msg = 'No tenant for user:' + ldapUser.uid + ' ldapRights: ' + ldapRights
logger.error(msg)
throw new Exception(msg)
}
result.tenants = result.tenants.unique()
return result
}
@Transactional
User createUserFromLdap(ldapUser) {
logger.debug('createUserFromLdap ' + ldapUser)
def tenantResult = fetchTenantsFromLdap(ldapUser)
User user = new User(ldapUser.uid, UUID.randomUUID().toString())
user.nameLast = ldapUser['sn']
user.importedId = ldapUser['uidNumber']
user.nameShort = ldapUser['Nutzerkuerzel']
if (user.nameLast != ldapUser['givenName']) {
user.nameFirst = ldapUser['givenName']
}
//
user.defaultTenant = tenantResult.default
user.enabled = ldapAccountEnabled
user.save(failOnError: true, flush: true)
UserInfo userInfo = new UserInfo(metaData: (new JSONObject(ldapUser)).toString(), user: user)
userInfo.save(failOnError: true, flush: true)
//TODO: Berater or Onlineteam??? Berater soll es sein https://tackl.it/app/#/tackls?projectId=188&tenantId=6&filterId=120&tacklId=9990
ShareRole defaultShareRole = ShareRole.findByNameOrId('Berater', 1)
tenantResult.tenants.each { Tenant tenant ->
Share share = new Share(user: user, shareRole: defaultShareRole)
share.setEntity(tenant)
share.save(failOnError: true, flush: true)
}
return user
}
/**
*
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Transactional(readOnly = false, noRollbackFor = [IllegalArgumentException, UsernameNotFoundException])
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
def ldapUser = ldapConnectionService.loadUser(username)
User user
if (ldapUser) {
// user = User.findByImportedId(ldapUser.uidNumber)
user = User.findByUsername(ldapUser.uid)
} else {
user = User.findByUsername(username)
}
if (!user && ldapUser) {
user = createUserFromLdap(ldapUser)
return new GrailsUser(username, 'ldap_init', ldapAccountEnabled,
true, true,
true, NO_ROLES, user.id)
}
if (!user && !ldapUser){
throw new NoStackUsernameNotFoundException()
}
if (user && ldapUser) {
updateUserInfo(user, ldapUser)
}
def roles = user.authorities
// or if you are using role groups:
// def roles = user.authorities.collect { it.authorities }.flatten().unique()
def authorities = roles.collect {
new SimpleGrantedAuthority(it.authority)
}
return new GrailsUser(user.username, user.password, user.enabled,
!user.accountExpired, !user.passwordExpired,
!user.accountLocked, authorities ?: NO_ROLES, user.id)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment