const { Model } = require('flitter-orm') const LDAP = require('ldapjs') // For organizational purposes only. class GroupModel extends Model { static get services() { return [...super.services, 'models', 'ldap_server', 'configs'] } static get schema() { return { name: String, user_ids: [String], posix_user_id: String, posix_group_id: Number, grants_sudo: { type: Boolean, default: false }, active: { type: Boolean, default: true }, ldap_visible: { type: Boolean, default: true }, } } identifier() { return this.name.toLowerCase().replace(/\s/g, '_') } get dn() { return LDAP.parseDN(`cn=${this.name},${this.ldap_server.group_dn().format(this.configs.get('ldap:server.format'))}`) } async users() { const User = this.models.get('auth:User') return await User.find({ _id: { $in: this.user_ids.map(x => this.constructor.to_object_id(x)) } }) } async get_gid_number() { if ( !this.posix_group_id ) { const Setting = this.models.get('Setting') let last_uid = await Setting.get('ldap.last_alloc_uid') if ( last_uid < 1 ) { last_uid = this.configs.get('ldap:server.schema.start_uid') } this.posix_group_id = last_uid + 1 await Setting.set('ldap.last_alloc_uid', this.posix_group_id) await this.save() } return this.posix_group_id } async to_ldap() { const users = await this.users() return { cn: this.name, dn: this.dn.format(this.configs.get('ldap:server.format')), objectClass: ['groupOfNames', 'posixGroup'], gidNumber: String(await this.get_gid_number()), member: users.map(x => x.dn.format(this.configs.get('ldap:server.format'))), } } static async sudo_directory() { const groups = await this.find({ ldap_visible: true, active: true, grants_sudo: true }) let users = [] for ( const group of groups ) { users = [...users, ...(await group.users())] } return users.filter(u => u.uid !== 'root') } static async ldap_directory() { const User = this.prototype.models.get('auth:User') const groups = await this.find({ ldap_visible: true, active: true }) const posix_user_ids = groups.map(group => group.posix_user_id) .filter(Boolean) .map(id => User.to_object_id(id)) const missing_posix_users = await User.find({ ldap_visible: true, _id: { $nin: posix_user_ids } }) for ( const user of missing_posix_users ) { const group = new this({ name: `${user.uid} (posix)`, user_ids: [user.id], posix_user_id: user.id, posix_group_id: await user.get_uid_number(), }) await group.save() groups.push(group) } return groups } async to_api() { return { id: this.id, name: this.name, user_ids: this.user_ids, ldap_visible: this.ldap_visible, grants_sudo: !!this.grants_sudo, } } } module.exports = exports = GroupModel