Draft Mode inkl. Token implementiert
This commit is contained in:
parent
226d2ebc1e
commit
b4cf17b8ea
|
|
@ -48,6 +48,9 @@ public
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
.env.local
|
.env.local
|
||||||
|
.env.prod
|
||||||
|
.env.dev
|
||||||
|
.env.test
|
||||||
|
|
||||||
# temp directory
|
# temp directory
|
||||||
.temp
|
.temp
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,15 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug Nest Framework",
|
"name": "Debug Nest Framework",
|
||||||
"runtimeExecutable": "npm",
|
"runtimeExecutable": "npm",
|
||||||
"runtimeArgs": [
|
"runtimeArgs": ["run", "start:debug", "--", "--inspect-brk"],
|
||||||
"run",
|
|
||||||
"start:debug",
|
|
||||||
"--",
|
|
||||||
"--inspect-brk"
|
|
||||||
],
|
|
||||||
"autoAttachChildProcesses": true,
|
"autoAttachChildProcesses": true,
|
||||||
"restart": true,
|
"restart": true,
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"stopOnEntry": false,
|
"stopOnEntry": false,
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
|
"env": {
|
||||||
|
"HOST_NAME": "localhost"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "node",
|
"type": "node",
|
||||||
|
|
@ -24,9 +22,7 @@
|
||||||
"name": "Debug Current TS File",
|
"name": "Debug Current TS File",
|
||||||
"program": "${workspaceFolder}/dist/src/drizzle/${fileBasenameNoExtension}.js",
|
"program": "${workspaceFolder}/dist/src/drizzle/${fileBasenameNoExtension}.js",
|
||||||
"preLaunchTask": "tsc: build - tsconfig.json",
|
"preLaunchTask": "tsc: build - tsconfig.json",
|
||||||
"outFiles": [
|
"outFiles": ["${workspaceFolder}/out/**/*.js"],
|
||||||
"${workspaceFolder}/out/**/*.js"
|
|
||||||
],
|
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"smartStep": true,
|
"smartStep": true,
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
"internalConsoleOptions": "openOnSessionStart"
|
||||||
|
|
@ -35,31 +31,21 @@
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "generateDefs",
|
"name": "generateDefs",
|
||||||
"skipFiles": [
|
"skipFiles": ["<node_internals>/**"],
|
||||||
"<node_internals>/**"
|
|
||||||
],
|
|
||||||
"program": "${workspaceFolder}/dist/src/drizzle/generateDefs.js",
|
"program": "${workspaceFolder}/dist/src/drizzle/generateDefs.js",
|
||||||
"outFiles": [
|
"outFiles": ["${workspaceFolder}/dist/src/drizzle/**/*.js"],
|
||||||
"${workspaceFolder}/dist/src/drizzle/**/*.js"
|
|
||||||
],
|
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"smartStep": true,
|
"smartStep": true
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "generateTypes",
|
"name": "generateTypes",
|
||||||
"skipFiles": [
|
"skipFiles": ["<node_internals>/**"],
|
||||||
"<node_internals>/**"
|
|
||||||
],
|
|
||||||
"program": "${workspaceFolder}/dist/src/drizzle/generateTypes.js",
|
"program": "${workspaceFolder}/dist/src/drizzle/generateTypes.js",
|
||||||
"outFiles": [
|
"outFiles": ["${workspaceFolder}/dist/src/drizzle/**/*.js"],
|
||||||
"${workspaceFolder}/dist/src/drizzle/**/*.js"
|
|
||||||
],
|
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"smartStep": true,
|
"smartStep": true
|
||||||
|
}
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -9,10 +9,10 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nest build",
|
"build": "nest build",
|
||||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
"start": "nest start",
|
"start": "HOST_NAME=localhost nest start",
|
||||||
"start:dev": "nest start --watch",
|
"start:dev": "HOST_NAME=dev.bizmatch.net nest start --watch",
|
||||||
"start:debug": "nest start --debug --watch",
|
"start:debug": "nest start --debug --watch",
|
||||||
"start:prod": "node dist/main",
|
"start:prod": "HOST_NAME=www.bizmatch.net node dist/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",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
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 * 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 path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
@ -14,13 +17,37 @@ import { ListingsModule } from './listings/listings.module.js';
|
||||||
import { MailModule } from './mail/mail.module.js';
|
import { MailModule } from './mail/mail.module.js';
|
||||||
import { RequestDurationMiddleware } from './request-duration/request-duration.middleware.js';
|
import { RequestDurationMiddleware } from './request-duration/request-duration.middleware.js';
|
||||||
import { SelectOptionsModule } from './select-options/select-options.module.js';
|
import { SelectOptionsModule } from './select-options/select-options.module.js';
|
||||||
|
|
||||||
import { PassportModule } from '@nestjs/passport';
|
|
||||||
import { UserModule } from './user/user.module.js';
|
import { UserModule } from './user/user.module.js';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
function loadEnvFiles() {
|
||||||
|
// Load the .env file
|
||||||
|
dotenv.config();
|
||||||
|
console.log('Loaded .env file');
|
||||||
|
|
||||||
|
// Determine which additional env file to load
|
||||||
|
let envFilePath = '';
|
||||||
|
const host = process.env.HOST_NAME || '';
|
||||||
|
|
||||||
|
if (host.includes('localhost')) {
|
||||||
|
envFilePath = '.env.local';
|
||||||
|
} else if (host.includes('dev.bizmatch.net')) {
|
||||||
|
envFilePath = '.env.dev';
|
||||||
|
} else if (host.includes('www.bizmatch.net') || host.includes('bizmatch.net')) {
|
||||||
|
envFilePath = '.env.prod';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the additional env file if it exists
|
||||||
|
if (fs.existsSync(envFilePath)) {
|
||||||
|
dotenv.config({ path: envFilePath });
|
||||||
|
console.log(`Loaded ${envFilePath} file`);
|
||||||
|
} else {
|
||||||
|
console.log(`No additional .env file found for HOST_NAME: ${host}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadEnvFiles();
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({ isGlobal: true }),
|
ConfigModule.forRoot({ isGlobal: true }),
|
||||||
|
|
@ -42,13 +69,6 @@ const __dirname = path.dirname(__filename);
|
||||||
],
|
],
|
||||||
// other options
|
// other options
|
||||||
}),
|
}),
|
||||||
// KeycloakConnectModule.register({
|
|
||||||
// authServerUrl: 'http://auth.bizmatch.net',
|
|
||||||
// realm: 'dev',
|
|
||||||
// clientId: 'dev',
|
|
||||||
// secret: 'Yu3lETbYUphDiJxgnhhpelcJ63p2FCDM',
|
|
||||||
// // Secret key of the client taken from keycloak server
|
|
||||||
// }),
|
|
||||||
GeoModule,
|
GeoModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
ListingsModule,
|
ListingsModule,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ export class ImageController {
|
||||||
@Delete('propertyPicture/:imagePath/:serial/:imagename')
|
@Delete('propertyPicture/:imagePath/:serial/:imagename')
|
||||||
async deletePropertyImagesById(@Param('imagePath') imagePath: string, @Param('serial') serial: string, @Param('imagename') imagename: string): Promise<any> {
|
async deletePropertyImagesById(@Param('imagePath') imagePath: string, @Param('serial') serial: string, @Param('imagename') imagename: string): Promise<any> {
|
||||||
this.fileService.deleteImage(`pictures/property/${imagePath}/${serial}/${imagename}`);
|
this.fileService.deleteImage(`pictures/property/${imagePath}/${serial}/${imagename}`);
|
||||||
|
await this.listingService.deleteImage(imagePath, serial, imagename);
|
||||||
}
|
}
|
||||||
// ############
|
// ############
|
||||||
// Profile
|
// Profile
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { PassportStrategy } from '@nestjs/passport';
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
import { passportJwtSecret } from 'jwks-rsa';
|
import { passportJwtSecret } from 'jwks-rsa';
|
||||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||||
|
import { JwtUser } from './models/main.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JwtStrategy extends PassportStrategy(Strategy) {
|
export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||||
constructor() {
|
constructor(configService: ConfigService) {
|
||||||
|
const realm = configService.get<string>('REALM');
|
||||||
super({
|
super({
|
||||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||||
ignoreExpiration: false,
|
ignoreExpiration: false,
|
||||||
|
|
@ -13,15 +16,16 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||||
cache: true,
|
cache: true,
|
||||||
rateLimit: true,
|
rateLimit: true,
|
||||||
jwksRequestsPerMinute: 5,
|
jwksRequestsPerMinute: 5,
|
||||||
jwksUri: 'https://auth.bizmatch.net/realms/dev/protocol/openid-connect/certs',
|
jwksUri: `https://auth.bizmatch.net/realms/${realm}/protocol/openid-connect/certs`,
|
||||||
}),
|
}),
|
||||||
audience: 'account', // Keycloak Client ID
|
audience: 'account', // Keycloak Client ID
|
||||||
issuer: 'https://auth.bizmatch.net/realms/dev',
|
authorize: '',
|
||||||
|
issuer: `https://auth.bizmatch.net/realms/${realm}`,
|
||||||
algorithms: ['RS256'],
|
algorithms: ['RS256'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async validate(payload: any) {
|
async validate(payload: any): Promise<JwtUser> {
|
||||||
console.log('JWT Payload:', payload); // Debugging: JWT Payload anzeigen
|
console.log('JWT Payload:', payload); // Debugging: JWT Payload anzeigen
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
console.error('Invalid payload');
|
console.error('Invalid payload');
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import { businesses } from '../drizzle/schema.js';
|
import { businesses } from '../drizzle/schema.js';
|
||||||
import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js';
|
import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js';
|
||||||
import { ListingCriteria } from '../models/main.model.js';
|
import { JwtUser, ListingCriteria } from '../models/main.model.js';
|
||||||
import { ListingsService } from './listings.service.js';
|
import { ListingsService } from './listings.service.js';
|
||||||
|
|
||||||
@Controller('listings/business')
|
@Controller('listings/business')
|
||||||
|
|
@ -13,15 +13,16 @@ export class BusinessListingsController {
|
||||||
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findById(@Param('id') id: string): any {
|
findById(@Request() req, @Param('id') id: string): any {
|
||||||
return this.listingsService.findById(id, businesses);
|
return this.listingsService.findBusinessesById(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get('user/:userid')
|
@Get('user/:userid')
|
||||||
findByUserId(@Request() req, @Param('userid') userid: string): any {
|
findByUserId(@Request() req, @Param('userid') userid: string): any {
|
||||||
return this.listingsService.findByUserId(userid, businesses, req.user?.username);
|
return this.listingsService.findBusinessesByEmail(userid, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('search')
|
@Post('search')
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { Body, Controller, Delete, Get, Inject, Param, Post, Put, Request, UseGuards } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Inject, Param, Post, Put, Request, UseGuards } from '@nestjs/common';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
|
import { CommercialPropertyListing } from 'src/models/db.model.js';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import { commercials } from '../drizzle/schema.js';
|
import { commercials } from '../drizzle/schema.js';
|
||||||
import { FileService } from '../file/file.service.js';
|
import { FileService } from '../file/file.service.js';
|
||||||
import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js';
|
import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js';
|
||||||
import { ListingCriteria } from '../models/main.model.js';
|
import { JwtUser, ListingCriteria } from '../models/main.model.js';
|
||||||
import { ListingsService } from './listings.service.js';
|
import { ListingsService } from './listings.service.js';
|
||||||
|
|
||||||
@Controller('listings/commercialProperty')
|
@Controller('listings/commercialProperty')
|
||||||
|
|
@ -15,16 +16,16 @@ export class CommercialPropertyListingsController {
|
||||||
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findById(@Param('id') id: string): any {
|
findById(@Request() req, @Param('id') id: string): any {
|
||||||
return this.listingsService.findById(id, commercials);
|
return this.listingsService.findCommercialPropertiesById(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(OptionalJwtAuthGuard)
|
@UseGuards(OptionalJwtAuthGuard)
|
||||||
@Get('user/:userid')
|
@Get('user/:email')
|
||||||
findByUserId(@Request() req, @Param('userid') userid: string): any {
|
findByEmail(@Request() req, @Param('email') email: string): Promise<CommercialPropertyListing[]> {
|
||||||
console.log(req.user?.username);
|
return this.listingsService.findCommercialPropertiesByEmail(email, req.user as JwtUser);
|
||||||
return this.listingsService.findByUserId(userid, commercials, req.user?.username);
|
|
||||||
}
|
}
|
||||||
@Post('search')
|
@Post('search')
|
||||||
async find(@Body() criteria: ListingCriteria): Promise<any> {
|
async find(@Body() criteria: ListingCriteria): Promise<any> {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { Logger } from 'winston';
|
||||||
import * as schema from '../drizzle/schema.js';
|
import * as schema from '../drizzle/schema.js';
|
||||||
import { PG_CONNECTION, businesses, commercials } from '../drizzle/schema.js';
|
import { PG_CONNECTION, businesses, commercials } from '../drizzle/schema.js';
|
||||||
import { FileService } from '../file/file.service.js';
|
import { FileService } from '../file/file.service.js';
|
||||||
import { ListingCriteria } from '../models/main.model.js';
|
import { JwtUser, ListingCriteria, emailToDirName } from '../models/main.model.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ListingsService {
|
export class ListingsService {
|
||||||
|
|
@ -64,12 +64,21 @@ export class ListingsService {
|
||||||
]);
|
]);
|
||||||
return { total, data };
|
return { total, data };
|
||||||
}
|
}
|
||||||
async findById(id: string, table: typeof businesses | typeof commercials): Promise<BusinessListing | CommercialPropertyListing> {
|
async findCommercialPropertiesById(id: string, user: JwtUser): Promise<CommercialPropertyListing> {
|
||||||
const result = await this.conn
|
let result = await this.conn
|
||||||
.select()
|
.select()
|
||||||
.from(table)
|
.from(commercials)
|
||||||
.where(and(sql`${table.id} = ${id}`, ne(table.draft, true)));
|
.where(and(sql`${commercials.id} = ${id}`));
|
||||||
return result[0] as BusinessListing | CommercialPropertyListing;
|
result = result.filter(r => !r.draft || r.imagePath === emailToDirName(user.username) || user.roles.includes('ADMIN'));
|
||||||
|
return result[0] as CommercialPropertyListing;
|
||||||
|
}
|
||||||
|
async findBusinessesById(id: string, user: JwtUser): Promise<CommercialPropertyListing> {
|
||||||
|
let result = await this.conn
|
||||||
|
.select()
|
||||||
|
.from(businesses)
|
||||||
|
.where(and(sql`${businesses.id} = ${id}`));
|
||||||
|
result = result.filter(r => !r.draft || r.imageName === emailToDirName(user.username) || user.roles.includes('ADMIN'));
|
||||||
|
return result[0] as BusinessListing;
|
||||||
}
|
}
|
||||||
async findByImagePath(imagePath: string, serial: string): Promise<CommercialPropertyListing> {
|
async findByImagePath(imagePath: string, serial: string): Promise<CommercialPropertyListing> {
|
||||||
const result = await this.conn
|
const result = await this.conn
|
||||||
|
|
@ -78,10 +87,28 @@ export class ListingsService {
|
||||||
.where(and(sql`${commercials.imagePath} = ${imagePath}`, sql`${commercials.serialId} = ${serial}`, ne(commercials.draft, true)));
|
.where(and(sql`${commercials.imagePath} = ${imagePath}`, sql`${commercials.serialId} = ${serial}`, ne(commercials.draft, true)));
|
||||||
return result[0] as CommercialPropertyListing;
|
return result[0] as CommercialPropertyListing;
|
||||||
}
|
}
|
||||||
async findByUserId(userId: string, table: typeof businesses | typeof commercials, email: string): Promise<BusinessListing[] | CommercialPropertyListing[]> {
|
async findCommercialPropertiesByEmail(email: string, user: JwtUser): Promise<CommercialPropertyListing[]> {
|
||||||
return (await this.conn.select().from(table).where(eq(table.userId, userId))) as BusinessListing[] | CommercialPropertyListing[];
|
const conditions = [];
|
||||||
|
conditions.push(eq(commercials.imagePath, emailToDirName(email)));
|
||||||
|
if (email !== user.username && !user.roles.includes('ADMIN')) {
|
||||||
|
conditions.push(ne(commercials.draft, true));
|
||||||
|
}
|
||||||
|
return (await this.conn
|
||||||
|
.select()
|
||||||
|
.from(commercials)
|
||||||
|
.where(and(...conditions))) as CommercialPropertyListing[];
|
||||||
|
}
|
||||||
|
async findBusinessesByEmail(email: string, user: JwtUser): Promise<BusinessListing[]> {
|
||||||
|
const conditions = [];
|
||||||
|
conditions.push(eq(businesses.imageName, emailToDirName(email)));
|
||||||
|
if (email !== user.username && !user.roles.includes('ADMIN')) {
|
||||||
|
conditions.push(ne(businesses.draft, true));
|
||||||
|
}
|
||||||
|
return (await this.conn
|
||||||
|
.select()
|
||||||
|
.from(businesses)
|
||||||
|
.where(and(...conditions))) as CommercialPropertyListing[];
|
||||||
}
|
}
|
||||||
|
|
||||||
async createListing(data: BusinessListing | CommercialPropertyListing, table: typeof businesses | typeof commercials): Promise<BusinessListing | CommercialPropertyListing> {
|
async createListing(data: BusinessListing | CommercialPropertyListing, table: typeof businesses | typeof commercials): Promise<BusinessListing | CommercialPropertyListing> {
|
||||||
data.created = new Date();
|
data.created = new Date();
|
||||||
data.updated = new Date();
|
data.updated = new Date();
|
||||||
|
|
@ -120,8 +147,8 @@ export class ListingsService {
|
||||||
// ##############################################################
|
// ##############################################################
|
||||||
// Images for commercial Properties
|
// Images for commercial Properties
|
||||||
// ##############################################################
|
// ##############################################################
|
||||||
async deleteImage(id: string, name: string) {
|
async deleteImage(imagePath: string, serial: string, name: string) {
|
||||||
const listing = (await this.findById(id, commercials)) as unknown as CommercialPropertyListing;
|
const listing = (await this.findByImagePath(imagePath, serial)) as unknown as CommercialPropertyListing;
|
||||||
const index = listing.imageOrder.findIndex(im => im === name);
|
const index = listing.imageOrder.findIndex(im => im === name);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
listing.imageOrder.splice(index, 1);
|
listing.imageOrder.splice(index, 1);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { Controller, Get, Inject, Param } from '@nestjs/common';
|
import { Controller, Inject } from '@nestjs/common';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import { businesses, commercials } from '../drizzle/schema.js';
|
|
||||||
import { ListingsService } from './listings.service.js';
|
import { ListingsService } from './listings.service.js';
|
||||||
|
|
||||||
@Controller('listings/undefined')
|
@Controller('listings/undefined')
|
||||||
|
|
@ -11,13 +10,13 @@ export class UnknownListingsController {
|
||||||
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get(':id')
|
// @Get(':id')
|
||||||
async findById(@Param('id') id: string): Promise<any> {
|
// async findById(@Param('id') id: string): Promise<any> {
|
||||||
const result = await this.listingsService.findById(id, businesses);
|
// const result = await this.listingsService.findById(id, businesses);
|
||||||
if (result) {
|
// if (result) {
|
||||||
return result;
|
// return result;
|
||||||
} else {
|
// } else {
|
||||||
return await this.listingsService.findById(id, commercials);
|
// return await this.listingsService.findById(id, commercials);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,11 @@ export interface KeycloakUser {
|
||||||
notBefore?: number;
|
notBefore?: number;
|
||||||
access?: Access;
|
access?: Access;
|
||||||
}
|
}
|
||||||
|
export interface JwtUser {
|
||||||
|
userId: string;
|
||||||
|
username: string;
|
||||||
|
roles: string[];
|
||||||
|
}
|
||||||
export interface Access {
|
export interface Access {
|
||||||
manageGroupMembership: boolean;
|
manageGroupMembership: boolean;
|
||||||
view: boolean;
|
view: boolean;
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,7 @@ export class DetailsUserComponent {
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.user = await this.userService.getById(this.id);
|
this.user = await this.userService.getById(this.id);
|
||||||
this.user.email;
|
const results = await Promise.all([await this.listingsService.getListingsByEmail(this.user.email, 'business'), await this.listingsService.getListingsByEmail(this.user.email, 'commercialProperty')]);
|
||||||
const results = await Promise.all([await this.listingsService.getListingByUserId(this.id, 'business'), await this.listingsService.getListingByUserId(this.id, 'commercialProperty')]);
|
|
||||||
// Zuweisen der Ergebnisse zu den Member-Variablen der Klasse
|
// Zuweisen der Ergebnisse zu den Member-Variablen der Klasse
|
||||||
this.businessListings = results[0];
|
this.businessListings = results[0];
|
||||||
this.commercialPropListings = results[1];
|
this.commercialPropListings = results[1];
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
<div class="mb-4 col-12 md:col-6">
|
||||||
|
<p-inputSwitch inputId="draft" [(ngModel)]="listing.draft"></p-inputSwitch>
|
||||||
|
<span class="ml-2 text-900 absolute translate-y-5">Draft Mode (Will not be shown as public listing)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<p-divider></p-divider>
|
<p-divider></p-divider>
|
||||||
<div class="flex gap-5 flex-column-reverse md:flex-row">
|
<div class="flex gap-5 flex-column-reverse md:flex-row">
|
||||||
<div class="flex-auto p-fluid">
|
<div class="flex-auto p-fluid">
|
||||||
|
|
@ -137,3 +144,4 @@
|
||||||
</div>
|
</div>
|
||||||
<p-toast></p-toast>
|
<p-toast></p-toast>
|
||||||
<p-confirmDialog></p-confirmDialog>
|
<p-confirmDialog></p-confirmDialog>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export class MyListingComponent {
|
||||||
const keycloakUser = map2User(token);
|
const keycloakUser = map2User(token);
|
||||||
const email = keycloakUser.email;
|
const email = keycloakUser.email;
|
||||||
this.user = await this.userService.getByMail(email);
|
this.user = await this.userService.getByMail(email);
|
||||||
const result = await Promise.all([await this.listingsService.getListingByUserId(this.user.id, 'business'), await this.listingsService.getListingByUserId(this.user.id, 'commercialProperty')]);
|
const result = await Promise.all([await this.listingsService.getListingsByEmail(this.user.email, 'business'), await this.listingsService.getListingsByEmail(this.user.email, 'commercialProperty')]);
|
||||||
this.myListings = [...result[0], ...result[1]];
|
this.myListings = [...result[0], ...result[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ export class MyListingComponent {
|
||||||
} else {
|
} else {
|
||||||
await this.listingsService.deleteCommercialPropertyListing(listing.id, (<CommercialPropertyListing>listing).imagePath);
|
await this.listingsService.deleteCommercialPropertyListing(listing.id, (<CommercialPropertyListing>listing).imagePath);
|
||||||
}
|
}
|
||||||
const result = await Promise.all([await this.listingsService.getListingByUserId(this.user.id, 'business'), await this.listingsService.getListingByUserId(this.user.id, 'commercialProperty')]);
|
const result = await Promise.all([await this.listingsService.getListingsByEmail(this.user.email, 'business'), await this.listingsService.getListingsByEmail(this.user.email, 'commercialProperty')]);
|
||||||
this.myListings = [...result[0], ...result[1]];
|
this.myListings = [...result[0], ...result[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ export class ListingsService {
|
||||||
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
|
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
getListingByUserId(userid: string, listingsCategory: 'business' | 'commercialProperty'): Promise<ListingType[]> {
|
getListingsByEmail(email: string, listingsCategory: 'business' | 'commercialProperty'): Promise<ListingType[]> {
|
||||||
return lastValueFrom(this.http.get<BusinessListing[]>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/user/${userid}`));
|
return lastValueFrom(this.http.get<BusinessListing[]>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/user/${email}`));
|
||||||
}
|
}
|
||||||
async save(listing: any, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
|
async save(listing: any, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
|
||||||
if (listing.id) {
|
if (listing.id) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue