CoreID/app/ldap/controllers/Sudo.controller.js

118 lines
4.3 KiB
JavaScript
Raw Normal View History

2021-03-11 05:43:16 +00:00
const LDAPController = require('./LDAPController')
const LDAP = require('ldapjs')
class SudoController extends LDAPController {
static get services() {
return [
...super.services,
'output',
'ldap_server',
'models',
'configs',
'auth'
]
}
constructor() {
super()
this.Group = this.models.get('auth:Group')
this.User = this.models.get('auth:User')
}
// TODO flitter-orm chunk query
// TODO generalize scoped search logic
async search_sudo(req, res, next) {
if ( !req.user.can('ldap:search:sudo') ) {
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 sudo with DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
const user = await this.get_resource_from_dn(req.dn)
// Make sure the user is ldap visible && match the filter
if ( user && user.ldap_visible && req.filter.matches(await user.to_sudo()) ) {
// If so, send the object
res.send({
dn: user.sudo_dn.format(this.configs.get('ldap:server.format')),
attributes: await user.to_sudo(),
})
}
} 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 sudo with DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
// Fetch the LDAP-visible users
const users = await this.Group.sudo_directory()
for ( const user of users ) {
// Make sure the user os of the appropriate scope
if ( req.dn.equals(user.sudo_dn) || user.sudo_dn.parent().equals(req.dn) ) {
// Check if the filter matches
if ( req.filter.matches(await user.to_sudo()) ) {
// If so, send the object
res.send({
dn: user.sudo_dn.format(this.configs.get('ldap:server.format')),
attributes: await user.to_sudo(),
})
}
}
}
} 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 sudo with DN: ${req.dn.format(this.configs.get('ldap:server.format'))}`)
// Fetch the users as LDAP objects
const users = await this.Group.sudo_directory()
for ( const user of users ) {
// Make sure the user is of appropriate scope
if ( req.dn.equals(user.sudo_dn) || req.dn.parentOf(user.sudo_dn) ) {
// Check if filter matches
if ( req.filter.matches(await user.to_sudo()) ) {
// If so, send the object
res.send({
dn: user.sudo_dn.format(this.configs.get('ldap:server.format')),
attributes: await user.to_sudo(),
})
}
}
}
} 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(sudo_dn) {
const cn = this.get_cn_from_dn(sudo_dn)
if ( cn ) {
const user = this.User.findOne({uid: cn.substr(5), ldap_visible: true})
if ( user && (await user.has_sudo()) ) return user
}
}
}
module.exports = exports = SudoController