diff --git a/bizmatch-server/dbschema.ts b/bizmatch-server/dbschema.ts deleted file mode 100644 index 0874b5f..0000000 --- a/bizmatch-server/dbschema.ts +++ /dev/null @@ -1,239 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ - - -/** - * AUTO-GENERATED FILE - DO NOT EDIT! - * - * This file was automatically generated by pg-to-ts v.4.1.1 - * $ pg-to-ts generate -c postgresql://username:password@localhost:5432/bizmatch -t businesses -t commercials -t users -s public - * - */ - - -export type Json = unknown; -export type customerSubType = 'appraiser' | 'attorney' | 'broker' | 'cpa' | 'surveyor' | 'titleCompany'; -export type customerType = 'buyer' | 'professional'; -export type gender = 'female' | 'male'; -export type listingsCategory = 'business' | 'commercialProperty'; - -// Table businesses -export interface Businesses { - id: string; - email: string | null; - type: string | null; - title: string | null; - description: string | null; - city: string | null; - state: string | null; - zipCode: number | null; - county: string | null; - price: number | null; - favoritesForUser: string[] | null; - draft: boolean | null; - listingsCategory: listingsCategory | null; - realEstateIncluded: boolean | null; - leasedLocation: boolean | null; - franchiseResale: boolean | null; - salesRevenue: number | null; - cashFlow: number | null; - supportAndTraining: string | null; - employees: number | null; - established: number | null; - internalListingNumber: number | null; - reasonForSale: string | null; - brokerLicencing: string | null; - internals: string | null; - imageName: string | null; - created: Date | null; - updated: Date | null; - visits: number | null; - lastVisit: Date | null; - latitude: number | null; - longitude: number | null; -} -export interface BusinessesInput { - id?: string; - email?: string | null; - type?: string | null; - title?: string | null; - description?: string | null; - city?: string | null; - state?: string | null; - zipCode?: number | null; - county?: string | null; - price?: number | null; - favoritesForUser?: string[] | null; - draft?: boolean | null; - listingsCategory?: listingsCategory | null; - realEstateIncluded?: boolean | null; - leasedLocation?: boolean | null; - franchiseResale?: boolean | null; - salesRevenue?: number | null; - cashFlow?: number | null; - supportAndTraining?: string | null; - employees?: number | null; - established?: number | null; - internalListingNumber?: number | null; - reasonForSale?: string | null; - brokerLicencing?: string | null; - internals?: string | null; - imageName?: string | null; - created?: Date | null; - updated?: Date | null; - visits?: number | null; - lastVisit?: Date | null; - latitude?: number | null; - longitude?: number | null; -} -const businesses = { - tableName: 'businesses', - columns: ['id', 'email', 'type', 'title', 'description', 'city', 'state', 'zipCode', 'county', 'price', 'favoritesForUser', 'draft', 'listingsCategory', 'realEstateIncluded', 'leasedLocation', 'franchiseResale', 'salesRevenue', 'cashFlow', 'supportAndTraining', 'employees', 'established', 'internalListingNumber', 'reasonForSale', 'brokerLicencing', 'internals', 'imageName', 'created', 'updated', 'visits', 'lastVisit', 'latitude', 'longitude'], - requiredForInsert: [], - primaryKey: 'id', - foreignKeys: { email: { table: 'users', column: 'email', $type: null as unknown as Users }, }, - $type: null as unknown as Businesses, - $input: null as unknown as BusinessesInput -} as const; - -// Table commercials -export interface Commercials { - id: string; - serialId: number; - email: string | null; - type: string | null; - title: string | null; - description: string | null; - city: string | null; - state: string | null; - price: number | null; - favoritesForUser: string[] | null; - listingsCategory: listingsCategory | null; - hideImage: boolean | null; - draft: boolean | null; - zipCode: number | null; - county: string | null; - imageOrder: string[] | null; - imagePath: string | null; - created: Date | null; - updated: Date | null; - visits: number | null; - lastVisit: Date | null; - latitude: number | null; - longitude: number | null; -} -export interface CommercialsInput { - id?: string; - serialId?: number; - email?: string | null; - type?: string | null; - title?: string | null; - description?: string | null; - city?: string | null; - state?: string | null; - price?: number | null; - favoritesForUser?: string[] | null; - listingsCategory?: listingsCategory | null; - hideImage?: boolean | null; - draft?: boolean | null; - zipCode?: number | null; - county?: string | null; - imageOrder?: string[] | null; - imagePath?: string | null; - created?: Date | null; - updated?: Date | null; - visits?: number | null; - lastVisit?: Date | null; - latitude?: number | null; - longitude?: number | null; -} -const commercials = { - tableName: 'commercials', - columns: ['id', 'serialId', 'email', 'type', 'title', 'description', 'city', 'state', 'price', 'favoritesForUser', 'listingsCategory', 'hideImage', 'draft', 'zipCode', 'county', 'imageOrder', 'imagePath', 'created', 'updated', 'visits', 'lastVisit', 'latitude', 'longitude'], - requiredForInsert: [], - primaryKey: 'id', - foreignKeys: { email: { table: 'users', column: 'email', $type: null as unknown as Users }, }, - $type: null as unknown as Commercials, - $input: null as unknown as CommercialsInput -} as const; - -// Table users -export interface Users { - id: string; - firstname: string; - lastname: string; - email: string; - phoneNumber: string | null; - description: string | null; - companyName: string | null; - companyOverview: string | null; - companyWebsite: string | null; - companyLocation: string | null; - offeredServices: string | null; - areasServed: Json | null; - hasProfile: boolean | null; - hasCompanyLogo: boolean | null; - licensedIn: Json | null; - gender: gender | null; - customerType: customerType | null; - customerSubType: customerSubType | null; - created: Date | null; - updated: Date | null; - latitude: number | null; - longitude: number | null; -} -export interface UsersInput { - id?: string; - firstname: string; - lastname: string; - email: string; - phoneNumber?: string | null; - description?: string | null; - companyName?: string | null; - companyOverview?: string | null; - companyWebsite?: string | null; - companyLocation?: string | null; - offeredServices?: string | null; - areasServed?: Json | null; - hasProfile?: boolean | null; - hasCompanyLogo?: boolean | null; - licensedIn?: Json | null; - gender?: gender | null; - customerType?: customerType | null; - customerSubType?: customerSubType | null; - created?: Date | null; - updated?: Date | null; - latitude?: number | null; - longitude?: number | null; -} -const users = { - tableName: 'users', - columns: ['id', 'firstname', 'lastname', 'email', 'phoneNumber', 'description', 'companyName', 'companyOverview', 'companyWebsite', 'companyLocation', 'offeredServices', 'areasServed', 'hasProfile', 'hasCompanyLogo', 'licensedIn', 'gender', 'customerType', 'customerSubType', 'created', 'updated', 'latitude', 'longitude'], - requiredForInsert: ['firstname', 'lastname', 'email'], - primaryKey: 'id', - foreignKeys: {}, - $type: null as unknown as Users, - $input: null as unknown as UsersInput -} as const; - - -export interface TableTypes { - businesses: { - select: Businesses; - input: BusinessesInput; - }; - commercials: { - select: Commercials; - input: CommercialsInput; - }; - users: { - select: Users; - input: UsersInput; - }; -} - -export const tables = { - businesses, - commercials, - users, -} diff --git a/bizmatch-server/package.json b/bizmatch-server/package.json index 21a8b10..fb5c83b 100644 --- a/bizmatch-server/package.json +++ b/bizmatch-server/package.json @@ -5,14 +5,14 @@ "author": "", "private": true, "license": "UNLICENSED", - "type": "module", "scripts": { "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "HOST_NAME=localhost nest start", - "start:dev": "HOST_NAME=dev.bizmatch.net nest start --watch", + "start:local": "HOST_NAME=localhost node dist/src/main", + "start:dev": "HOST_NAME=dev.bizmatch.net node dist/src/main", "start:debug": "nest start --debug --watch", - "start:prod": "HOST_NAME=www.bizmatch.net node dist/main", + "start:prod": "HOST_NAME=www.bizmatch.net node dist/src/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", @@ -42,6 +42,8 @@ "fs-extra": "^11.2.0", "groq-sdk": "^0.5.0", "handlebars": "^4.7.8", + "jsonwebtoken": "^9.0.2", + "jwk-to-pem": "^2.0.6", "jwks-rsa": "^3.1.0", "ky": "^1.4.0", "nest-winston": "^1.9.4", @@ -71,6 +73,8 @@ "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", "@types/jest": "^29.5.2", + "@types/jsonwebtoken": "^9.0.6", + "@types/jwk-to-pem": "^2.0.3", "@types/multer": "^1.4.11", "@types/node": "^20.11.19", "@types/nodemailer": "^6.4.14", @@ -117,4 +121,4 @@ "coverageDirectory": "../coverage", "testEnvironment": "node" } -} +} \ No newline at end of file diff --git a/bizmatch-server/src/ai/ai.controller.ts b/bizmatch-server/src/ai/ai.controller.ts index 9e09e40..4f438c0 100644 --- a/bizmatch-server/src/ai/ai.controller.ts +++ b/bizmatch-server/src/ai/ai.controller.ts @@ -1,5 +1,5 @@ import { Body, Controller, Post } from '@nestjs/common'; -import { AiService } from './ai.service.js'; +import { AiService } from './ai.service'; @Controller('ai') export class AiController { diff --git a/bizmatch-server/src/ai/ai.module.ts b/bizmatch-server/src/ai/ai.module.ts index 5360cc5..2f59dd3 100644 --- a/bizmatch-server/src/ai/ai.module.ts +++ b/bizmatch-server/src/ai/ai.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { AiController } from './ai.controller.js'; -import { AiService } from './ai.service.js'; +import { AiController } from './ai.controller'; +import { AiService } from './ai.service'; @Module({ controllers: [AiController], diff --git a/bizmatch-server/src/app.controller.ts b/bizmatch-server/src/app.controller.ts index 4feaacd..91cb182 100644 --- a/bizmatch-server/src/app.controller.ts +++ b/bizmatch-server/src/app.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Request, UseGuards } from '@nestjs/common'; -import { AppService } from './app.service.js'; -import { AuthService } from './auth/auth.service.js'; -import { JwtAuthGuard } from './jwt-auth/jwt-auth.guard.js'; +import { AppService } from './app.service'; +import { AuthService } from './auth/auth.service'; +import { JwtAuthGuard } from './jwt-auth/jwt-auth.guard'; @Controller() export class AppController { diff --git a/bizmatch-server/src/app.module.ts b/bizmatch-server/src/app.module.ts index 0541f07..9a5292c 100644 --- a/bizmatch-server/src/app.module.ts +++ b/bizmatch-server/src/app.module.ts @@ -5,22 +5,23 @@ import * as dotenv from 'dotenv'; import fs from 'fs-extra'; import { WinstonModule, utilities as nestWinstonModuleUtilities } from 'nest-winston'; import * as winston from 'winston'; -import { AiModule } from './ai/ai.module.js'; -import { AppController } from './app.controller.js'; -import { AppService } from './app.service.js'; -import { AuthModule } from './auth/auth.module.js'; -import { FileService } from './file/file.service.js'; -import { GeoModule } from './geo/geo.module.js'; -import { ImageModule } from './image/image.module.js'; -import { ListingsModule } from './listings/listings.module.js'; -import { LogController } from './log/log.controller.js'; -import { LogModule } from './log/log.module.js'; +import { AiModule } from './ai/ai.module'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { AuthModule } from './auth/auth.module'; +import { FileService } from './file/file.service'; +import { GeoModule } from './geo/geo.module'; +import { ImageModule } from './image/image.module'; +import { ListingsModule } from './listings/listings.module'; +import { LogController } from './log/log.controller'; +import { LogModule } from './log/log.module'; -import { MailModule } from './mail/mail.module.js'; -import { PaymentModule } from './payment/payment.module.js'; -import { RequestDurationMiddleware } from './request-duration/request-duration.middleware.js'; -import { SelectOptionsModule } from './select-options/select-options.module.js'; -import { UserModule } from './user/user.module.js'; +import { JwtStrategy } from './jwt.strategy'; +import { MailModule } from './mail/mail.module'; +import { PaymentModule } from './payment/payment.module'; +import { RequestDurationMiddleware } from './request-duration/request-duration.middleware'; +import { SelectOptionsModule } from './select-options/select-options.module'; +import { UserModule } from './user/user.module'; // const __filename = fileURLToPath(import.meta.url); // const __dirname = path.dirname(__filename); @@ -86,7 +87,7 @@ loadEnvFiles(); PaymentModule, ], controllers: [AppController, LogController], - providers: [AppService, FileService], + providers: [AppService, FileService, JwtStrategy], }) export class AppModule { configure(consumer: MiddlewareConsumer) { diff --git a/bizmatch-server/src/assets/keycloak-certs.json b/bizmatch-server/src/assets/keycloak-certs.json new file mode 100644 index 0000000..b8c94aa --- /dev/null +++ b/bizmatch-server/src/assets/keycloak-certs.json @@ -0,0 +1,30 @@ +{ + "keys": [ + { + "kid": "0NxHr10meEVrGYmGlWz_WHiTPxbuNaU6vmShQYWFBh8", + "kty": "RSA", + "alg": "RSA-OAEP", + "use": "enc", + "n": "7hzWTnW6WOrZQmeZ26fD5Fu0NvxiQP8pVfesK9MXO4R1gjGlPViGWCdUKrG9Ux6h9X6SXHOWPWZmbfmjNeK7kQOjYPS_06GQ3X19tFikdWoufZMTpAb6p9CENsIbpzX9c1JZRs1xSJ9B505NjLVp29WzhugQfQR2ctv4nLZYmo1ojGjUQMGPNO_4bMqzO_luBQGEAqnRojZzxHVp-ruNyR9DmQbPbUULrOOXfGjCeAYukZ-5UHl6pngk8b6NKdGq6E_qxNsZVStWxbeGAG5UhxSl6oaGL8R0fP9JiAtlWfubJsCtibk712MaMb59JEdr_f3R3pXN7He8brS3smPgcQ", + "e": "AQAB", + "x5c": [ + "MIIClTCCAX0CBgGN9oQZDTANBgkqhkiG9w0BAQsFADAOMQwwCgYDVQQDDANkZXYwHhcNMjQwMjI5MjAxNjA4WhcNMzQwMjI4MjAxNzQ4WjAOMQwwCgYDVQQDDANkZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDuHNZOdbpY6tlCZ5nbp8PkW7Q2/GJA/ylV96wr0xc7hHWCMaU9WIZYJ1Qqsb1THqH1fpJcc5Y9ZmZt+aM14ruRA6Ng9L/ToZDdfX20WKR1ai59kxOkBvqn0IQ2whunNf1zUllGzXFIn0HnTk2MtWnb1bOG6BB9BHZy2/ictliajWiMaNRAwY807/hsyrM7+W4FAYQCqdGiNnPEdWn6u43JH0OZBs9tRQus45d8aMJ4Bi6Rn7lQeXqmeCTxvo0p0aroT+rE2xlVK1bFt4YAblSHFKXqhoYvxHR8/0mIC2VZ+5smwK2JuTvXYxoxvn0kR2v9/dHelc3sd7xutLeyY+BxAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAL5CFk/T8Thoi6yNRg7CSiWuehCwwzC+FfsoVQNkcq2loZYgWjO34b9fXysT0xXLJOAnw0+xvwAhbVdBwTathQb2PJST5Ei6RGIOsT2gfE91Je3BGpXnsNNDja0be1bS/uN07aa3MshkgVBOYVDe2FoK7g4zSgViMXLEzGpRdio9mIrH3KADdEAFrhiNClu19gefONT86vUvIpSCS4XJ+nSUPbNkbhe9MlvZ8TRWFMoUzuZML6Xf+FbimAv1ZBk1NWobWPtyaDFF9Lgse7LHGiKPKvBHonVMbWYf7Lk8nGA7/90WVOX5Fd2LItH/13rPNlwbspAcz/nB2groa8/DrdE=" + ], + "x5t": "3ZyfzL7Gn0dcNq8H8X1L0uagQMI", + "x5t#S256": "Wwu30X3ZnchcXsJHJmOHT8BLOFCH6y2TpO3hyzojhdk" + }, + { + "kid": "yAfIWlA3TFvR_h112X4sJHK0kog4_4xDLkRnJnzTv98", + "kty": "RSA", + "alg": "RS256", + "use": "sig", + "n": "xpYiq2XOtKV-xeLmFM-4sUWDpzw1UJlN9NXj833MZKsW_bwWixlsJTsB-2kfQ6mXUTbfxsuoZuWMZdQVpsWoKOPeK1Gsd8Gsoa0v2pv3uzPA8_SLqDrBNtIz9mDJc6jf-XkOdtAfPzW_aMf4TzThzIkEH5ptUde0gDKNd8je2lFo4loFJkLhOO2HZ7cLQcspXB_vNqpjAMED15GmGRizeTsA4IWC9WjGyziVvlbgQqC0MqCieT2r4dB0FZGWFwzlm-EhvyHu6G1Hw55jn5AcEHh5fke9XvTBzF6MmM_MQEDc9QWHj16ekVdQB7fxzBHbyLMr3ivQizcHAGYvemNhHw", + "e": "AQAB", + "x5c": [ + "MIIClTCCAX0CBgGN9oQYYzANBgkqhkiG9w0BAQsFADAOMQwwCgYDVQQDDANkZXYwHhcNMjQwMjI5MjAxNjA4WhcNMzQwMjI4MjAxNzQ4WjAOMQwwCgYDVQQDDANkZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGliKrZc60pX7F4uYUz7ixRYOnPDVQmU301ePzfcxkqxb9vBaLGWwlOwH7aR9DqZdRNt/Gy6hm5Yxl1BWmxago494rUax3wayhrS/am/e7M8Dz9IuoOsE20jP2YMlzqN/5eQ520B8/Nb9ox/hPNOHMiQQfmm1R17SAMo13yN7aUWjiWgUmQuE47YdntwtByylcH+82qmMAwQPXkaYZGLN5OwDghYL1aMbLOJW+VuBCoLQyoKJ5Pavh0HQVkZYXDOWb4SG/Ie7obUfDnmOfkBwQeHl+R71e9MHMXoyYz8xAQNz1BYePXp6RV1AHt/HMEdvIsyveK9CLNwcAZi96Y2EfAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABQaqejZ5iWybWeiK0j9iKTn5DNr8LFXdJNRk+odI5TwCtaVDTCQRrF1KKT6F6RmzQyc6xyKojtnI1mKjs+Wo8vYE483pDgoGkv7UquKeQAWbXRajbkpGKasIux7m0MgDhPGKtxoha3kI2Yi2dOFYGdRuqv35/ZD+9nfHfk03fylrf5saroOYBGW6RRpdygB14zQ5ZbXin6gVJSBuJWMiWpxzAB05llZVaHOJ7kO+402YV2/l2TJm0bc883HZuIKxh11PI20lZop9ZwctVtmwf2iFfMfQgQ5wZpV/1gEMynVypxe6OY7biQyIERX6oEFWmZIOrnytSawLyy5gCFrStY=" + ], + "x5t": "L27m4VtyyHlrajDI_47_mmRSP08", + "x5t#S256": "KOcIpGLNb4ZGg_G2jc6ieZC_86-QQjoaSsMDoV0RWZg" + } + ] +} \ No newline at end of file diff --git a/bizmatch-server/src/auth/auth.controller.ts b/bizmatch-server/src/auth/auth.controller.ts index 229bbf0..379c79a 100644 --- a/bizmatch-server/src/auth/auth.controller.ts +++ b/bizmatch-server/src/auth/auth.controller.ts @@ -1,6 +1,6 @@ -import { Controller, Get, Param, UseGuards } from '@nestjs/common'; -import { AdminAuthGuard } from '../jwt-auth/admin-auth.guard.js'; -import { AuthService } from './auth.service.js'; +import { Controller, Get, UseGuards } from '@nestjs/common'; +import { AdminAuthGuard } from '../jwt-auth/admin-auth.guard'; +import { AuthService } from './auth.service'; @Controller('auth') export class AuthController { @@ -18,15 +18,15 @@ export class AuthController { return this.authService.getUsers(); } - @UseGuards(AdminAuthGuard) - @Get('user/:userid') - getUser(@Param('userid') userId: string): any { - return this.authService.getUser(userId); - } + // @UseGuards(AdminAuthGuard) + // @Get('user/:userid') + // getUser(@Param('userid') userId: string): any { + // return this.authService.getUser(userId); + // } - @UseGuards(AdminAuthGuard) - @Get('user/:userid/lastlogin') //e0811669-c7eb-4e5e-a699-e8334d5c5b01 -> aknuth - getLastLogin(@Param('userid') userId: string): any { - return this.authService.getLastLogin(userId); - } + // @UseGuards(AdminAuthGuard) + // @Get('user/:userid/lastlogin') //e0811669-c7eb-4e5e-a699-e8334d5c5b01 -> aknuth + // getLastLogin(@Param('userid') userId: string): any { + // return this.authService.getLastLogin(userId); + // } } diff --git a/bizmatch-server/src/auth/auth.module.ts b/bizmatch-server/src/auth/auth.module.ts index 0d88910..a5e6116 100644 --- a/bizmatch-server/src/auth/auth.module.ts +++ b/bizmatch-server/src/auth/auth.module.ts @@ -1,12 +1,11 @@ import { Module } from '@nestjs/common'; import { PassportModule } from '@nestjs/passport'; -import { JwtStrategy } from '../jwt.strategy.js'; -import { AuthController } from './auth.controller.js'; -import { AuthService } from './auth.service.js'; +import { AuthController } from './auth.controller'; +import { AuthService } from './auth.service'; @Module({ imports: [PassportModule], - providers: [AuthService, JwtStrategy], + providers: [AuthService], controllers: [AuthController], exports: [AuthService], }) diff --git a/bizmatch-server/src/auth/auth.service.ts b/bizmatch-server/src/auth/auth.service.ts index 645ae95..518c1fd 100644 --- a/bizmatch-server/src/auth/auth.service.ts +++ b/bizmatch-server/src/auth/auth.service.ts @@ -1,7 +1,5 @@ import { Injectable } from '@nestjs/common'; -import ky from 'ky'; import { KeycloakUser } from 'src/models/main.model'; -import urlcat from 'urlcat'; @Injectable() export class AuthService { @@ -13,16 +11,19 @@ export class AuthService { params.append('password', process.env.KEYCLOAK_ADMIN_PASSWORD); const URL = `${process.env.KEYCLOAK_HOST}${process.env.KEYCLOAK_TOKEN_URL}`; - const response = await ky - .post(URL, { - body: params.toString(), - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: process.env.KEYCLOAK_ADMIN_TOKEN, - }, - }) - .json(); - return (response).access_token; + const response = await fetch(URL, { + method: 'POST', + body: params.toString(), + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: process.env.KEYCLOAK_ADMIN_TOKEN, + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + return (data).access_token; } catch (error) { if (error.name === 'HTTPError') { const errorJson = await error.response.json(); @@ -36,43 +37,46 @@ export class AuthService { public async getUsers(): Promise { const token = await this.getAccessToken(); const URL = `${process.env.KEYCLOAK_HOST}${process.env.KEYCLOAK_ADMIN_REALM}${process.env.REALM}${process.env.KEYCLOAK_USERS_URL}`; - const response = await ky - .get(URL, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: `Bearer ${token}`, - }, - }) - .json(); - return response as KeycloakUser[]; - } - public async getUser(userid: string) { - const token = await this.getAccessToken(); - const URLPATH = `${process.env.KEYCLOAK_ADMIN_REALM}${process.env.REALM}${process.env.KEYCLOAK_USER_URL}`; - const URL = urlcat(process.env.KEYCLOAK_HOST, URLPATH, { userid }); - const response = await ky - .get(URL, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: `Bearer ${token}`, - }, - }) - .json(); - return response; + const response = await fetch(URL, { + method: 'GET', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: `Bearer ${token}`, + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + return data as KeycloakUser[]; } + // public async getUser(userid: string) { + // const token = await this.getAccessToken(); + // const URLPATH = `${process.env.KEYCLOAK_ADMIN_REALM}${process.env.REALM}${process.env.KEYCLOAK_USER_URL}`; + // const URL = urlcat(process.env.KEYCLOAK_HOST, URLPATH, { userid }); + // const response = await ky + // .get(URL, { + // headers: { + // 'Content-Type': 'application/x-www-form-urlencoded', + // Authorization: `Bearer ${token}`, + // }, + // }) + // .json(); + // return response; + // } - public async getLastLogin(userid: string) { - const token = await this.getAccessToken(); - const URLPATH = `${process.env.KEYCLOAK_ADMIN_REALM}${process.env.REALM}${process.env.KEYCLOAK_LASTLOGIN_URL}`; - const URL = urlcat(process.env.KEYCLOAK_HOST, URLPATH, { userid }); - const response = await ky - .get(URL, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: `Bearer ${token}`, - }, - }) - .json(); - return response; - } + // public async getLastLogin(userid: string) { + // const token = await this.getAccessToken(); + // const URLPATH = `${process.env.KEYCLOAK_ADMIN_REALM}${process.env.REALM}${process.env.KEYCLOAK_LASTLOGIN_URL}`; + // const URL = urlcat(process.env.KEYCLOAK_HOST, URLPATH, { userid }); + // const response = await ky + // .get(URL, { + // headers: { + // 'Content-Type': 'application/x-www-form-urlencoded', + // Authorization: `Bearer ${token}`, + // }, + // }) + // .json(); + // return response; + // } } diff --git a/bizmatch-server/src/drizzle/drizzle.module.ts b/bizmatch-server/src/drizzle/drizzle.module.ts index d4ae6d1..6c67523 100644 --- a/bizmatch-server/src/drizzle/drizzle.module.ts +++ b/bizmatch-server/src/drizzle/drizzle.module.ts @@ -1,11 +1,10 @@ import { Module } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { drizzle } from 'drizzle-orm/node-postgres'; import pkg from 'pg'; +import * as schema from './schema'; +import { PG_CONNECTION } from './schema'; const { Pool } = pkg; -import * as schema from './schema.js'; -import { ConfigService } from '@nestjs/config'; -import { jsonb, varchar } from 'drizzle-orm/pg-core'; -import { PG_CONNECTION } from './schema.js'; @Module({ providers: [ { @@ -18,7 +17,7 @@ import { PG_CONNECTION } from './schema.js'; // ssl: true, }); - return drizzle(pool, { schema, logger:true }); + return drizzle(pool, { schema, logger: true }); }, }, ], diff --git a/bizmatch-server/src/drizzle/import.ts b/bizmatch-server/src/drizzle/import.ts index b6cb778..16279b6 100644 --- a/bizmatch-server/src/drizzle/import.ts +++ b/bizmatch-server/src/drizzle/import.ts @@ -7,15 +7,15 @@ import { join } from 'path'; import pkg from 'pg'; import { rimraf } from 'rimraf'; import sharp from 'sharp'; -import { BusinessListingService } from 'src/listings/business-listing.service.js'; -import { CommercialPropertyService } from 'src/listings/commercial-property.service.js'; -import { Geo } from 'src/models/server.model.js'; +import { BusinessListingService } from 'src/listings/business-listing.service'; +import { CommercialPropertyService } from 'src/listings/commercial-property.service'; +import { Geo } from 'src/models/server.model'; import winston from 'winston'; -import { User, UserData } from '../models/db.model.js'; -import { createDefaultBusinessListing, createDefaultCommercialPropertyListing, createDefaultUser, emailToDirName, KeyValueStyle } from '../models/main.model.js'; -import { SelectOptionsService } from '../select-options/select-options.service.js'; -import { convertUserToDrizzleUser } from '../utils.js'; -import * as schema from './schema.js'; +import { User, UserData } from '../models/db.model'; +import { createDefaultBusinessListing, createDefaultCommercialPropertyListing, createDefaultUser, emailToDirName, KeyValueStyle } from '../models/main.model'; +import { SelectOptionsService } from '../select-options/select-options.service'; +import { convertUserToDrizzleUser } from '../utils'; +import * as schema from './schema'; interface PropertyImportListing { id: string; userId: string; diff --git a/bizmatch-server/src/drizzle/migrate.ts b/bizmatch-server/src/drizzle/migrate.ts index f114bec..e35435a 100644 --- a/bizmatch-server/src/drizzle/migrate.ts +++ b/bizmatch-server/src/drizzle/migrate.ts @@ -1,7 +1,7 @@ import 'dotenv/config'; import { drizzle } from 'drizzle-orm/node-postgres'; import pkg from 'pg'; -import * as schema from './schema.js'; +import * as schema from './schema'; const { Pool } = pkg; const connectionString = process.env.DATABASE_URL; const pool = new Pool({ connectionString }); diff --git a/bizmatch-server/src/drizzle/test.js b/bizmatch-server/src/drizzle/test.js index 049353a..061d2f5 100644 --- a/bizmatch-server/src/drizzle/test.js +++ b/bizmatch-server/src/drizzle/test.js @@ -2,7 +2,7 @@ const fs = require('fs'); const path = require('path'); // Angenommen, du hast eine Datei `databaseModels.js` mit deinen pgTable-Definitionen -const { users } = require('./schema.js'); +const { users } = require('./schema'); function generateTypeScriptInterface(tableDefinition, tableName) { let interfaceString = `export interface ${tableName} {\n`; diff --git a/bizmatch-server/src/file/file.service.ts b/bizmatch-server/src/file/file.service.ts index ccc1659..acb800a 100644 --- a/bizmatch-server/src/file/file.service.ts +++ b/bizmatch-server/src/file/file.service.ts @@ -2,13 +2,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { readFileSync } from 'fs'; import fs from 'fs-extra'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; -import path, { join } from 'path'; +import { join } from 'path'; import sharp from 'sharp'; -import { fileURLToPath } from 'url'; import { Logger } from 'winston'; -import { ImageProperty, Subscription } from '../models/main.model.js'; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import { ImageProperty, Subscription } from '../models/main.model'; @Injectable() export class FileService { diff --git a/bizmatch-server/src/geo/geo.controller.ts b/bizmatch-server/src/geo/geo.controller.ts index cdc1bfd..b97bab9 100644 --- a/bizmatch-server/src/geo/geo.controller.ts +++ b/bizmatch-server/src/geo/geo.controller.ts @@ -1,6 +1,6 @@ import { Body, Controller, Get, Param, Post } from '@nestjs/common'; -import { CountyRequest } from 'src/models/server.model.js'; -import { GeoService } from './geo.service.js'; +import { CountyRequest } from 'src/models/server.model'; +import { GeoService } from './geo.service'; @Controller('geo') export class GeoController { diff --git a/bizmatch-server/src/geo/geo.module.ts b/bizmatch-server/src/geo/geo.module.ts index ba36868..52b96f2 100644 --- a/bizmatch-server/src/geo/geo.module.ts +++ b/bizmatch-server/src/geo/geo.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { GeoController } from './geo.controller.js'; -import { GeoService } from './geo.service.js'; +import { GeoController } from './geo.controller'; +import { GeoService } from './geo.service'; @Module({ controllers: [GeoController], - providers: [GeoService] + providers: [GeoService], }) export class GeoModule {} diff --git a/bizmatch-server/src/geo/geo.service.ts b/bizmatch-server/src/geo/geo.service.ts index 0a90c2c..7140c53 100644 --- a/bizmatch-server/src/geo/geo.service.ts +++ b/bizmatch-server/src/geo/geo.service.ts @@ -1,12 +1,11 @@ import { Injectable } from '@nestjs/common'; import { readFileSync } from 'fs'; -import path, { join } from 'path'; -import { CityAndStateResult, CountyResult, GeoResult } from 'src/models/main.model.js'; -import { fileURLToPath } from 'url'; -import { City, CountyData, Geo, State } from '../models/server.model.js'; +import { join } from 'path'; +import { CityAndStateResult, CountyResult, GeoResult } from 'src/models/main.model'; +import { City, CountyData, Geo, State } from '../models/server.model'; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +// const __filename = fileURLToPath(import.meta.url); +// const __dirname = path.dirname(__filename); @Injectable() export class GeoService { @@ -24,7 +23,7 @@ export class GeoService { this.counties = JSON.parse(rawCountiesData); } findCountiesStartingWith(prefix: string, states?: string[]) { - let results: CountyResult[] = []; + const results: CountyResult[] = []; let idCounter = 1; this.counties.forEach(stateData => { diff --git a/bizmatch-server/src/image/image.controller.ts b/bizmatch-server/src/image/image.controller.ts index 7374127..e0117b6 100644 --- a/bizmatch-server/src/image/image.controller.ts +++ b/bizmatch-server/src/image/image.controller.ts @@ -2,9 +2,9 @@ import { Controller, Delete, Inject, Param, Post, UploadedFile, UseInterceptors import { FileInterceptor } from '@nestjs/platform-express'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import { FileService } from '../file/file.service.js'; -import { CommercialPropertyService } from '../listings/commercial-property.service.js'; -import { SelectOptionsService } from '../select-options/select-options.service.js'; +import { FileService } from '../file/file.service'; +import { CommercialPropertyService } from '../listings/commercial-property.service'; +import { SelectOptionsService } from '../select-options/select-options.service'; @Controller('image') export class ImageController { diff --git a/bizmatch-server/src/image/image.module.ts b/bizmatch-server/src/image/image.module.ts index e5f1211..3df6077 100644 --- a/bizmatch-server/src/image/image.module.ts +++ b/bizmatch-server/src/image/image.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { FileService } from '../file/file.service.js'; -import { ListingsModule } from '../listings/listings.module.js'; -import { SelectOptionsService } from '../select-options/select-options.service.js'; -import { ImageController } from './image.controller.js'; -import { ImageService } from './image.service.js'; +import { FileService } from '../file/file.service'; +import { ListingsModule } from '../listings/listings.module'; +import { SelectOptionsService } from '../select-options/select-options.service'; +import { ImageController } from './image.controller'; +import { ImageService } from './image.service'; @Module({ imports: [ListingsModule], diff --git a/bizmatch-server/src/jwt.strategy.ts b/bizmatch-server/src/jwt.strategy.ts index c03b736..d06e93f 100644 --- a/bizmatch-server/src/jwt.strategy.ts +++ b/bizmatch-server/src/jwt.strategy.ts @@ -1,11 +1,17 @@ import { Inject, Injectable, UnauthorizedException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; +import fs from 'fs'; import { passportJwtSecret } from 'jwks-rsa'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { ExtractJwt, Strategy } from 'passport-jwt'; +import path from 'path'; import { Logger } from 'winston'; import { JwtPayload, JwtUser } from './models/main.model'; +// const logger = winston.createLogger({ +// transports: [new winston.transports.Console()], +// }); +// const pemCache = new Map(); @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor( @@ -13,22 +19,44 @@ export class JwtStrategy extends PassportStrategy(Strategy) { @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, ) { const realm = configService.get('REALM'); + // const staticCerts = loadStaticCerts(); super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, secretOrKeyProvider: passportJwtSecret({ cache: true, - rateLimit: true, - jwksRequestsPerMinute: 5, + rateLimit: false, + // jwksRequestsPerMinute: 5, 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 authorize: '', issuer: `https://auth.bizmatch.net/realms/${realm}`, algorithms: ['RS256'], }); } - async validate(payload: JwtPayload): Promise { if (!payload) { this.logger.error('Invalid payload'); @@ -43,3 +71,8 @@ export class JwtStrategy extends PassportStrategy(Strategy) { return result; } } +export function loadStaticCerts() { + const certsPath = path.join(__dirname, '../', 'assets', 'keycloak-certs.json'); + const certsData = fs.readFileSync(certsPath, 'utf8'); + return JSON.parse(certsData); +} diff --git a/bizmatch-server/src/listings/broker-listings.controller.ts b/bizmatch-server/src/listings/broker-listings.controller.ts index da02dc2..1806fc3 100644 --- a/bizmatch-server/src/listings/broker-listings.controller.ts +++ b/bizmatch-server/src/listings/broker-listings.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Inject, Post } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; -import { UserListingCriteria } from 'src/models/main.model.js'; +import { UserListingCriteria } from 'src/models/main.model'; import { Logger } from 'winston'; -import { UserService } from '../user/user.service.js'; +import { UserService } from '../user/user.service'; @Controller('listings/professionals_brokers') export class BrokerListingsController { diff --git a/bizmatch-server/src/listings/business-listing.service.ts b/bizmatch-server/src/listings/business-listing.service.ts index ae9fdaa..5f91977 100644 --- a/bizmatch-server/src/listings/business-listing.service.ts +++ b/bizmatch-server/src/listings/business-listing.service.ts @@ -4,13 +4,13 @@ import { NodePgDatabase } from 'drizzle-orm/node-postgres'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; import { ZodError } from 'zod'; -import * as schema from '../drizzle/schema.js'; -import { businesses, PG_CONNECTION } from '../drizzle/schema.js'; -import { FileService } from '../file/file.service.js'; -import { GeoService } from '../geo/geo.service.js'; -import { BusinessListing, BusinessListingSchema } from '../models/db.model.js'; -import { BusinessListingCriteria, emailToDirName, JwtUser } from '../models/main.model.js'; -import { convertBusinessToDrizzleBusiness, convertDrizzleBusinessToBusiness, getDistanceQuery, splitName } from '../utils.js'; +import * as schema from '../drizzle/schema'; +import { businesses, PG_CONNECTION } from '../drizzle/schema'; +import { FileService } from '../file/file.service'; +import { GeoService } from '../geo/geo.service'; +import { BusinessListing, BusinessListingSchema } from '../models/db.model'; +import { BusinessListingCriteria, JwtUser } from '../models/main.model'; +import { convertBusinessToDrizzleBusiness, convertDrizzleBusinessToBusiness, getDistanceQuery, splitName } from '../utils'; @Injectable() export class BusinessListingService { @@ -162,7 +162,7 @@ export class BusinessListingService { conditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true))); } conditions.push(sql`${businesses.id} = ${id}`); - let result = await this.conn + const result = await this.conn .select() .from(businesses) .where(and(...conditions)); @@ -175,7 +175,7 @@ export class BusinessListingService { async findBusinessesByEmail(email: string, user: JwtUser): Promise { const conditions = []; - conditions.push(eq(businesses.imageName, emailToDirName(email))); + conditions.push(eq(businesses.email, email)); if (email !== user?.username && (!user?.roles?.includes('ADMIN') ?? false)) { conditions.push(ne(businesses.draft, true)); } @@ -199,7 +199,7 @@ export class BusinessListingService { try { data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date(); data.updated = new Date(); - const validatedBusinessListing = BusinessListingSchema.parse(data); + BusinessListingSchema.parse(data); const convertedBusinessListing = convertBusinessToDrizzleBusiness(data); delete convertedBusinessListing.id; const [createdListing] = await this.conn.insert(businesses).values(convertedBusinessListing).returning(); @@ -222,7 +222,7 @@ export class BusinessListingService { try { data.updated = new Date(); data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date(); - const validatedBusinessListing = BusinessListingSchema.parse(data); + BusinessListingSchema.parse(data); const convertedBusinessListing = convertBusinessToDrizzleBusiness(data); const [updateListing] = await this.conn.update(businesses).set(convertedBusinessListing).where(eq(businesses.id, id)).returning(); return convertDrizzleBusinessToBusiness(updateListing); diff --git a/bizmatch-server/src/listings/business-listings.controller.ts b/bizmatch-server/src/listings/business-listings.controller.ts index 7f27b68..e7e17e5 100644 --- a/bizmatch-server/src/listings/business-listings.controller.ts +++ b/bizmatch-server/src/listings/business-listings.controller.ts @@ -1,11 +1,11 @@ import { Body, Controller, Delete, Get, Inject, Param, Post, Put, Request, UseGuards } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import { JwtAuthGuard } from '../jwt-auth/jwt-auth.guard.js'; -import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js'; -import { BusinessListing } from '../models/db.model.js'; -import { BusinessListingCriteria, JwtUser } from '../models/main.model.js'; -import { BusinessListingService } from './business-listing.service.js'; +import { JwtAuthGuard } from '../jwt-auth/jwt-auth.guard'; +import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard'; +import { BusinessListing } from '../models/db.model'; +import { BusinessListingCriteria, JwtUser } from '../models/main.model'; +import { BusinessListingService } from './business-listing.service'; @Controller('listings/business') export class BusinessListingsController { diff --git a/bizmatch-server/src/listings/commercial-property-listings.controller.ts b/bizmatch-server/src/listings/commercial-property-listings.controller.ts index a8ab9ed..b80009c 100644 --- a/bizmatch-server/src/listings/commercial-property-listings.controller.ts +++ b/bizmatch-server/src/listings/commercial-property-listings.controller.ts @@ -1,12 +1,12 @@ import { Body, Controller, Delete, Get, Inject, Param, Post, Put, Request, UseGuards } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import { FileService } from '../file/file.service.js'; -import { JwtAuthGuard } from '../jwt-auth/jwt-auth.guard.js'; -import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js'; +import { FileService } from '../file/file.service'; +import { JwtAuthGuard } from '../jwt-auth/jwt-auth.guard'; +import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard'; import { CommercialPropertyListing } from '../models/db.model'; -import { CommercialPropertyListingCriteria, JwtUser } from '../models/main.model.js'; -import { CommercialPropertyService } from './commercial-property.service.js'; +import { CommercialPropertyListingCriteria, JwtUser } from '../models/main.model'; +import { CommercialPropertyService } from './commercial-property.service'; @Controller('listings/commercialProperty') export class CommercialPropertyListingsController { diff --git a/bizmatch-server/src/listings/commercial-property.service.ts b/bizmatch-server/src/listings/commercial-property.service.ts index 29f0293..2e7d067 100644 --- a/bizmatch-server/src/listings/commercial-property.service.ts +++ b/bizmatch-server/src/listings/commercial-property.service.ts @@ -4,13 +4,13 @@ import { NodePgDatabase } from 'drizzle-orm/node-postgres'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; import { ZodError } from 'zod'; -import * as schema from '../drizzle/schema.js'; -import { commercials, PG_CONNECTION } from '../drizzle/schema.js'; -import { FileService } from '../file/file.service.js'; -import { GeoService } from '../geo/geo.service.js'; -import { CommercialPropertyListing, CommercialPropertyListingSchema } from '../models/db.model.js'; -import { CommercialPropertyListingCriteria, emailToDirName, JwtUser } from '../models/main.model.js'; -import { convertCommercialToDrizzleCommercial, convertDrizzleBusinessToBusiness, convertDrizzleCommercialToCommercial, getDistanceQuery } from '../utils.js'; +import * as schema from '../drizzle/schema'; +import { commercials, PG_CONNECTION } from '../drizzle/schema'; +import { FileService } from '../file/file.service'; +import { GeoService } from '../geo/geo.service'; +import { CommercialPropertyListing, CommercialPropertyListingSchema } from '../models/db.model'; +import { CommercialPropertyListingCriteria, JwtUser } from '../models/main.model'; +import { convertCommercialToDrizzleCommercial, convertDrizzleBusinessToBusiness, convertDrizzleCommercialToCommercial, getDistanceQuery } from '../utils'; @Injectable() export class CommercialPropertyService { @@ -99,7 +99,7 @@ export class CommercialPropertyService { conditions.push(or(eq(commercials.email, user?.username), ne(commercials.draft, true))); } conditions.push(sql`${commercials.id} = ${id}`); - let result = await this.conn + const result = await this.conn .select() .from(commercials) .where(and(...conditions)); @@ -113,7 +113,7 @@ export class CommercialPropertyService { // #### Find by User EMail ######################################## async findCommercialPropertiesByEmail(email: string, user: JwtUser): Promise { const conditions = []; - conditions.push(eq(commercials.imagePath, emailToDirName(email))); + conditions.push(eq(commercials.email, email)); if (email !== user?.username && (!user?.roles?.includes('ADMIN') ?? false)) { conditions.push(ne(commercials.draft, true)); } @@ -144,7 +144,7 @@ export class CommercialPropertyService { try { data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date(); data.updated = new Date(); - const validatedCommercialPropertyListing = CommercialPropertyListingSchema.parse(data); + CommercialPropertyListingSchema.parse(data); const convertedCommercialPropertyListing = convertCommercialToDrizzleCommercial(data); delete convertedCommercialPropertyListing.id; const [createdListing] = await this.conn.insert(commercials).values(convertedCommercialPropertyListing).returning(); @@ -167,9 +167,9 @@ export class CommercialPropertyService { try { data.updated = new Date(); data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date(); - const validatedCommercialPropertyListing = CommercialPropertyListingSchema.parse(data); + CommercialPropertyListingSchema.parse(data); const imageOrder = await this.fileService.getPropertyImages(data.imagePath, String(data.serialId)); - let difference = imageOrder.filter(x => !data.imageOrder.includes(x)).concat(data.imageOrder.filter(x => !imageOrder.includes(x))); + const difference = imageOrder.filter(x => !data.imageOrder.includes(x)).concat(data.imageOrder.filter(x => !imageOrder.includes(x))); if (difference.length > 0) { this.logger.warn(`changes between image directory and imageOrder in listing ${data.serialId}: ${difference.join(',')}`); data.imageOrder = imageOrder; diff --git a/bizmatch-server/src/listings/listings.module.ts b/bizmatch-server/src/listings/listings.module.ts index 7a31ead..9914b53 100644 --- a/bizmatch-server/src/listings/listings.module.ts +++ b/bizmatch-server/src/listings/listings.module.ts @@ -1,17 +1,17 @@ import { Module } from '@nestjs/common'; -import { AuthModule } from '../auth/auth.module.js'; -import { DrizzleModule } from '../drizzle/drizzle.module.js'; -import { FileService } from '../file/file.service.js'; -import { UserService } from '../user/user.service.js'; -import { BrokerListingsController } from './broker-listings.controller.js'; -import { BusinessListingsController } from './business-listings.controller.js'; -import { CommercialPropertyListingsController } from './commercial-property-listings.controller.js'; +import { AuthModule } from '../auth/auth.module'; +import { DrizzleModule } from '../drizzle/drizzle.module'; +import { FileService } from '../file/file.service'; +import { UserService } from '../user/user.service'; +import { BrokerListingsController } from './broker-listings.controller'; +import { BusinessListingsController } from './business-listings.controller'; +import { CommercialPropertyListingsController } from './commercial-property-listings.controller'; -import { GeoModule } from '../geo/geo.module.js'; -import { GeoService } from '../geo/geo.service.js'; -import { BusinessListingService } from './business-listing.service.js'; -import { CommercialPropertyService } from './commercial-property.service.js'; -import { UnknownListingsController } from './unknown-listings.controller.js'; +import { GeoModule } from '../geo/geo.module'; +import { GeoService } from '../geo/geo.service'; +import { BusinessListingService } from './business-listing.service'; +import { CommercialPropertyService } from './commercial-property.service'; +import { UnknownListingsController } from './unknown-listings.controller'; @Module({ imports: [DrizzleModule, AuthModule, GeoModule], diff --git a/bizmatch-server/src/listings/unknown-listings.controller.ts b/bizmatch-server/src/listings/unknown-listings.controller.ts index 6f4fd89..0cde0f5 100644 --- a/bizmatch-server/src/listings/unknown-listings.controller.ts +++ b/bizmatch-server/src/listings/unknown-listings.controller.ts @@ -1,9 +1,9 @@ import { Controller, Get, Inject, Param, Request, UseGuards } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js'; -import { BusinessListingService } from './business-listing.service.js'; -import { CommercialPropertyService } from './commercial-property.service.js'; +import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard'; +import { BusinessListingService } from './business-listing.service'; +import { CommercialPropertyService } from './commercial-property.service'; @Controller('listings/undefined') export class UnknownListingsController { diff --git a/bizmatch-server/src/log/log.controller.ts b/bizmatch-server/src/log/log.controller.ts index 6fe77d7..f9289a6 100644 --- a/bizmatch-server/src/log/log.controller.ts +++ b/bizmatch-server/src/log/log.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Inject, Post, Request, UseGuards } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js'; -import { LogMessage } from '../models/main.model.js'; +import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard'; +import { LogMessage } from '../models/main.model'; @Controller('log') export class LogController { constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {} diff --git a/bizmatch-server/src/log/log.module.ts b/bizmatch-server/src/log/log.module.ts index 2b85cb7..1c6816b 100644 --- a/bizmatch-server/src/log/log.module.ts +++ b/bizmatch-server/src/log/log.module.ts @@ -1,5 +1,5 @@ import { Module } from '@nestjs/common'; -import { LogController } from './log.controller.js'; +import { LogController } from './log.controller'; @Module({ controllers: [LogController], diff --git a/bizmatch-server/src/mail/mail.controller.ts b/bizmatch-server/src/mail/mail.controller.ts index 27a43b8..f4415b1 100644 --- a/bizmatch-server/src/mail/mail.controller.ts +++ b/bizmatch-server/src/mail/mail.controller.ts @@ -1,7 +1,7 @@ import { Body, Controller, Post } from '@nestjs/common'; import { ShareByEMail, User } from 'src/models/db.model'; import { ErrorResponse, MailInfo } from '../models/main.model'; -import { MailService } from './mail.service.js'; +import { MailService } from './mail.service'; @Controller('mail') export class MailController { diff --git a/bizmatch-server/src/mail/mail.module.ts b/bizmatch-server/src/mail/mail.module.ts index 6a5927c..9f20409 100644 --- a/bizmatch-server/src/mail/mail.module.ts +++ b/bizmatch-server/src/mail/mail.module.ts @@ -1,22 +1,18 @@ import { MailerModule } from '@nestjs-modules/mailer'; -import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter.js'; +import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter'; import { Module } from '@nestjs/common'; -import path, { join } from 'path'; -import { fileURLToPath } from 'url'; -import { DrizzleModule } from '../drizzle/drizzle.module.js'; -import { FileService } from '../file/file.service.js'; -import { GeoModule } from '../geo/geo.module.js'; -import { GeoService } from '../geo/geo.service.js'; -import { UserModule } from '../user/user.module.js'; -import { UserService } from '../user/user.service.js'; -import { MailController } from './mail.controller.js'; -import { MailService } from './mail.service.js'; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const user = process.env.AMAZON_USER; -const password = process.env.AMAZON_PASSWORD; -console.log('Amazon User:', process.env.AMAZON_USER); -console.log('Amazon Password:', process.env.AMAZON_PASSWORD); +import { join } from 'path'; +import { DrizzleModule } from '../drizzle/drizzle.module'; +import { FileService } from '../file/file.service'; +import { GeoModule } from '../geo/geo.module'; +import { GeoService } from '../geo/geo.service'; +import { UserModule } from '../user/user.module'; +import { UserService } from '../user/user.service'; +import { MailController } from './mail.controller'; +import { MailService } from './mail.service'; +// const __filename = fileURLToPath(import.meta.url); +// const __dirname = path.dirname(__filename); + @Module({ imports: [ DrizzleModule, diff --git a/bizmatch-server/src/mail/mail.service.ts b/bizmatch-server/src/mail/mail.service.ts index 19ae0e7..288fdda 100644 --- a/bizmatch-server/src/mail/mail.service.ts +++ b/bizmatch-server/src/mail/mail.service.ts @@ -1,13 +1,12 @@ import { MailerService } from '@nestjs-modules/mailer'; import { BadRequestException, Injectable } from '@nestjs/common'; -import path, { join } from 'path'; -import { fileURLToPath } from 'url'; +import { join } from 'path'; import { ZodError } from 'zod'; -import { SenderSchema, ShareByEMail, ShareByEMailSchema, User } from '../models/db.model.js'; -import { ErrorResponse, MailInfo, isEmpty } from '../models/main.model.js'; -import { UserService } from '../user/user.service.js'; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import { SenderSchema, ShareByEMail, ShareByEMailSchema, User } from '../models/db.model'; +import { ErrorResponse, MailInfo, isEmpty } from '../models/main.model'; +import { UserService } from '../user/user.service'; +// const __filename = fileURLToPath(import.meta.url); +// const __dirname = path.dirname(__filename); @Injectable() export class MailService { diff --git a/bizmatch-server/src/main.ts b/bizmatch-server/src/main.ts index 0eff9f2..8e2bfd4 100644 --- a/bizmatch-server/src/main.ts +++ b/bizmatch-server/src/main.ts @@ -1,10 +1,10 @@ import { NestFactory } from '@nestjs/core'; import bodyParser from 'body-parser'; import express from 'express'; -import { AppModule } from './app.module.js'; +import { AppModule } from './app.module'; async function bootstrap() { - const server = express(); + express(); const app = await NestFactory.create(AppModule); app.use('/bizmatch/payment/webhook', bodyParser.raw({ type: 'application/json' })); app.setGlobalPrefix('bizmatch'); diff --git a/bizmatch-server/src/models/main.model.ts b/bizmatch-server/src/models/main.model.ts index 363f3ae..34139c4 100644 --- a/bizmatch-server/src/models/main.model.ts +++ b/bizmatch-server/src/models/main.model.ts @@ -1,6 +1,6 @@ import Stripe from 'stripe'; -import { BusinessListing, CommercialPropertyListing, Sender, User } from './db.model.js'; -import { State } from './server.model.js'; +import { BusinessListing, CommercialPropertyListing, Sender, User } from './db.model'; +import { State } from './server.model'; export interface StatesResult { state: string; diff --git a/bizmatch-server/src/payment/payment.controller.ts b/bizmatch-server/src/payment/payment.controller.ts index a59a6ea..c7abb37 100644 --- a/bizmatch-server/src/payment/payment.controller.ts +++ b/bizmatch-server/src/payment/payment.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Get, HttpException, HttpStatus, Param, Post, Req, Res } from '@nestjs/common'; import { Request, Response } from 'express'; -import { Checkout } from 'src/models/main.model.js'; +import { Checkout } from 'src/models/main.model'; import Stripe from 'stripe'; -import { PaymentService } from './payment.service.js'; +import { PaymentService } from './payment.service'; @Controller('payment') export class PaymentController { diff --git a/bizmatch-server/src/payment/payment.module.ts b/bizmatch-server/src/payment/payment.module.ts index fc47b75..dfcbec9 100644 --- a/bizmatch-server/src/payment/payment.module.ts +++ b/bizmatch-server/src/payment/payment.module.ts @@ -1,15 +1,15 @@ import { Module } from '@nestjs/common'; -import { AuthModule } from '../auth/auth.module.js'; -import { AuthService } from '../auth/auth.service.js'; -import { DrizzleModule } from '../drizzle/drizzle.module.js'; -import { FileService } from '../file/file.service.js'; -import { GeoService } from '../geo/geo.service.js'; -import { MailModule } from '../mail/mail.module.js'; -import { MailService } from '../mail/mail.service.js'; -import { UserModule } from '../user/user.module.js'; -import { UserService } from '../user/user.service.js'; -import { PaymentController } from './payment.controller.js'; -import { PaymentService } from './payment.service.js'; +import { AuthModule } from '../auth/auth.module'; +import { AuthService } from '../auth/auth.service'; +import { DrizzleModule } from '../drizzle/drizzle.module'; +import { FileService } from '../file/file.service'; +import { GeoService } from '../geo/geo.service'; +import { MailModule } from '../mail/mail.module'; +import { MailService } from '../mail/mail.service'; +import { UserModule } from '../user/user.module'; +import { UserService } from '../user/user.service'; +import { PaymentController } from './payment.controller'; +import { PaymentService } from './payment.service'; @Module({ imports: [DrizzleModule, UserModule, MailModule, AuthModule], diff --git a/bizmatch-server/src/payment/payment.service.ts b/bizmatch-server/src/payment/payment.service.ts index f2f7ea7..d81e85f 100644 --- a/bizmatch-server/src/payment/payment.service.ts +++ b/bizmatch-server/src/payment/payment.service.ts @@ -1,14 +1,14 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { NodePgDatabase } from 'drizzle-orm/node-postgres/driver.js'; +import { NodePgDatabase } from 'drizzle-orm/node-postgres/driver'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import Stripe from 'stripe'; import { Logger } from 'winston'; -import { AuthService } from '../auth/auth.service.js'; -import * as schema from '../drizzle/schema.js'; -import { PG_CONNECTION } from '../drizzle/schema.js'; -import { MailService } from '../mail/mail.service.js'; -import { Checkout } from '../models/main.model.js'; -import { UserService } from '../user/user.service.js'; +import { AuthService } from '../auth/auth.service'; +import * as schema from '../drizzle/schema'; +import { PG_CONNECTION } from '../drizzle/schema'; +import { MailService } from '../mail/mail.service'; +import { Checkout } from '../models/main.model'; +import { UserService } from '../user/user.service'; export interface BillingAddress { country: string; state: string; diff --git a/bizmatch-server/src/select-options/select-options.controller.ts b/bizmatch-server/src/select-options/select-options.controller.ts index 98c58ca..da3d0f9 100644 --- a/bizmatch-server/src/select-options/select-options.controller.ts +++ b/bizmatch-server/src/select-options/select-options.controller.ts @@ -1,5 +1,5 @@ import { Controller, Get } from '@nestjs/common'; -import { SelectOptionsService } from './select-options.service.js'; +import { SelectOptionsService } from './select-options.service'; @Controller('select-options') export class SelectOptionsController { diff --git a/bizmatch-server/src/select-options/select-options.module.ts b/bizmatch-server/src/select-options/select-options.module.ts index ed0f3e1..757ede0 100644 --- a/bizmatch-server/src/select-options/select-options.module.ts +++ b/bizmatch-server/src/select-options/select-options.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { SelectOptionsController } from './select-options.controller.js'; -import { SelectOptionsService } from './select-options.service.js'; +import { SelectOptionsController } from './select-options.controller'; +import { SelectOptionsService } from './select-options.service'; @Module({ - controllers: [SelectOptionsController], - providers: [SelectOptionsService] - }) + controllers: [SelectOptionsController], + providers: [SelectOptionsService], +}) export class SelectOptionsModule {} diff --git a/bizmatch-server/src/select-options/select-options.service.ts b/bizmatch-server/src/select-options/select-options.service.ts index ae395e2..87e050c 100644 --- a/bizmatch-server/src/select-options/select-options.service.ts +++ b/bizmatch-server/src/select-options/select-options.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { ImageType, KeyValue, KeyValueStyle } from '../models/main.model.js'; +import { ImageType, KeyValue, KeyValueStyle } from '../models/main.model'; @Injectable() export class SelectOptionsService { diff --git a/bizmatch-server/src/user/user.controller.ts b/bizmatch-server/src/user/user.controller.ts index 0300c59..629fa96 100644 --- a/bizmatch-server/src/user/user.controller.ts +++ b/bizmatch-server/src/user/user.controller.ts @@ -2,12 +2,12 @@ import { BadRequestException, Body, Controller, Get, Inject, Param, Post, Query, import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; import { ZodError } from 'zod'; -import { FileService } from '../file/file.service.js'; -import { JwtAuthGuard } from '../jwt-auth/jwt-auth.guard.js'; -import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js'; +import { FileService } from '../file/file.service'; +import { JwtAuthGuard } from '../jwt-auth/jwt-auth.guard'; +import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard'; import { User } from '../models/db.model'; -import { JwtUser, Subscription, UserListingCriteria } from '../models/main.model.js'; -import { UserService } from './user.service.js'; +import { JwtUser, Subscription, UserListingCriteria } from '../models/main.model'; +import { UserService } from './user.service'; @Controller('user') export class UserController { diff --git a/bizmatch-server/src/user/user.module.ts b/bizmatch-server/src/user/user.module.ts index 7552b0b..92a458a 100644 --- a/bizmatch-server/src/user/user.module.ts +++ b/bizmatch-server/src/user/user.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; -import { DrizzleModule } from '../drizzle/drizzle.module.js'; -import { FileService } from '../file/file.service.js'; -import { GeoModule } from '../geo/geo.module.js'; -import { GeoService } from '../geo/geo.service.js'; -import { UserController } from './user.controller.js'; -import { UserService } from './user.service.js'; +import { DrizzleModule } from '../drizzle/drizzle.module'; +import { FileService } from '../file/file.service'; +import { GeoModule } from '../geo/geo.module'; +import { GeoService } from '../geo/geo.service'; +import { UserController } from './user.controller'; +import { UserService } from './user.service'; @Module({ imports: [DrizzleModule, GeoModule], diff --git a/bizmatch-server/src/user/user.service.ts b/bizmatch-server/src/user/user.service.ts index 9a70253..bbdbe9a 100644 --- a/bizmatch-server/src/user/user.service.ts +++ b/bizmatch-server/src/user/user.service.ts @@ -1,15 +1,15 @@ import { Inject, Injectable } from '@nestjs/common'; import { and, count, eq, ilike, inArray, or, SQL, sql } from 'drizzle-orm'; -import { NodePgDatabase } from 'drizzle-orm/node-postgres/driver.js'; +import { NodePgDatabase } from 'drizzle-orm/node-postgres/driver'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -import * as schema from '../drizzle/schema.js'; -import { customerSubTypeEnum, PG_CONNECTION } from '../drizzle/schema.js'; -import { FileService } from '../file/file.service.js'; -import { GeoService } from '../geo/geo.service.js'; -import { User, UserSchema } from '../models/db.model.js'; -import { createDefaultUser, emailToDirName, JwtUser, UserListingCriteria } from '../models/main.model.js'; -import { convertDrizzleUserToUser, convertUserToDrizzleUser, getDistanceQuery, splitName } from '../utils.js'; +import * as schema from '../drizzle/schema'; +import { customerSubTypeEnum, PG_CONNECTION } from '../drizzle/schema'; +import { FileService } from '../file/file.service'; +import { GeoService } from '../geo/geo.service'; +import { User, UserSchema } from '../models/db.model'; +import { createDefaultUser, emailToDirName, JwtUser, UserListingCriteria } from '../models/main.model'; +import { convertDrizzleUserToUser, convertUserToDrizzleUser, getDistanceQuery, splitName } from '../utils'; type CustomerSubType = (typeof customerSubTypeEnum.enumValues)[number]; @Injectable() diff --git a/bizmatch-server/src/utils.ts b/bizmatch-server/src/utils.ts index 69fb98c..9b60efa 100644 --- a/bizmatch-server/src/utils.ts +++ b/bizmatch-server/src/utils.ts @@ -1,6 +1,6 @@ import { sql } from 'drizzle-orm'; -import { businesses, commercials, users } from './drizzle/schema.js'; -import { BusinessListing, CommercialPropertyListing, User } from './models/db.model.js'; +import { businesses, commercials, users } from './drizzle/schema'; +import { BusinessListing, CommercialPropertyListing, User } from './models/db.model'; export const EARTH_RADIUS_KM = 6371; // Erdradius in Kilometern export const EARTH_RADIUS_MILES = 3959; // Erdradius in Meilen export function convertStringToNullUndefined(value) { diff --git a/bizmatch-server/tsconfig.build.json b/bizmatch-server/tsconfig.build.json index 21fdd0a..b0ce1b9 100644 --- a/bizmatch-server/tsconfig.build.json +++ b/bizmatch-server/tsconfig.build.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "exclude": ["node_modules", "test", "dist", "**/*spec.ts"], + "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "src/drizzle/import.ts"] } diff --git a/bizmatch-server/tsconfig.json b/bizmatch-server/tsconfig.json index 425ca7d..af69ced 100644 --- a/bizmatch-server/tsconfig.json +++ b/bizmatch-server/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { "target": "ES2021", - "module": "ESNext", - "moduleResolution": "Node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, @@ -18,6 +18,6 @@ "strictBindCallApply": false, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": false, - "esModuleInterop":true + "esModuleInterop": true } }