Skip to content

Commit 6c61cf9

Browse files
guguclaude
andcommitted
fix: fix encrypted field lookup in password update and return connectionId from create endpoint
The database column is stored encrypted and only decrypted in @afterload, so querying by plaintext value would never match. Now fetches connections by company and filters by decrypted database name in code. Also simplifies create hosted connection response to return just the connectionId. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c86f66a commit 6c61cf9

5 files changed

Lines changed: 29 additions & 32 deletions

File tree

backend/src/microservices/saas-microservice/data-structures/common-responce.ds.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ export class SuccessResponse {
44
@ApiProperty()
55
success: boolean;
66
}
7+
8+
export class CreatedConnectionResponse {
9+
@ApiProperty()
10+
connectionId: string;
11+
}

backend/src/microservices/saas-microservice/saas.controller.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { UserEntity } from '../../entities/user/user.entity.js';
2424
import { InTransactionEnum } from '../../enums/in-transaction.enum.js';
2525
import { Messages } from '../../exceptions/text/messages.js';
2626
import { SentryInterceptor } from '../../interceptors/sentry.interceptor.js';
27-
import { SuccessResponse } from './data-structures/common-responce.ds.js';
27+
import { CreatedConnectionResponse, SuccessResponse } from './data-structures/common-responce.ds.js';
2828
import { CreateConnectionForHostedDbDto } from './data-structures/create-connecttion-for-selfhosted-db.dto.js';
2929
import { DeleteConnectionForHostedDbDto } from './data-structures/delete-connection-for-hosted-db.dto.js';
3030
import { RegisterCompanyWebhookDS } from './data-structures/register-company.ds.js';
@@ -292,12 +292,12 @@ export class SaasController {
292292
@ApiBody({ type: CreateConnectionForHostedDbDto })
293293
@ApiResponse({
294294
status: 201,
295-
type: CreatedConnectionDTO,
295+
type: CreatedConnectionResponse,
296296
})
297297
@Post('/connection/hosted')
298298
async createConnectionForHostedDb(
299299
@Body() connectionData: CreateConnectionForHostedDbDto,
300-
): Promise<CreatedConnectionDTO> {
300+
): Promise<CreatedConnectionResponse> {
301301
return await this.createConnectionForHostedDbUseCase.execute(connectionData);
302302
}
303303

backend/src/microservices/saas-microservice/use-cases/create-connection-for-hosted-db.use.case.ts

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,19 @@ import { ConnectionTypesEnum } from '@rocketadmin/shared-code/dist/src/shared/en
44
import AbstractUseCase from '../../../common/abstract-use.case.js';
55
import { IGlobalDatabaseContext } from '../../../common/application/global-database-context.interface.js';
66
import { BaseType } from '../../../common/data-injection.tokens.js';
7-
import { Messages } from '../../../exceptions/text/messages.js';
8-
import { slackPostMessage } from '../../../helpers/index.js';
9-
import { AccessLevelEnum } from '../../../enums/index.js';
107
import { generateCedarPolicyForGroup } from '../../../entities/cedar-authorization/cedar-policy-generator.js';
11-
import { CreatedConnectionDTO } from '../../../entities/connection/application/dto/created-connection.dto.js';
128
import { ConnectionEntity } from '../../../entities/connection/connection.entity.js';
139
import { readSslCertificate } from '../../../entities/connection/ssl-certificate/read-certificate.js';
14-
import { buildCreatedConnectionDs } from '../../../entities/connection/utils/build-created-connection.ds.js';
10+
import { AccessLevelEnum } from '../../../enums/index.js';
11+
import { Messages } from '../../../exceptions/text/messages.js';
12+
import { slackPostMessage } from '../../../helpers/index.js';
13+
import { CreatedConnectionResponse } from '../data-structures/common-responce.ds.js';
1514
import { CreateConnectionForHostedDbDto } from '../data-structures/create-connecttion-for-selfhosted-db.dto.js';
1615
import { ICreateConnectionForHostedDb } from './saas-use-cases.interface.js';
1716

1817
@Injectable({ scope: Scope.REQUEST })
1918
export class CreateConnectionForHostedDbUseCase
20-
extends AbstractUseCase<CreateConnectionForHostedDbDto, CreatedConnectionDTO>
19+
extends AbstractUseCase<CreateConnectionForHostedDbDto, CreatedConnectionResponse>
2120
implements ICreateConnectionForHostedDb
2221
{
2322
constructor(
@@ -27,17 +26,15 @@ export class CreateConnectionForHostedDbUseCase
2726
super();
2827
}
2928

30-
protected async implementation(inputData: CreateConnectionForHostedDbDto): Promise<CreatedConnectionDTO> {
29+
protected async implementation(inputData: CreateConnectionForHostedDbDto): Promise<CreatedConnectionResponse> {
3130
const { companyId, userId, databaseName, hostname, port, username, password } = inputData;
3231

3332
const connectionAuthor = await this._dbContext.userRepository.findOneUserById(userId);
3433
if (!connectionAuthor) {
3534
throw new InternalServerErrorException(Messages.USER_NOT_FOUND);
3635
}
3736

38-
await slackPostMessage(
39-
Messages.USER_TRY_CREATE_CONNECTION(connectionAuthor.email, ConnectionTypesEnum.postgres),
40-
);
37+
await slackPostMessage(Messages.USER_TRY_CREATE_CONNECTION(connectionAuthor.email, ConnectionTypesEnum.postgres));
4138

4239
const cert = await readSslCertificate();
4340

@@ -85,21 +82,18 @@ export class CreateConnectionForHostedDbUseCase
8582
savedConnection,
8683
connectionAuthor,
8784
);
88-
createdAdminGroup.cedarPolicy = generateCedarPolicyForGroup(
89-
savedConnection.id,
90-
true,
91-
{
92-
connection: { connectionId: savedConnection.id, accessLevel: AccessLevelEnum.edit },
93-
group: { groupId: createdAdminGroup.id, accessLevel: AccessLevelEnum.edit },
94-
tables: [],
95-
},
96-
);
85+
createdAdminGroup.cedarPolicy = generateCedarPolicyForGroup(savedConnection.id, true, {
86+
connection: { connectionId: savedConnection.id, accessLevel: AccessLevelEnum.edit },
87+
group: { groupId: createdAdminGroup.id, accessLevel: AccessLevelEnum.edit },
88+
tables: [],
89+
});
9790
await this._dbContext.groupRepository.saveNewOrUpdatedGroup(createdAdminGroup);
9891
delete createdAdminGroup.connection;
9992
await this._dbContext.userRepository.saveUserEntity(connectionAuthor);
10093
savedConnection.groups = [createdAdminGroup];
10194

102-
const foundCompany = await this._dbContext.companyInfoRepository.findCompanyInfoByCompanyIdWithoutConnections(companyId);
95+
const foundCompany =
96+
await this._dbContext.companyInfoRepository.findCompanyInfoByCompanyIdWithoutConnections(companyId);
10397
if (foundCompany) {
10498
const connectionToUpdate = await this._dbContext.connectionRepository.findOne({
10599
where: { id: savedConnection.id },
@@ -108,11 +102,8 @@ export class CreateConnectionForHostedDbUseCase
108102
await this._dbContext.connectionRepository.saveUpdatedConnection(connectionToUpdate);
109103
}
110104

111-
await slackPostMessage(
112-
Messages.USER_CREATED_CONNECTION(connectionAuthor.email, ConnectionTypesEnum.postgres),
113-
);
105+
await slackPostMessage(Messages.USER_CREATED_CONNECTION(connectionAuthor.email, ConnectionTypesEnum.postgres));
114106

115-
const connectionRO = buildCreatedConnectionDs(savedConnection, null, null);
116-
return connectionRO;
107+
return { connectionId: savedConnection.id };
117108
}
118109
}

backend/src/microservices/saas-microservice/use-cases/saas-use-cases.interface.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SaasUsualUserRegisterDS } from '../../../entities/user/application/data
55
import { FoundUserDto } from '../../../entities/user/dto/found-user.dto.js';
66
import { UserEntity } from '../../../entities/user/user.entity.js';
77
import { InTransactionEnum } from '../../../enums/in-transaction.enum.js';
8-
import { SuccessResponse } from '../data-structures/common-responce.ds.js';
8+
import { CreatedConnectionResponse, SuccessResponse } from '../data-structures/common-responce.ds.js';
99
import { CreateConnectionForHostedDbDto } from '../data-structures/create-connecttion-for-selfhosted-db.dto.js';
1010
import { DeleteConnectionForHostedDbDto } from '../data-structures/delete-connection-for-hosted-db.dto.js';
1111
import { FreezeConnectionsInCompanyDS } from '../data-structures/freeze-connections-in-company.ds.js';
@@ -72,7 +72,7 @@ export interface ISaasSAMLRegisterUser {
7272
}
7373

7474
export interface ICreateConnectionForHostedDb {
75-
execute(inputData: CreateConnectionForHostedDbDto): Promise<CreatedConnectionDTO>;
75+
execute(inputData: CreateConnectionForHostedDbDto): Promise<CreatedConnectionResponse>;
7676
}
7777

7878
export interface IDeleteConnectionForHostedDb {

backend/src/microservices/saas-microservice/use-cases/update-hosted-connection-password.use.case.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ export class UpdateHostedConnectionPasswordUseCase
2828
throw new NotFoundException(Messages.COMPANY_NOT_FOUND);
2929
}
3030

31-
const connection = await this._dbContext.connectionRepository.findOne({
32-
where: { company: { id: companyId }, database: databaseName },
31+
const companyConnections = await this._dbContext.connectionRepository.find({
32+
where: { company: { id: companyId } },
3333
});
34+
const connection = companyConnections.find((conn) => conn.database === databaseName);
3435
if (!connection) {
3536
throw new NotFoundException(Messages.CONNECTION_NOT_FOUND);
3637
}

0 commit comments

Comments
 (0)