apps/api: remove ldap module and replace with utils
This commit is contained in:
parent
a8179a324a
commit
f1114cb703
@ -2,7 +2,6 @@ import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { env } from './config/env';
|
||||
import { LdapModule } from './ldap/ldap.module';
|
||||
import { UsersModule } from './users/users.module';
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
@ -25,7 +24,6 @@ import { MongooseModule } from '@nestjs/mongoose';
|
||||
}),
|
||||
AuthModule,
|
||||
UsersModule,
|
||||
LdapModule,
|
||||
MongooseModule.forRoot(`mongodb://${env.MONGO_HOST}`),
|
||||
],
|
||||
providers: [AppService],
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
/* eslint-disable class-methods-use-this */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import { AuthService } from './auth.service';
|
||||
import { Credentials } from './types/request';
|
||||
import { Credentials } from './dto/credentials';
|
||||
import type { CookieSerializeOptions } from '@fastify/cookie';
|
||||
import { Body, Controller, Get, HttpException, HttpStatus, Post, Req, Res } from '@nestjs/common';
|
||||
import { FastifyReply, FastifyRequest } from 'fastify';
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { LdapModule } from '../ldap/ldap.module';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
@ -6,7 +5,7 @@ import { Module } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
controllers: [AuthController],
|
||||
imports: [UsersModule, LdapModule],
|
||||
imports: [UsersModule],
|
||||
providers: [AuthService],
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
import { LdapService } from '../ldap/ldap.service';
|
||||
import { UsersCache } from '../users/users.cache';
|
||||
import type { DecodedToken, TokenPayload } from './types/jwt';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { env } from 'src/config/env';
|
||||
import * as ldap from 'src/utils/ldap';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private readonly ldapService: LdapService,
|
||||
private readonly usersCache: UsersCache,
|
||||
private readonly jwtService: JwtService
|
||||
) {}
|
||||
|
||||
public async login(login: string, password: string) {
|
||||
const user = await this.ldapService.authenticate(login, password);
|
||||
const user = await ldap.authenticate(login, password);
|
||||
const { username } = user;
|
||||
|
||||
await this.usersCache.addUser(username, user);
|
||||
|
||||
4
apps/api/src/auth/dto/credentials.ts
Normal file
4
apps/api/src/auth/dto/credentials.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class Credentials {
|
||||
readonly login: string;
|
||||
readonly password: string;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
export type TokenPayload = {
|
||||
username: string;
|
||||
domain: string;
|
||||
username: string;
|
||||
};
|
||||
|
||||
export type DecodedToken = {
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
export type Credentials = {
|
||||
login: string;
|
||||
password: string;
|
||||
};
|
||||
@ -1,9 +0,0 @@
|
||||
import { LdapService } from './ldap.service';
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
exports: [LdapService],
|
||||
providers: [LdapService],
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||
export class LdapModule {}
|
||||
@ -1,19 +0,0 @@
|
||||
import { LdapService } from './ldap.service';
|
||||
import type { TestingModule } from '@nestjs/testing';
|
||||
import { Test } from '@nestjs/testing';
|
||||
|
||||
describe('LdapService', () => {
|
||||
let service: LdapService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [LdapService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<LdapService>(LdapService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -1,44 +0,0 @@
|
||||
import { env } from '../config/env';
|
||||
import type { User } from '../types/user';
|
||||
import type { LdapUser } from './types/user';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import type { AuthenticationOptions } from 'ldap-authentication';
|
||||
import { authenticate } from 'ldap-authentication';
|
||||
|
||||
@Injectable()
|
||||
export class LdapService {
|
||||
public async authenticate(login: string, password?: string) {
|
||||
const options: AuthenticationOptions = {
|
||||
adminDn: env.LDAP_BIND_DN,
|
||||
adminPassword: env.LDAP_BIND_CREDENTIALS,
|
||||
ldapOpts: {
|
||||
url: env.LDAP_URL,
|
||||
},
|
||||
userPassword: password,
|
||||
userSearchBase: env.LDAP_BASE,
|
||||
username: login,
|
||||
usernameAttribute: env.LDAP_ATTRIBUTE,
|
||||
verifyUserExists: password === undefined,
|
||||
};
|
||||
|
||||
const {
|
||||
displayName,
|
||||
department,
|
||||
title,
|
||||
mail,
|
||||
sAMAccountName: username,
|
||||
}: LdapUser = await authenticate(options);
|
||||
|
||||
const user: User = {
|
||||
department,
|
||||
displayName,
|
||||
domain: env.LDAP_DOMAIN,
|
||||
domainName: `${env.LDAP_DOMAIN}\\${username}`,
|
||||
mail,
|
||||
position: title,
|
||||
username,
|
||||
};
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
export type User = {
|
||||
department: string;
|
||||
displayName: string;
|
||||
domain: string;
|
||||
domainName: string;
|
||||
mail: string;
|
||||
position: string;
|
||||
username: string;
|
||||
};
|
||||
@ -1,4 +1,3 @@
|
||||
import type { User } from '../types/user';
|
||||
import { CACHE_MANAGER } from '@nestjs/cache-manager';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Cache } from 'cache-manager';
|
||||
@ -6,15 +5,15 @@ import { Cache } from 'cache-manager';
|
||||
@Injectable()
|
||||
export class UsersCache {
|
||||
constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: Cache) {}
|
||||
async getUser(username: string) {
|
||||
return (await this.cacheManager.get(username)) as User;
|
||||
public async getUser<T extends object>(username: string) {
|
||||
return (await this.cacheManager.get(username)) as T;
|
||||
}
|
||||
|
||||
async addUser(username: string, user: User) {
|
||||
public async addUser<T extends object>(username: string, user: T) {
|
||||
await this.cacheManager.set(username, user);
|
||||
}
|
||||
|
||||
async deleteUser(username: string) {
|
||||
public async deleteUser(username: string) {
|
||||
if (this.cacheManager.get(username)) {
|
||||
await this.cacheManager.del(username);
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { LdapModule } from '../ldap/ldap.module';
|
||||
import { UsersCache } from './users.cache';
|
||||
import { UsersController } from './users.controller';
|
||||
import { UsersService } from './users.service';
|
||||
@ -20,7 +19,6 @@ import { User, UserSchema } from 'src/schemas/user.schema';
|
||||
store: redisStore,
|
||||
ttl: env.API_CACHE_TTL,
|
||||
}),
|
||||
LdapModule,
|
||||
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
|
||||
],
|
||||
providers: [UsersService, UsersCache],
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import type { DecodedToken } from '../auth/types/jwt';
|
||||
import { LdapService } from '../ldap/ldap.service';
|
||||
import type { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UsersCache } from './users.cache';
|
||||
import { Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
|
||||
@ -8,14 +7,14 @@ import { InjectModel } from '@nestjs/mongoose';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { Model } from 'mongoose';
|
||||
import { User } from 'src/schemas/user.schema';
|
||||
import { generatePassword } from 'utils/password';
|
||||
import * as ldap from 'src/utils/ldap';
|
||||
import { generatePassword } from 'src/utils/password';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
constructor(
|
||||
private readonly usersCache: UsersCache,
|
||||
private readonly jwtService: JwtService,
|
||||
private readonly ldapService: LdapService,
|
||||
@InjectModel(User.name)
|
||||
private userModel: Model<User>
|
||||
) {}
|
||||
@ -26,7 +25,7 @@ export class UsersService {
|
||||
const cachedUser = await this.usersCache.getUser(username);
|
||||
|
||||
if (!cachedUser) {
|
||||
const user = await this.ldapService.authenticate(username);
|
||||
const user = await ldap.authenticate(username);
|
||||
|
||||
await this.usersCache.addUser(username, user);
|
||||
|
||||
|
||||
@ -1,3 +1,17 @@
|
||||
import type { AuthenticationOptions } from 'ldap-authentication';
|
||||
import * as ldap from 'ldap-authentication';
|
||||
import { env } from 'src/config/env';
|
||||
|
||||
export type User = {
|
||||
department: string;
|
||||
displayName: string;
|
||||
domain: string;
|
||||
domainName: string;
|
||||
mail: string;
|
||||
position: string;
|
||||
username: string;
|
||||
};
|
||||
|
||||
export type LdapUser = {
|
||||
accountExpires: string;
|
||||
badPasswordTime: string;
|
||||
@ -61,3 +75,42 @@ export type LdapUser = {
|
||||
whenChanged: string;
|
||||
whenCreated: string;
|
||||
};
|
||||
|
||||
const BASE_OPTIONS: AuthenticationOptions = {
|
||||
adminDn: env.LDAP_BIND_DN,
|
||||
adminPassword: env.LDAP_BIND_CREDENTIALS,
|
||||
ldapOpts: {
|
||||
url: env.LDAP_URL,
|
||||
},
|
||||
userSearchBase: env.LDAP_BASE,
|
||||
usernameAttribute: env.LDAP_ATTRIBUTE,
|
||||
};
|
||||
|
||||
export async function authenticate(login: string, password?: string) {
|
||||
const options: AuthenticationOptions = {
|
||||
...BASE_OPTIONS,
|
||||
userPassword: password,
|
||||
username: login,
|
||||
verifyUserExists: password === undefined,
|
||||
};
|
||||
|
||||
const {
|
||||
displayName,
|
||||
department,
|
||||
title,
|
||||
mail,
|
||||
sAMAccountName: username,
|
||||
}: LdapUser = await ldap.authenticate(options);
|
||||
|
||||
const user: User = {
|
||||
department,
|
||||
displayName,
|
||||
domain: env.LDAP_DOMAIN,
|
||||
domainName: `${env.LDAP_DOMAIN}\\${username}`,
|
||||
mail,
|
||||
position: title,
|
||||
username,
|
||||
};
|
||||
|
||||
return user;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user