-
-
Notifications
You must be signed in to change notification settings - Fork 18
feat: add hosted database password update webhook endpoint #1690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { ApiProperty } from '@nestjs/swagger'; | ||
| import { IsNotEmpty, IsString, IsUUID } from 'class-validator'; | ||
|
|
||
| export class UpdateHostedConnectionPasswordDto { | ||
| @ApiProperty({ | ||
| description: 'Company ID', | ||
| example: '123e4567-e89b-12d3-a456-426614174000', | ||
| }) | ||
| @IsNotEmpty() | ||
| @IsString() | ||
| @IsUUID() | ||
| companyId: string; | ||
|
|
||
| @ApiProperty({ | ||
| description: 'Database name', | ||
| example: 'my_database', | ||
| }) | ||
| @IsNotEmpty() | ||
| @IsString() | ||
| databaseName: string; | ||
|
|
||
| @ApiProperty({ | ||
| description: 'New database password', | ||
| example: 'new_secure_password', | ||
| }) | ||
| @IsNotEmpty() | ||
| @IsString() | ||
| password: string; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import { Inject, Injectable, NotFoundException, Scope } from '@nestjs/common'; | ||
| import AbstractUseCase from '../../../common/abstract-use.case.js'; | ||
| import { IGlobalDatabaseContext } from '../../../common/application/global-database-context.interface.js'; | ||
| import { BaseType } from '../../../common/data-injection.tokens.js'; | ||
| import { Messages } from '../../../exceptions/text/messages.js'; | ||
| import { SuccessResponse } from '../data-structures/common-responce.ds.js'; | ||
| import { UpdateHostedConnectionPasswordDto } from '../data-structures/update-hosted-connection-password.dto.js'; | ||
| import { IUpdateHostedConnectionPassword } from './saas-use-cases.interface.js'; | ||
|
|
||
| @Injectable({ scope: Scope.REQUEST }) | ||
| export class UpdateHostedConnectionPasswordUseCase | ||
| extends AbstractUseCase<UpdateHostedConnectionPasswordDto, SuccessResponse> | ||
| implements IUpdateHostedConnectionPassword | ||
| { | ||
| constructor( | ||
| @Inject(BaseType.GLOBAL_DB_CONTEXT) | ||
| protected _dbContext: IGlobalDatabaseContext, | ||
| ) { | ||
| super(); | ||
| } | ||
|
|
||
| protected async implementation(inputData: UpdateHostedConnectionPasswordDto): Promise<SuccessResponse> { | ||
| const { companyId, databaseName, password } = inputData; | ||
|
|
||
| const foundCompany = | ||
| await this._dbContext.companyInfoRepository.findCompanyInfoByCompanyIdWithoutConnections(companyId); | ||
| if (!foundCompany) { | ||
| throw new NotFoundException(Messages.COMPANY_NOT_FOUND); | ||
| } | ||
|
|
||
| const companyConnections = await this._dbContext.connectionRepository.find({ | ||
| where: { company: { id: companyId } }, | ||
| }); | ||
| const connection = companyConnections.find((conn) => conn.database === databaseName); | ||
| if (!connection) { | ||
| throw new NotFoundException(Messages.CONNECTION_NOT_FOUND); | ||
| } | ||
|
Comment on lines
+34
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if there's a unique constraint on company+database
echo "=== Checking for unique constraints on connection entity ==="
rg -n "unique|@Unique|@Index" backend/src/entities/connection/connection.entity.ts -A 2 -B 2
echo "=== Checking how hosted connections are created ==="
rg -n "databaseName|database" backend/src/microservices/saas-microservice/use-cases/create-connection-for-hosted-db.use.case.tsRepository: rocket-admin/rocketadmin Length of output: 456 🏁 Script executed: cat -n backend/src/microservices/saas-microservice/use-cases/update-hosted-connection-password.use.case.ts | head -50Repository: rocket-admin/rocketadmin Length of output: 2199 🏁 Script executed: cat -n backend/src/entities/connection/connection.entity.tsRepository: rocket-admin/rocketadmin Length of output: 10808 🏁 Script executed: # Check for database migrations or constraints
fd -t f "migration" backend/src --type f | head -10Repository: rocket-admin/rocketadmin Length of output: 124 🏁 Script executed: head -200 backend/src/migrations/1594021894551-InitialMigration.ts | grep -A 5 -B 5 "connection\|unique\|UNIQUE" -iRepository: rocket-admin/rocketadmin Length of output: 4151 🏁 Script executed: # Also check if there are any other migration files that might define this constraint
find backend/src/migrations -type f -name "*.ts" | xargs grep -l "connection\|database" | head -5Repository: rocket-admin/rocketadmin Length of output: 373 🏁 Script executed: # Check for companyId in the connection table and any unique constraints added later
grep -n "companyId\|UNIQUE.*database\|UNIQUE.*company" backend/src/migrations/*.tsRepository: rocket-admin/rocketadmin Length of output: 8417 🏁 Script executed: # Also check the create-connection-for-hosted-db to see the full picture
cat -n backend/src/microservices/saas-microservice/use-cases/create-connection-for-hosted-db.use.case.tsRepository: rocket-admin/rocketadmin Length of output: 5350 Potential ambiguity if multiple connections share the same database name. The lookup uses only The database schema does not enforce a unique constraint on
🤖 Prompt for AI Agents |
||
|
|
||
| connection.password = password; | ||
| await this._dbContext.connectionRepository.saveUpdatedConnection(connection); | ||
|
|
||
| return { success: true }; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
databaseNameas the identifier for the hosted connection is ambiguous (a company can have multiple connections with the same DB name) and, because thedatabasecolumn is encrypted at rest, it can’t be used for direct DB lookups. Consider including ahostedDatabaseId/connectionId in this DTO (consistent withDeleteConnectionForHostedDbDto) and using that to target the exact connection.