124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
|
|
import { Injectable, Logger } from '@nestjs/common';
|
||
|
|
import { ConfigService } from '@nestjs/config';
|
||
|
|
import { Client, Attribute, Change } from 'ldapts';
|
||
|
|
|
||
|
|
@Injectable()
|
||
|
|
export class ActiveDirectoryService {
|
||
|
|
private readonly logger = new Logger(ActiveDirectoryService.name);
|
||
|
|
|
||
|
|
constructor(private configService: ConfigService) { }
|
||
|
|
|
||
|
|
private createClient(): Client {
|
||
|
|
return new Client({
|
||
|
|
url: this.configService.get<string>('AD_URL')!,
|
||
|
|
tlsOptions: { rejectUnauthorized: false },
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async createUser(cuenta: string): Promise<void> {
|
||
|
|
const client = this.createClient();
|
||
|
|
const bindDN = this.configService.get<string>('AD_BIND_DN')!;
|
||
|
|
const bindPass = this.configService.get<string>('AD_BIND_PASS')!;
|
||
|
|
const baseDN = this.configService.get<string>('AD_BASE_DN')!;
|
||
|
|
|
||
|
|
try {
|
||
|
|
await client.bind(bindDN, bindPass);
|
||
|
|
|
||
|
|
const userDN = `CN=${cuenta},${baseDN}`;
|
||
|
|
|
||
|
|
await client.add(userDN, {
|
||
|
|
objectClass: ['top', 'person', 'organizationalPerson', 'user'],
|
||
|
|
sAMAccountName: cuenta,
|
||
|
|
cn: cuenta,
|
||
|
|
description: 'Creado desde el Sitio',
|
||
|
|
userAccountControl: '32',
|
||
|
|
});
|
||
|
|
|
||
|
|
const encodedPassword = Buffer.from(`"${cuenta}"`, 'utf16le');
|
||
|
|
|
||
|
|
await client.modify(userDN, [
|
||
|
|
new Change({
|
||
|
|
operation: 'replace',
|
||
|
|
modification: new Attribute({ type: 'unicodePwd', values: [encodedPassword] }),
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
|
||
|
|
await client.modify(userDN, [
|
||
|
|
new Change({
|
||
|
|
operation: 'replace',
|
||
|
|
modification: new Attribute({ type: 'pwdLastSet', values: ['0'] }),
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
|
||
|
|
await client.modify(userDN, [
|
||
|
|
new Change({
|
||
|
|
operation: 'replace',
|
||
|
|
modification: new Attribute({ type: 'userAccountControl', values: ['512'] }),
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
|
||
|
|
this.logger.log(`Usuario ${cuenta} creado exitosamente en AD`);
|
||
|
|
} catch (error) {
|
||
|
|
this.logger.error(`Error al crear usuario ${cuenta} en AD`, error);
|
||
|
|
throw error;
|
||
|
|
} finally {
|
||
|
|
await client.unbind();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async resetPassword(cuenta: string): Promise<void> {
|
||
|
|
const client = this.createClient();
|
||
|
|
const bindDN = this.configService.get<string>('AD_BIND_DN')!;
|
||
|
|
const bindPass = this.configService.get<string>('AD_BIND_PASS')!;
|
||
|
|
const baseDN = this.configService.get<string>('AD_BASE_DN')!;
|
||
|
|
|
||
|
|
try {
|
||
|
|
await client.bind(bindDN, bindPass);
|
||
|
|
const userDN = `CN=${cuenta},${baseDN}`;
|
||
|
|
await client.del(userDN);
|
||
|
|
this.logger.log(`Usuario ${cuenta} eliminado de AD`);
|
||
|
|
} catch (error) {
|
||
|
|
this.logger.warn(`No se pudo eliminar ${cuenta} de AD (puede no existir)`, error);
|
||
|
|
} finally {
|
||
|
|
await client.unbind();
|
||
|
|
}
|
||
|
|
|
||
|
|
await this.createUser(cuenta);
|
||
|
|
}
|
||
|
|
|
||
|
|
async changePassword(cuenta: string, newPass?: string): Promise<void> {
|
||
|
|
const client = this.createClient();
|
||
|
|
const bindDN = this.configService.get<string>('AD_BIND_DN')!;
|
||
|
|
const bindPass = this.configService.get<string>('AD_BIND_PASS')!;
|
||
|
|
const baseDN = this.configService.get<string>('AD_BASE_DN')!;
|
||
|
|
const password = newPass ?? cuenta;
|
||
|
|
|
||
|
|
try {
|
||
|
|
await client.bind(bindDN, bindPass);
|
||
|
|
|
||
|
|
const userDN = `CN=${cuenta},${baseDN}`;
|
||
|
|
const encodedPassword = Buffer.from(`"${password}"`, 'utf16le');
|
||
|
|
|
||
|
|
await client.modify(userDN, [
|
||
|
|
new Change({
|
||
|
|
operation: 'replace',
|
||
|
|
modification: new Attribute({ type: 'unicodePwd', values: [encodedPassword] }),
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
|
||
|
|
await client.modify(userDN, [
|
||
|
|
new Change({
|
||
|
|
operation: 'replace',
|
||
|
|
modification: new Attribute({ type: 'pwdLastSet', values: ['0'] }),
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
|
||
|
|
this.logger.log(`Contraseña de ${cuenta} actualizada`);
|
||
|
|
} catch (error) {
|
||
|
|
this.logger.error(`Error al cambiar contraseña de ${cuenta}`, error);
|
||
|
|
throw error;
|
||
|
|
} finally {
|
||
|
|
await client.unbind();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|