BugFixes bzgl. Observables, Logging Anpassungen, Endpunkt hardening, dotenv-flow usage
This commit is contained in:
parent
205793faab
commit
3e84b82c92
|
|
@ -0,0 +1,4 @@
|
||||||
|
REALM=bizmatch-dev
|
||||||
|
usersURL=/admin/realms/bizmatch-dev/users
|
||||||
|
WEB_HOST=https://dev.bizmatch.net
|
||||||
|
STRIPE_WEBHOOK_SECRET=whsec_w2yvJY8qFMfO5wJgyNHCn6oYT7o2J5pS
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
REALM=bizmatch
|
||||||
|
WEB_HOST=https://www.bizmatch.net
|
||||||
|
|
@ -8,11 +8,11 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nest build",
|
"build": "nest build",
|
||||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
"start": "HOST_NAME=localhost nest start",
|
"start": "nest start",
|
||||||
"start:local": "HOST_NAME=localhost node dist/src/main",
|
"start:local": "HOST_NAME=localhost node dist/src/main",
|
||||||
"start:dev": "HOST_NAME=dev.bizmatch.net node dist/src/main",
|
"start:dev": "NODE_ENV=development node dist/src/main",
|
||||||
"start:debug": "nest start --debug --watch",
|
"start:debug": "nest start --debug --watch",
|
||||||
"start:prod": "HOST_NAME=www.bizmatch.net node dist/src/main",
|
"start:prod": "NODE_ENV=production node dist/src/main",
|
||||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
|
"dotenv-flow": "^4.1.0",
|
||||||
"drizzle-orm": "^0.32.0",
|
"drizzle-orm": "^0.32.0",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"groq-sdk": "^0.5.0",
|
"groq-sdk": "^0.5.0",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { MiddlewareConsumer, Module } from '@nestjs/common';
|
import { MiddlewareConsumer, Module } from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { PassportModule } from '@nestjs/passport';
|
import { PassportModule } from '@nestjs/passport';
|
||||||
import * as dotenv from 'dotenv';
|
|
||||||
import fs from 'fs-extra';
|
|
||||||
import { WinstonModule, utilities as nestWinstonModuleUtilities } from 'nest-winston';
|
import { WinstonModule, utilities as nestWinstonModuleUtilities } from 'nest-winston';
|
||||||
import * as winston from 'winston';
|
import * as winston from 'winston';
|
||||||
import { AiModule } from './ai/ai.module';
|
import { AiModule } from './ai/ai.module';
|
||||||
|
|
@ -16,46 +14,48 @@ import { ListingsModule } from './listings/listings.module';
|
||||||
import { LogController } from './log/log.controller';
|
import { LogController } from './log/log.controller';
|
||||||
import { LogModule } from './log/log.module';
|
import { LogModule } from './log/log.module';
|
||||||
|
|
||||||
|
import dotenvFlow from 'dotenv-flow';
|
||||||
|
import { EventModule } from './event/event.module';
|
||||||
import { JwtStrategy } from './jwt.strategy';
|
import { JwtStrategy } from './jwt.strategy';
|
||||||
import { MailModule } from './mail/mail.module';
|
import { MailModule } from './mail/mail.module';
|
||||||
import { PaymentModule } from './payment/payment.module';
|
import { PaymentModule } from './payment/payment.module';
|
||||||
import { RequestDurationMiddleware } from './request-duration/request-duration.middleware';
|
import { RequestDurationMiddleware } from './request-duration/request-duration.middleware';
|
||||||
import { SelectOptionsModule } from './select-options/select-options.module';
|
import { SelectOptionsModule } from './select-options/select-options.module';
|
||||||
import { UserModule } from './user/user.module';
|
import { UserModule } from './user/user.module';
|
||||||
import { EventModule } from './event/event.module';
|
|
||||||
// const __filename = fileURLToPath(import.meta.url);
|
|
||||||
// const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
function loadEnvFiles() {
|
// function loadEnvFiles() {
|
||||||
// Determine which additional env file to load
|
// // Determine which additional env file to load
|
||||||
let envFilePath = '';
|
// let envFilePath = '';
|
||||||
const host = process.env.HOST_NAME || '';
|
// const host = process.env.HOST_NAME || '';
|
||||||
|
|
||||||
if (host.includes('localhost')) {
|
// if (host.includes('localhost')) {
|
||||||
envFilePath = '.env.local';
|
// envFilePath = '.env.local';
|
||||||
} else if (host.includes('dev.bizmatch.net')) {
|
// } else if (host.includes('dev.bizmatch.net')) {
|
||||||
envFilePath = '.env.dev';
|
// envFilePath = '.env.dev';
|
||||||
} else if (host.includes('www.bizmatch.net') || host.includes('bizmatch.net')) {
|
// } else if (host.includes('www.bizmatch.net') || host.includes('bizmatch.net')) {
|
||||||
envFilePath = '.env.prod';
|
// envFilePath = '.env.prod';
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Load the additional env file if it exists
|
// // Load the additional env file if it exists
|
||||||
if (fs.existsSync(envFilePath)) {
|
// if (fs.existsSync(envFilePath)) {
|
||||||
dotenv.config({ path: envFilePath });
|
// dotenv.config({ path: envFilePath });
|
||||||
console.log(`Loaded ${envFilePath} file`);
|
// console.log(`Loaded ${envFilePath} file`);
|
||||||
} else {
|
// } else {
|
||||||
console.log(`No additional .env file found for HOST_NAME: ${host}`);
|
// console.log(`No additional .env file found for HOST_NAME: ${host}`);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Load the .env file
|
// // Load the .env file
|
||||||
dotenv.config();
|
// dotenv.config();
|
||||||
console.log('Loaded .env file');
|
// console.log('Loaded .env file');
|
||||||
// Output all loaded environment variables
|
// // Output all loaded environment variables
|
||||||
|
// console.log('Loaded environment variables:');
|
||||||
|
// console.log(JSON.stringify(process.env, null, 2));
|
||||||
|
// }
|
||||||
|
|
||||||
|
//loadEnvFiles();
|
||||||
|
dotenvFlow.config();
|
||||||
console.log('Loaded environment variables:');
|
console.log('Loaded environment variables:');
|
||||||
console.log(JSON.stringify(process.env, null, 2));
|
console.log(JSON.stringify(process.env, null, 2));
|
||||||
}
|
|
||||||
|
|
||||||
loadEnvFiles();
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({ isGlobal: true }),
|
ConfigModule.forRoot({ isGlobal: true }),
|
||||||
|
|
@ -65,7 +65,9 @@ loadEnvFiles();
|
||||||
transports: [
|
transports: [
|
||||||
new winston.transports.Console({
|
new winston.transports.Console({
|
||||||
format: winston.format.combine(
|
format: winston.format.combine(
|
||||||
winston.format.timestamp(),
|
winston.format.timestamp({
|
||||||
|
format: 'YYYY-MM-DD hh:mm:ss.SSS A',
|
||||||
|
}),
|
||||||
winston.format.ms(),
|
winston.format.ms(),
|
||||||
nestWinstonModuleUtilities.format.nestLike('Bizmatch', {
|
nestWinstonModuleUtilities.format.nestLike('Bizmatch', {
|
||||||
colors: true,
|
colors: true,
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,25 @@ export class AuthController {
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@Get()
|
@Get()
|
||||||
getAccessToken(): any {
|
async getAccessToken(): Promise<any> {
|
||||||
return this.authService.getAccessToken();
|
return await this.authService.getAccessToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@Get('user/all')
|
@Get('user/all')
|
||||||
getUsers(): any {
|
async getUsers(): Promise<any> {
|
||||||
return this.authService.getUsers();
|
return await this.authService.getUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Get('users/:userid')
|
@Get('users/:userid')
|
||||||
getUser(@Param('userid') userId: string): any {
|
async getUser(@Param('userid') userId: string): Promise<any> {
|
||||||
return this.authService.getUser(userId);
|
return await this.authService.getUser(userId);
|
||||||
}
|
}
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Put('users/:userid')
|
@Put('users/:userid')
|
||||||
updateKeycloakUser(@Body() keycloakUser: KeycloakUser): any {
|
async updateKeycloakUser(@Body() keycloakUser: KeycloakUser): Promise<any> {
|
||||||
return this.authService.updateKeycloakUser(keycloakUser);
|
return await this.authService.updateKeycloakUser(keycloakUser);
|
||||||
}
|
}
|
||||||
// @UseGuards(AdminAuthGuard)
|
// @UseGuards(AdminAuthGuard)
|
||||||
// @Get('user/:userid/lastlogin') //e0811669-c7eb-4e5e-a699-e8334d5c5b01 -> aknuth
|
// @Get('user/:userid/lastlogin') //e0811669-c7eb-4e5e-a699-e8334d5c5b01 -> aknuth
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { drizzle } from 'drizzle-orm/node-postgres';
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
||||||
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
import pkg from 'pg';
|
import pkg from 'pg';
|
||||||
|
import { Logger } from 'winston';
|
||||||
import * as schema from './schema';
|
import * as schema from './schema';
|
||||||
import { PG_CONNECTION } from './schema';
|
import { PG_CONNECTION } from './schema';
|
||||||
const { Pool } = pkg;
|
const { Pool } = pkg;
|
||||||
|
|
@ -9,15 +11,21 @@ const { Pool } = pkg;
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: PG_CONNECTION,
|
provide: PG_CONNECTION,
|
||||||
inject: [ConfigService],
|
inject: [ConfigService, WINSTON_MODULE_PROVIDER],
|
||||||
useFactory: async (configService: ConfigService) => {
|
useFactory: async (configService: ConfigService, logger: Logger) => {
|
||||||
const connectionString = configService.get<string>('DATABASE_URL');
|
const connectionString = configService.get<string>('DATABASE_URL');
|
||||||
const pool = new Pool({
|
const pool = new Pool({
|
||||||
connectionString,
|
connectionString,
|
||||||
// ssl: true,
|
// ssl: true,
|
||||||
});
|
});
|
||||||
|
// Definiere einen benutzerdefinierten Logger für Drizzle
|
||||||
|
const drizzleLogger = {
|
||||||
|
logQuery(query: string, params: unknown[]): void {
|
||||||
|
logger.info(query, params);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return drizzle(pool, { schema, logger: true });
|
return drizzle(pool, { schema, logger: drizzleLogger });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,9 @@ export class EventController {
|
||||||
@Ip() userIp: string, // IP Adresse des Clients
|
@Ip() userIp: string, // IP Adresse des Clients
|
||||||
@Headers('user-agent') userAgent: string, // User-Agent des Clients
|
@Headers('user-agent') userAgent: string, // User-Agent des Clients
|
||||||
) {
|
) {
|
||||||
//const { listingId, userId, eventType, locationCountry, locationCity, locationLat, locationLng, referrer, additionalData } = body;
|
|
||||||
event.userIp = userIp;
|
event.userIp = userIp;
|
||||||
event.userAgent = userAgent;
|
event.userAgent = userAgent;
|
||||||
this.eventService.createEvent(event);
|
await this.eventService.createEvent(event);
|
||||||
return { message: 'Event gespeichert' };
|
return { message: 'Event gespeichert' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,22 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { readFileSync } from 'fs';
|
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
import { join } from 'path';
|
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import { ImageProperty, Subscription } from '../models/main.model';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FileService {
|
export class FileService {
|
||||||
private subscriptions: any;
|
|
||||||
constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {
|
constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {
|
||||||
this.loadSubscriptions();
|
|
||||||
fs.ensureDirSync(`./pictures`);
|
fs.ensureDirSync(`./pictures`);
|
||||||
fs.ensureDirSync(`./pictures/profile`);
|
fs.ensureDirSync(`./pictures/profile`);
|
||||||
fs.ensureDirSync(`./pictures/logo`);
|
fs.ensureDirSync(`./pictures/logo`);
|
||||||
fs.ensureDirSync(`./pictures/property`);
|
fs.ensureDirSync(`./pictures/property`);
|
||||||
}
|
}
|
||||||
// ############
|
// ############
|
||||||
// Subscriptions
|
|
||||||
// ############
|
|
||||||
private loadSubscriptions(): void {
|
|
||||||
const filePath = join(__dirname, '../..', 'assets', 'subscriptions.json');
|
|
||||||
const rawData = readFileSync(filePath, 'utf8');
|
|
||||||
this.subscriptions = JSON.parse(rawData);
|
|
||||||
}
|
|
||||||
getSubscriptions(): Subscription[] {
|
|
||||||
return this.subscriptions;
|
|
||||||
}
|
|
||||||
// ############
|
|
||||||
// Profile
|
// Profile
|
||||||
// ############
|
// ############
|
||||||
async storeProfilePicture(file: Express.Multer.File, adjustedEmail: string) {
|
async storeProfilePicture(file: Express.Multer.File, adjustedEmail: string) {
|
||||||
let quality = 50;
|
const quality = 50;
|
||||||
const output = await sharp(file.buffer)
|
const output = await sharp(file.buffer)
|
||||||
.resize({ width: 300 })
|
.resize({ width: 300 })
|
||||||
.avif({ quality }) // Verwende AVIF
|
.avif({ quality }) // Verwende AVIF
|
||||||
|
|
@ -47,7 +31,7 @@ export class FileService {
|
||||||
// Logo
|
// Logo
|
||||||
// ############
|
// ############
|
||||||
async storeCompanyLogo(file: Express.Multer.File, adjustedEmail: string) {
|
async storeCompanyLogo(file: Express.Multer.File, adjustedEmail: string) {
|
||||||
let quality = 50;
|
const quality = 50;
|
||||||
const output = await sharp(file.buffer)
|
const output = await sharp(file.buffer)
|
||||||
.resize({ width: 300 })
|
.resize({ width: 300 })
|
||||||
.avif({ quality }) // Verwende AVIF
|
.avif({ quality }) // Verwende AVIF
|
||||||
|
|
@ -76,7 +60,6 @@ export class FileService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async hasPropertyImages(imagePath: string, serial: string): Promise<boolean> {
|
async hasPropertyImages(imagePath: string, serial: string): Promise<boolean> {
|
||||||
const result: ImageProperty[] = [];
|
|
||||||
const directory = `./pictures/property/${imagePath}/${serial}`;
|
const directory = `./pictures/property/${imagePath}/${serial}`;
|
||||||
if (fs.existsSync(directory)) {
|
if (fs.existsSync(directory)) {
|
||||||
const files = await fs.readdir(directory);
|
const files = await fs.readdir(directory);
|
||||||
|
|
@ -86,7 +69,6 @@ export class FileService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async storePropertyPicture(file: Express.Multer.File, imagePath: string, serial: string): Promise<string> {
|
async storePropertyPicture(file: Express.Multer.File, imagePath: string, serial: string): Promise<string> {
|
||||||
const suffix = file.mimetype.includes('png') ? 'png' : 'jpg';
|
|
||||||
const directory = `./pictures/property/${imagePath}/${serial}`;
|
const directory = `./pictures/property/${imagePath}/${serial}`;
|
||||||
fs.ensureDirSync(`${directory}`);
|
fs.ensureDirSync(`${directory}`);
|
||||||
const imageName = await this.getNextImageName(directory);
|
const imageName = await this.getNextImageName(directory);
|
||||||
|
|
@ -113,16 +95,15 @@ export class FileService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async resizeImageToAVIF(buffer: Buffer, maxSize: number, imageName: string, directory: string) {
|
async resizeImageToAVIF(buffer: Buffer, maxSize: number, imageName: string, directory: string) {
|
||||||
let quality = 50; // AVIF kann mit niedrigeren Qualitätsstufen gute Ergebnisse erzielen
|
const quality = 50; // AVIF kann mit niedrigeren Qualitätsstufen gute Ergebnisse erzielen
|
||||||
let output;
|
const start = Date.now();
|
||||||
let start = Date.now();
|
const output = await sharp(buffer)
|
||||||
output = await sharp(buffer)
|
|
||||||
.resize({ width: 1500 })
|
.resize({ width: 1500 })
|
||||||
.avif({ quality }) // Verwende AVIF
|
.avif({ quality }) // Verwende AVIF
|
||||||
//.webp({ quality }) // Verwende Webp
|
//.webp({ quality }) // Verwende Webp
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
await sharp(output).toFile(`${directory}/${imageName}.avif`); // Ersetze Dateierweiterung
|
await sharp(output).toFile(`${directory}/${imageName}.avif`); // Ersetze Dateierweiterung
|
||||||
let timeTaken = Date.now() - start;
|
const timeTaken = Date.now() - start;
|
||||||
this.logger.info(`Quality: ${quality} - Time: ${timeTaken} milliseconds`);
|
this.logger.info(`Quality: ${quality} - Time: ${timeTaken} milliseconds`);
|
||||||
}
|
}
|
||||||
deleteImage(path: string) {
|
deleteImage(path: string) {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export class GeoController {
|
||||||
return this.geoService.findCountiesStartingWith(countyRequest.prefix, countyRequest.states);
|
return this.geoService.findCountiesStartingWith(countyRequest.prefix, countyRequest.states);
|
||||||
}
|
}
|
||||||
@Get('ipinfo/georesult/wysiwyg')
|
@Get('ipinfo/georesult/wysiwyg')
|
||||||
fetchIpAndGeoLocation(@RealIp() ipInfo: RealIpInfo): any {
|
async fetchIpAndGeoLocation(@RealIp() ipInfo: RealIpInfo): Promise<any> {
|
||||||
return this.geoService.fetchIpAndGeoLocation(ipInfo);
|
return await this.geoService.fetchIpAndGeoLocation(ipInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export class GeoService {
|
||||||
this.counties.forEach(stateData => {
|
this.counties.forEach(stateData => {
|
||||||
if (!states || states.includes(stateData.state)) {
|
if (!states || states.includes(stateData.state)) {
|
||||||
stateData.counties.forEach(county => {
|
stateData.counties.forEach(county => {
|
||||||
if (county.startsWith(prefix.toUpperCase())) {
|
if (county.startsWith(prefix?.toUpperCase())) {
|
||||||
results.push({
|
results.push({
|
||||||
id: idCounter++,
|
id: idCounter++,
|
||||||
name: county,
|
name: county,
|
||||||
|
|
|
||||||
|
|
@ -29,28 +29,6 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||||
// jwksRequestsPerMinute: 5,
|
// jwksRequestsPerMinute: 5,
|
||||||
jwksUri: `https://auth.bizmatch.net/realms/${realm}/protocol/openid-connect/certs`,
|
jwksUri: `https://auth.bizmatch.net/realms/${realm}/protocol/openid-connect/certs`,
|
||||||
}),
|
}),
|
||||||
// cache: true, // Enable caching of validated tokens
|
|
||||||
// cacheTTL: 60 * 60 * 1000, // 1 hour cache TTL
|
|
||||||
// secretOrKeyProvider: (request, rawJwtToken, done) => {
|
|
||||||
// const start = Date.now();
|
|
||||||
// const decodedToken = jwt.decode(rawJwtToken, { complete: true });
|
|
||||||
// const kid = decodedToken?.header?.kid;
|
|
||||||
// if (pemCache.has(kid)) {
|
|
||||||
// this.logger.info(`Using cached PEM for kid ${kid}`);
|
|
||||||
// return done(null, pemCache.get(kid));
|
|
||||||
// }
|
|
||||||
// const key = staticCerts.keys.find(k => k.kid === kid);
|
|
||||||
|
|
||||||
// if (!key) {
|
|
||||||
// this.logger.error(`No matching key found for kid: ${kid}`);
|
|
||||||
// return done(new Error('No matching key found'), null);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const publicKey = jwkToPem(key);
|
|
||||||
// pemCache.set(kid, publicKey);
|
|
||||||
// done(null, publicKey);
|
|
||||||
// this.logger.info(`Total JWT verification time: ${Date.now() - start}ms`);
|
|
||||||
// },
|
|
||||||
audience: 'account', // Keycloak Client ID
|
audience: 'account', // Keycloak Client ID
|
||||||
authorize: '',
|
authorize: '',
|
||||||
issuer: `https://auth.bizmatch.net/realms/${realm}`,
|
issuer: `https://auth.bizmatch.net/realms/${realm}`,
|
||||||
|
|
@ -67,7 +45,6 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
}
|
}
|
||||||
const result = { userId: payload.sub, firstname: payload.given_name, lastname: payload.family_name, username: payload.preferred_username, roles: payload.realm_access?.roles };
|
const result = { userId: payload.sub, firstname: payload.given_name, lastname: payload.family_name, username: payload.preferred_username, roles: payload.realm_access?.roles };
|
||||||
this.logger.info(`JWT User: ${JSON.stringify(result)}`); // Debugging: JWT Payload anzeigen
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export class BrokerListingsController {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Post('search')
|
@Post('search')
|
||||||
find(@Body() criteria: UserListingCriteria): any {
|
async find(@Body() criteria: UserListingCriteria): Promise<any> {
|
||||||
return this.userService.searchUserListings(criteria);
|
return await this.userService.searchUserListings(criteria);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -280,14 +280,4 @@ export class BusinessListingService {
|
||||||
})
|
})
|
||||||
.where(sql`${businesses.id} = ${id}`);
|
.where(sql`${businesses.id} = ${id}`);
|
||||||
}
|
}
|
||||||
// ##############################################################
|
|
||||||
// States
|
|
||||||
// ##############################################################
|
|
||||||
// async getStates(): Promise<any[]> {
|
|
||||||
// return await this.conn
|
|
||||||
// .select({ state: businesses.state, count: sql<number>`count(${businesses.id})`.mapWith(Number) })
|
|
||||||
// .from(businesses)
|
|
||||||
// .groupBy(sql`${businesses.state}`)
|
|
||||||
// .orderBy(sql`count desc`);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,48 +16,46 @@ export class BusinessListingsController {
|
||||||
|
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findById(@Request() req, @Param('id') id: string): any {
|
async findById(@Request() req, @Param('id') id: string): Promise<any> {
|
||||||
return this.listingsService.findBusinessesById(id, req.user as JwtUser);
|
return await this.listingsService.findBusinessesById(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Get('favorites/all')
|
@Get('favorites/all')
|
||||||
findFavorites(@Request() req): any {
|
async findFavorites(@Request() req): Promise<any> {
|
||||||
return this.listingsService.findFavoriteListings(req.user as JwtUser);
|
return await this.listingsService.findFavoriteListings(req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get('user/:userid')
|
@Get('user/:userid')
|
||||||
findByUserId(@Request() req, @Param('userid') userid: string): Promise<BusinessListing[]> {
|
async findByUserId(@Request() req, @Param('userid') userid: string): Promise<BusinessListing[]> {
|
||||||
return this.listingsService.findBusinessesByEmail(userid, req.user as JwtUser);
|
return await this.listingsService.findBusinessesByEmail(userid, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Post('find')
|
@Post('find')
|
||||||
find(@Request() req, @Body() criteria: BusinessListingCriteria): any {
|
async find(@Request() req, @Body() criteria: BusinessListingCriteria): Promise<any> {
|
||||||
return this.listingsService.searchBusinessListings(criteria, req.user as JwtUser);
|
return await this.listingsService.searchBusinessListings(criteria, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Post('findTotal')
|
@Post('findTotal')
|
||||||
findTotal(@Request() req, @Body() criteria: BusinessListingCriteria): Promise<number> {
|
async findTotal(@Request() req, @Body() criteria: BusinessListingCriteria): Promise<number> {
|
||||||
return this.listingsService.getBusinessListingsCount(criteria, req.user as JwtUser);
|
return await this.listingsService.getBusinessListingsCount(criteria, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(@Body() listing: any) {
|
async create(@Body() listing: any) {
|
||||||
this.logger.info(`Save Listing`);
|
return await this.listingsService.createListing(listing);
|
||||||
return this.listingsService.createListing(listing);
|
|
||||||
}
|
}
|
||||||
@Put()
|
@Put()
|
||||||
update(@Body() listing: any) {
|
async update(@Body() listing: any) {
|
||||||
this.logger.info(`Save Listing`);
|
return await this.listingsService.updateBusinessListing(listing.id, listing);
|
||||||
return this.listingsService.updateBusinessListing(listing.id, listing);
|
|
||||||
}
|
}
|
||||||
@Delete('listing/:id')
|
@Delete('listing/:id')
|
||||||
deleteById(@Param('id') id: string) {
|
async deleteById(@Param('id') id: string) {
|
||||||
this.listingsService.deleteListing(id);
|
await this.listingsService.deleteListing(id);
|
||||||
}
|
}
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('favorite/:id')
|
@Delete('favorite/:id')
|
||||||
deleteFavorite(@Request() req, @Param('id') id: string) {
|
async deleteFavorite(@Request() req, @Param('id') id: string) {
|
||||||
this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
await this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,18 @@ export class CommercialPropertyListingsController {
|
||||||
|
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findById(@Request() req, @Param('id') id: string): any {
|
async findById(@Request() req, @Param('id') id: string): Promise<any> {
|
||||||
return this.listingsService.findCommercialPropertiesById(id, req.user as JwtUser);
|
return await this.listingsService.findCommercialPropertiesById(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Get('favorites/all')
|
@Get('favorites/all')
|
||||||
findFavorites(@Request() req): any {
|
async findFavorites(@Request() req): Promise<any> {
|
||||||
return this.listingsService.findFavoriteListings(req.user as JwtUser);
|
return await this.listingsService.findFavoriteListings(req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get('user/:email')
|
@Get('user/:email')
|
||||||
findByEmail(@Request() req, @Param('email') email: string): Promise<CommercialPropertyListing[]> {
|
async findByEmail(@Request() req, @Param('email') email: string): Promise<CommercialPropertyListing[]> {
|
||||||
return this.listingsService.findCommercialPropertiesByEmail(email, req.user as JwtUser);
|
return await this.listingsService.findCommercialPropertiesByEmail(email, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Post('find')
|
@Post('find')
|
||||||
|
|
@ -38,27 +38,25 @@ export class CommercialPropertyListingsController {
|
||||||
}
|
}
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Post('findTotal')
|
@Post('findTotal')
|
||||||
findTotal(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
|
async findTotal(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
|
||||||
return this.listingsService.getCommercialPropertiesCount(criteria, req.user as JwtUser);
|
return await this.listingsService.getCommercialPropertiesCount(criteria, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
@Post()
|
@Post()
|
||||||
async create(@Body() listing: any) {
|
async create(@Body() listing: any) {
|
||||||
this.logger.info(`Save Listing`);
|
|
||||||
return await this.listingsService.createListing(listing);
|
return await this.listingsService.createListing(listing);
|
||||||
}
|
}
|
||||||
@Put()
|
@Put()
|
||||||
async update(@Body() listing: any) {
|
async update(@Body() listing: any) {
|
||||||
this.logger.info(`Save Listing`);
|
|
||||||
return await this.listingsService.updateCommercialPropertyListing(listing.id, listing);
|
return await this.listingsService.updateCommercialPropertyListing(listing.id, listing);
|
||||||
}
|
}
|
||||||
@Delete('listing/:id/:imagePath')
|
@Delete('listing/:id/:imagePath')
|
||||||
deleteById(@Param('id') id: string, @Param('imagePath') imagePath: string) {
|
async deleteById(@Param('id') id: string, @Param('imagePath') imagePath: string) {
|
||||||
this.listingsService.deleteListing(id);
|
await this.listingsService.deleteListing(id);
|
||||||
this.fileService.deleteDirectoryIfExists(imagePath);
|
this.fileService.deleteDirectoryIfExists(imagePath);
|
||||||
}
|
}
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('favorite/:id')
|
@Delete('favorite/:id')
|
||||||
deleteFavorite(@Request() req, @Param('id') id: string) {
|
async deleteFavorite(@Request() req, @Param('id') id: string) {
|
||||||
this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
await this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,19 @@ import { MailService } from './mail.service';
|
||||||
export class MailController {
|
export class MailController {
|
||||||
constructor(private mailService: MailService) {}
|
constructor(private mailService: MailService) {}
|
||||||
@Post()
|
@Post()
|
||||||
sendEMail(@Body() mailInfo: MailInfo): Promise<void | ErrorResponse> {
|
async sendEMail(@Body() mailInfo: MailInfo): Promise<void | ErrorResponse> {
|
||||||
if (mailInfo.listing) {
|
if (mailInfo.listing) {
|
||||||
return this.mailService.sendInquiry(mailInfo);
|
return await this.mailService.sendInquiry(mailInfo);
|
||||||
} else {
|
} else {
|
||||||
return this.mailService.sendRequest(mailInfo);
|
return await this.mailService.sendRequest(mailInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Post('subscriptionConfirmation')
|
@Post('subscriptionConfirmation')
|
||||||
sendSubscriptionConfirmation(@Body() user: User): Promise<void | ErrorResponse> {
|
async sendSubscriptionConfirmation(@Body() user: User): Promise<void | ErrorResponse> {
|
||||||
return this.mailService.sendSubscriptionConfirmation(user);
|
return await this.mailService.sendSubscriptionConfirmation(user);
|
||||||
}
|
}
|
||||||
@Post('send2Friend')
|
@Post('send2Friend')
|
||||||
send2Friend(@Body() shareByEMail: ShareByEMail): Promise<void | ErrorResponse> {
|
async send2Friend(@Body() shareByEMail: ShareByEMail): Promise<void | ErrorResponse> {
|
||||||
return this.mailService.send2Friend(shareByEMail);
|
return await this.mailService.send2Friend(shareByEMail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,20 @@
|
||||||
|
import { LoggerService } from '@nestjs/common';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const server = express();
|
const server = express();
|
||||||
server.set('trust proxy', true);
|
server.set('trust proxy', true);
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
// const logger = app.get<Logger>(WINSTON_MODULE_NEST_PROVIDER);
|
||||||
|
const logger = app.get<LoggerService>(WINSTON_MODULE_NEST_PROVIDER);
|
||||||
|
app.useLogger(logger);
|
||||||
app.use('/bizmatch/payment/webhook', bodyParser.raw({ type: 'application/json' }));
|
app.use('/bizmatch/payment/webhook', bodyParser.raw({ type: 'application/json' }));
|
||||||
app.setGlobalPrefix('bizmatch');
|
app.setGlobalPrefix('bizmatch');
|
||||||
|
|
||||||
app.enableCors({
|
app.enableCors({
|
||||||
origin: '*',
|
origin: '*',
|
||||||
//origin: 'http://localhost:4200', // Die URL Ihrer Angular-App
|
//origin: 'http://localhost:4200', // Die URL Ihrer Angular-App
|
||||||
|
|
|
||||||
|
|
@ -17,21 +17,21 @@ export class PaymentController {
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@Get('user/all')
|
@Get('user/all')
|
||||||
async getAllStripeCustomer(): Promise<Stripe.Customer[]> {
|
async getAllStripeCustomer(): Promise<Stripe.Customer[]> {
|
||||||
return this.paymentService.getAllStripeCustomer();
|
return await this.paymentService.getAllStripeCustomer();
|
||||||
}
|
}
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@Get('subscription/all')
|
@Get('subscription/all')
|
||||||
async getAllStripeSubscriptions(): Promise<Stripe.Subscription[]> {
|
async getAllStripeSubscriptions(): Promise<Stripe.Subscription[]> {
|
||||||
return this.paymentService.getAllStripeSubscriptions();
|
return await this.paymentService.getAllStripeSubscriptions();
|
||||||
}
|
}
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@Get('paymentmethod/:email')
|
@Get('paymentmethod/:email')
|
||||||
async getStripePaymentMethods(@Param('email') email: string): Promise<Stripe.PaymentMethod[]> {
|
async getStripePaymentMethods(@Param('email') email: string): Promise<Stripe.PaymentMethod[]> {
|
||||||
return this.paymentService.getStripePaymentMethod(email);
|
return await this.paymentService.getStripePaymentMethod(email);
|
||||||
}
|
}
|
||||||
@Post('create-checkout-session')
|
@Post('create-checkout-session')
|
||||||
async createCheckoutSession(@Body() checkout: Checkout) {
|
async createCheckoutSession(@Body() checkout: Checkout) {
|
||||||
return this.paymentService.createCheckoutSession(checkout);
|
return await this.paymentService.createCheckoutSession(checkout);
|
||||||
}
|
}
|
||||||
@Post('webhook')
|
@Post('webhook')
|
||||||
async handleWebhook(@Req() req: Request, @Res() res: Response): Promise<void> {
|
async handleWebhook(@Req() req: Request, @Res() res: Response): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,6 @@ export class PaymentService {
|
||||||
username: keycloakUser.email,
|
username: keycloakUser.email,
|
||||||
roles: [],
|
roles: [],
|
||||||
});
|
});
|
||||||
this.logger.info(JSON.stringify(session));
|
|
||||||
user.subscriptionId = session.subscription as string;
|
user.subscriptionId = session.subscription as string;
|
||||||
const subscription = await this.stripe.subscriptions.retrieve(user.subscriptionId);
|
const subscription = await this.stripe.subscriptions.retrieve(user.subscriptionId);
|
||||||
user.customerType = 'professional';
|
user.customerType = 'professional';
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,21 @@ export class RequestDurationMiddleware implements NestMiddleware {
|
||||||
|
|
||||||
use(req: Request, res: Response, next: NextFunction) {
|
use(req: Request, res: Response, next: NextFunction) {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
|
const clientIp = req.ip;
|
||||||
|
this.logger.log(`Entering ${req.method} ${req.originalUrl} from ${clientIp}`);
|
||||||
|
|
||||||
res.on('finish', () => {
|
res.on('finish', () => {
|
||||||
// const duration = Date.now() - start;
|
|
||||||
// this.logger.log(`${req.method} ${req.url} - ${duration}ms`);
|
|
||||||
const duration = Date.now() - start;
|
const duration = Date.now() - start;
|
||||||
let logMessage = `${req.method} ${req.url} - ${duration}ms`;
|
let logMessage = `${req.method} ${req.originalUrl} - ${duration}ms - IP: ${clientIp}`;
|
||||||
|
|
||||||
if (req.method === 'POST' || req.method === 'PUT') {
|
if (req.method === 'POST' || req.method === 'PUT') {
|
||||||
const body = JSON.stringify(req.body);
|
const body = JSON.stringify(req.body);
|
||||||
logMessage += ` - Body: ${body}`;
|
logMessage += ` - Incoming Body: ${body}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.log(logMessage);
|
this.logger.log(logMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,13 @@ export class UserController {
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get()
|
@Get()
|
||||||
async findByMail(@Request() req, @Query('mail') mail: string): Promise<User> {
|
async findByMail(@Request() req, @Query('mail') mail: string): Promise<User> {
|
||||||
this.logger.info(`Searching for user with EMail: ${mail}`);
|
|
||||||
const user = await this.userService.getUserByMail(mail, req.user as JwtUser);
|
const user = await this.userService.getUserByMail(mail, req.user as JwtUser);
|
||||||
this.logger.info(`Found user: ${JSON.stringify(user)}`);
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
async findById(@Param('id') id: string): Promise<User> {
|
async findById(@Param('id') id: string): Promise<User> {
|
||||||
this.logger.info(`Searching for user with ID: ${id}`);
|
|
||||||
const user = await this.userService.getUserById(id);
|
const user = await this.userService.getUserById(id);
|
||||||
this.logger.info(`Found user: ${JSON.stringify(user)}`);
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
|
|
@ -40,10 +36,8 @@ export class UserController {
|
||||||
}
|
}
|
||||||
@Post()
|
@Post()
|
||||||
async save(@Body() user: any): Promise<User> {
|
async save(@Body() user: any): Promise<User> {
|
||||||
this.logger.info(`Saving user: ${JSON.stringify(user)}`);
|
|
||||||
try {
|
try {
|
||||||
const savedUser = await this.userService.saveUser(user);
|
const savedUser = await this.userService.saveUser(user);
|
||||||
this.logger.info(`User persisted: ${JSON.stringify(savedUser)}`);
|
|
||||||
return savedUser;
|
return savedUser;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof ZodError) {
|
if (error instanceof ZodError) {
|
||||||
|
|
@ -60,27 +54,23 @@ export class UserController {
|
||||||
}
|
}
|
||||||
@Post('guaranteed')
|
@Post('guaranteed')
|
||||||
async saveGuaranteed(@Body() user: any): Promise<User> {
|
async saveGuaranteed(@Body() user: any): Promise<User> {
|
||||||
this.logger.info(`Saving user guaranteed: ${JSON.stringify(user)}`);
|
|
||||||
const savedUser = await this.userService.saveUser(user, false);
|
const savedUser = await this.userService.saveUser(user, false);
|
||||||
this.logger.info(`User persisted guaranteed: ${JSON.stringify(savedUser)}`);
|
|
||||||
return savedUser;
|
return savedUser;
|
||||||
}
|
}
|
||||||
@Post('search')
|
@Post('search')
|
||||||
async find(@Body() criteria: UserListingCriteria): Promise<{ results: User[]; totalCount: number }> {
|
async find(@Body() criteria: UserListingCriteria): Promise<{ results: User[]; totalCount: number }> {
|
||||||
this.logger.info(`Searching for users with criteria: ${JSON.stringify(criteria)}`);
|
|
||||||
const foundUsers = await this.userService.searchUserListings(criteria);
|
const foundUsers = await this.userService.searchUserListings(criteria);
|
||||||
this.logger.info(`Found users: ${JSON.stringify(foundUsers)}`);
|
|
||||||
return foundUsers;
|
return foundUsers;
|
||||||
}
|
}
|
||||||
@Post('findTotal')
|
@Post('findTotal')
|
||||||
findTotal(@Body() criteria: UserListingCriteria): Promise<number> {
|
async findTotal(@Body() criteria: UserListingCriteria): Promise<number> {
|
||||||
return this.userService.getUserListingsCount(criteria);
|
return await this.userService.getUserListingsCount(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Get('subscriptions/:id')
|
@Get('subscriptions/:id')
|
||||||
async findSubscriptionsById(@Param('id') id: string): Promise<Subscription[]> {
|
async findSubscriptionsById(@Param('id') id: string): Promise<Subscription[]> {
|
||||||
const subscriptions = this.fileService.getSubscriptions();
|
const subscriptions = [];
|
||||||
const user = await this.userService.getUserById(id);
|
const user = await this.userService.getUserById(id);
|
||||||
subscriptions.forEach(s => {
|
subscriptions.forEach(s => {
|
||||||
s.userId = user.id;
|
s.userId = user.id;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ export class HeaderComponent {
|
||||||
this.baseRoute = url.split('/')[1]; // Nimmt den ersten Teil der Route nach dem ersten '/'
|
this.baseRoute = url.split('/')[1]; // Nimmt den ersten Teil der Route nach dem ersten '/'
|
||||||
const specialRoutes = [, '', ''];
|
const specialRoutes = [, '', ''];
|
||||||
this.criteria = getCriteriaProxy(this.baseRoute, this);
|
this.criteria = getCriteriaProxy(this.baseRoute, this);
|
||||||
this.searchService.search(this.criteria);
|
// this.searchService.search(this.criteria);
|
||||||
}
|
}
|
||||||
setupSortByOptions() {
|
setupSortByOptions() {
|
||||||
this.sortByOptions = [];
|
this.sortByOptions = [];
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { CommonModule, NgOptimizedImage } from '@angular/common';
|
||||||
import { ChangeDetectorRef, Component } from '@angular/core';
|
import { ChangeDetectorRef, Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { LISTINGS_PER_PAGE, ListingType, UserListingCriteria, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { LISTINGS_PER_PAGE, ListingType, UserListingCriteria, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
|
|
@ -13,7 +14,7 @@ import { SearchService } from '../../../services/search.service';
|
||||||
import { SelectOptionsService } from '../../../services/select-options.service';
|
import { SelectOptionsService } from '../../../services/select-options.service';
|
||||||
import { UserService } from '../../../services/user.service';
|
import { UserService } from '../../../services/user.service';
|
||||||
import { getCriteriaStateObject } from '../../../utils/utils';
|
import { getCriteriaStateObject } from '../../../utils/utils';
|
||||||
|
@UntilDestroy()
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-broker-listings',
|
selector: 'app-broker-listings',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
@ -55,7 +56,7 @@ export class BrokerListingsComponent {
|
||||||
) {
|
) {
|
||||||
this.criteria = getCriteriaStateObject('brokerListings');
|
this.criteria = getCriteriaStateObject('brokerListings');
|
||||||
this.init();
|
this.init();
|
||||||
this.searchService.currentCriteria.subscribe(criteria => {
|
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(criteria => {
|
||||||
if (criteria && criteria.criteriaType === 'brokerListings') {
|
if (criteria && criteria.criteriaType === 'brokerListings') {
|
||||||
this.criteria = criteria as UserListingCriteria;
|
this.criteria = criteria as UserListingCriteria;
|
||||||
this.search();
|
this.search();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||||
import { ChangeDetectorRef, Component } from '@angular/core';
|
import { ChangeDetectorRef, Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { BusinessListingCriteria, LISTINGS_PER_PAGE, ListingType, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { BusinessListingCriteria, LISTINGS_PER_PAGE, ListingType, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
|
|
@ -12,7 +13,7 @@ import { ListingsService } from '../../../services/listings.service';
|
||||||
import { SearchService } from '../../../services/search.service';
|
import { SearchService } from '../../../services/search.service';
|
||||||
import { SelectOptionsService } from '../../../services/select-options.service';
|
import { SelectOptionsService } from '../../../services/select-options.service';
|
||||||
import { getCriteriaStateObject } from '../../../utils/utils';
|
import { getCriteriaStateObject } from '../../../utils/utils';
|
||||||
|
@UntilDestroy()
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-business-listings',
|
selector: 'app-business-listings',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
@ -51,7 +52,7 @@ export class BusinessListingsComponent {
|
||||||
) {
|
) {
|
||||||
this.criteria = getCriteriaStateObject('businessListings');
|
this.criteria = getCriteriaStateObject('businessListings');
|
||||||
this.init();
|
this.init();
|
||||||
this.searchService.currentCriteria.subscribe(criteria => {
|
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(criteria => {
|
||||||
if (criteria && criteria.criteriaType === 'businessListings') {
|
if (criteria && criteria.criteriaType === 'businessListings') {
|
||||||
this.criteria = criteria as BusinessListingCriteria;
|
this.criteria = criteria as BusinessListingCriteria;
|
||||||
this.search();
|
this.search();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||||
import { ChangeDetectorRef, Component } from '@angular/core';
|
import { ChangeDetectorRef, Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { CommercialPropertyListingCriteria, LISTINGS_PER_PAGE, ResponseCommercialPropertyListingArray } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { CommercialPropertyListingCriteria, LISTINGS_PER_PAGE, ResponseCommercialPropertyListingArray } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
|
|
@ -12,7 +13,7 @@ import { ListingsService } from '../../../services/listings.service';
|
||||||
import { SearchService } from '../../../services/search.service';
|
import { SearchService } from '../../../services/search.service';
|
||||||
import { SelectOptionsService } from '../../../services/select-options.service';
|
import { SelectOptionsService } from '../../../services/select-options.service';
|
||||||
import { getCriteriaStateObject } from '../../../utils/utils';
|
import { getCriteriaStateObject } from '../../../utils/utils';
|
||||||
|
@UntilDestroy()
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-commercial-property-listings',
|
selector: 'app-commercial-property-listings',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
@ -50,7 +51,7 @@ export class CommercialPropertyListingsComponent {
|
||||||
) {
|
) {
|
||||||
this.criteria = getCriteriaStateObject('commercialPropertyListings');
|
this.criteria = getCriteriaStateObject('commercialPropertyListings');
|
||||||
this.init();
|
this.init();
|
||||||
this.searchService.currentCriteria.subscribe(criteria => {
|
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(criteria => {
|
||||||
if (criteria && criteria.criteriaType === 'commercialPropertyListings') {
|
if (criteria && criteria.criteriaType === 'commercialPropertyListings') {
|
||||||
this.criteria = criteria as CommercialPropertyListingCriteria;
|
this.criteria = criteria as CommercialPropertyListingCriteria;
|
||||||
this.search();
|
this.search();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue