feat(ldap): Adding support for LDAP authentication (#554)

This commit is contained in:
WolverinDEV
2024-08-24 16:15:33 +02:00
committed by GitHub
parent 4924f76394
commit 4186a768b3
17 changed files with 573 additions and 128 deletions

View File

@@ -25,16 +25,21 @@ export class UserDTO {
@Expose()
isAdmin: boolean;
@Expose()
isLdap: boolean;
ldapDN?: string;
@Expose()
totpVerified: boolean;
from(partial: Partial<UserDTO>) {
return plainToClass(UserDTO, partial, { excludeExtraneousValues: true });
const result = plainToClass(UserDTO, partial, { excludeExtraneousValues: true });
result.isLdap = partial.ldapDN?.length > 0;
return result;
}
fromList(partial: Partial<UserDTO>[]) {
return partial.map((part) =>
plainToClass(UserDTO, part, { excludeExtraneousValues: true }),
);
return partial.map((part) => this.from(part));
}
}

View File

@@ -8,5 +8,6 @@ import { FileModule } from "src/file/file.module";
imports: [EmailModule, FileModule],
providers: [UserSevice],
controllers: [UserController],
exports: [UserSevice]
})
export class UserModule {}
export class UserModule { }

View File

@@ -7,6 +7,8 @@ import { PrismaService } from "src/prisma/prisma.service";
import { FileService } from "../file/file.service";
import { CreateUserDTO } from "./dto/createUser.dto";
import { UpdateUserDto } from "./dto/updateUser.dto";
import { ConfigService } from "../config/config.service";
import { LdapAuthenticateResult } from "../auth/ldap.service";
@Injectable()
export class UserSevice {
@@ -14,7 +16,8 @@ export class UserSevice {
private prisma: PrismaService,
private emailService: EmailService,
private fileService: FileService,
) {}
private configService: ConfigService,
) { }
async list() {
return await this.prisma.user.findMany();
@@ -88,4 +91,41 @@ export class UserSevice {
return await this.prisma.user.delete({ where: { id } });
}
async findOrCreateFromLDAP(username: string, ldap: LdapAuthenticateResult) {
const passwordHash = await argon.hash(crypto.randomUUID());
const userEmail = ldap.attributes["userPrincipalName"]?.at(0) ?? `${crypto.randomUUID()}@ldap.local`;
const adminGroup = this.configService.get("ldap.adminGroups");
const isAdmin = ldap.attributes["memberOf"]?.includes(adminGroup) ?? false;
try {
return await this.prisma.user.upsert({
create: {
username,
email: userEmail,
password: passwordHash,
isAdmin,
ldapDN: ldap.userDn,
},
update: {
username,
email: userEmail,
isAdmin,
ldapDN: ldap.userDn,
},
where: {
ldapDN: ldap.userDn
}
});
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e.code == "P2002") {
const duplicatedField: string = e.meta.target[0];
throw new BadRequestException(
`A user with this ${duplicatedField} already exists`,
);
}
}
}
}
}