116 lines
4.2 KiB
JavaScript
116 lines
4.2 KiB
JavaScript
const LDAPController = require('./LDAPController')
|
|
const LDAP = require('ldapjs')
|
|
|
|
class GroupsController extends LDAPController {
|
|
static get services() {
|
|
return [
|
|
...super.services,
|
|
'output',
|
|
'ldap_server',
|
|
'models',
|
|
'configs',
|
|
'auth'
|
|
]
|
|
}
|
|
|
|
constructor() {
|
|
super()
|
|
this.Group = this.models.get('auth:Group')
|
|
}
|
|
|
|
// TODO flitter-orm chunk query
|
|
// TODO generalize scoped search logic
|
|
async search_groups(req, res, next) {
|
|
if ( !req.user.can('ldap:search:groups') ) {
|
|
return next(new LDAP.InsufficientAccessRightsError())
|
|
}
|
|
|
|
if ( req.scope === 'base' ) {
|
|
// If scope is base, check if the base DN matches the filter.
|
|
// If so, return it. Else, return empty.
|
|
this.output.debug(`Running base DN search for groups with DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
|
|
|
|
const group = await this.get_resource_from_dn(req.dn)
|
|
|
|
// Make sure the user is ldap visible && match the filter
|
|
if ( group && group.ldap_visible && req.filter.matches(await group.to_ldap()) ) {
|
|
|
|
// If so, send the object
|
|
res.send({
|
|
dn: group.dn.format(this.configs.get('ldap:server.format')),
|
|
attributes: await group.to_ldap(),
|
|
})
|
|
}
|
|
} else if ( req.scope === 'one' ) {
|
|
// If scope is one, find all entries that are the immediate
|
|
// subordinates of the base DN that match the filter.
|
|
this.output.debug(`Running one DN search for groups with DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
|
|
|
|
// Fetch the LDAP-visible users
|
|
const groups = await this.Group.ldap_directory()
|
|
for ( const group of groups ) {
|
|
|
|
// Make sure the user os of the appropriate scope
|
|
if ( req.dn.equals(group.dn) || group.dn.parent().equals(req.dn) ) {
|
|
|
|
// Check if the filter matches
|
|
if ( req.filter.matches(await group.to_ldap()) ) {
|
|
|
|
// If so, send the object
|
|
res.send({
|
|
dn: group.dn.format(this.configs.get('ldap:server.format')),
|
|
attributes: await group.to_ldap(),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
} else if ( req.scope === 'sub' ) {
|
|
// If scope is sub, find all entries that are subordinates
|
|
// of the base DN at any level and match the filter.
|
|
this.output.debug(`Running sub DN search for groups with DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
|
|
|
|
// Fetch the users as LDAP objects
|
|
const groups = await this.Group.ldap_directory()
|
|
for ( const group of groups ) {
|
|
|
|
// Make sure the user is of appropriate scope
|
|
if ( req.dn.equals(group.dn) || req.dn.parentOf(group.dn) ) {
|
|
|
|
// Check if filter matches
|
|
if ( req.filter.matches(await group.to_ldap()) ) {
|
|
|
|
// If so, send the object
|
|
res.send({
|
|
dn: group.dn.format(this.configs.get('ldap:server.format')),
|
|
attributes: await group.to_ldap(),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
this.output.error(`Attempted to perform LDAP search with invalid scope: ${req.scope}`)
|
|
return next(new LDAP.OtherError('Attempted to perform LDAP search with invalid scope.'))
|
|
}
|
|
|
|
res.end()
|
|
return next()
|
|
}
|
|
|
|
get_cn_from_dn(dn) {
|
|
try {
|
|
if ( typeof dn === 'string' ) dn = LDAP.parseDN(dn)
|
|
return dn.rdns[0].attrs.cn.value
|
|
} catch (e) { console.log('Error parsing CN from DN', e) }
|
|
}
|
|
|
|
async get_resource_from_dn(dn) {
|
|
const cn = this.get_cn_from_dn(dn)
|
|
if ( cn ) {
|
|
return this.Group.findOne({name: cn, ldap_visible: true, active: true})
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = exports = GroupsController
|