Skip to content

Commit 80bd4fe

Browse files
committed
remove viewing secrets
1 parent edb5545 commit 80bd4fe

22 files changed

Lines changed: 75 additions & 811 deletions

backend/src/entities/user-secret/application/data-structures/found-secret.ds.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
export class FoundSecretDS {
22
id: string;
33
slug: string;
4-
value?: string;
54
companyId: string;
65
createdAt: Date;
76
updatedAt: Date;
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export class GetSecretDS {
22
userId: string;
33
slug: string;
4-
masterPassword?: string;
54
}

backend/src/entities/user-secret/application/dto/found-secret.dto.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,6 @@ export class FoundSecretDto {
1515
})
1616
slug: string;
1717

18-
@ApiProperty({
19-
type: String,
20-
required: false,
21-
description: 'Decrypted secret value (only included when retrieving a specific secret)',
22-
example: 'my-secret-value-123',
23-
})
24-
value?: string;
25-
2618
@ApiProperty({
2719
type: String,
2820
description: 'Company ID that owns this secret',
Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import { ForbiddenException, GoneException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
1+
import { GoneException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
22
import AbstractUseCase from '../../../common/abstract-use.case.js';
33
import { BaseType } from '../../../common/data-injection.tokens.js';
44
import { IGlobalDatabaseContext } from '../../../common/application/global-database-context.interface.js';
55
import { GetSecretDS } from '../application/data-structures/get-secret.ds.js';
66
import { FoundSecretDS } from '../application/data-structures/found-secret.ds.js';
77
import { IGetSecretBySlug } from './user-secret-use-cases.interface.js';
88
import { buildFoundSecretDS } from '../utils/build-found-secret.ds.js';
9-
import { Encryptor } from '../../../helpers/encryption/encryptor.js';
10-
import { SecretActionEnum } from '../../secret-access-log/secret-access-log.entity.js';
119
import { Messages } from '../../../exceptions/text/messages.js';
1210

1311
@Injectable({ scope: Scope.REQUEST })
@@ -20,7 +18,7 @@ export class GetSecretBySlugUseCase extends AbstractUseCase<GetSecretDS, FoundSe
2018
}
2119

2220
protected async implementation(inputData: GetSecretDS): Promise<FoundSecretDS> {
23-
const { userId, slug, masterPassword } = inputData;
21+
const { userId, slug } = inputData;
2422

2523
const user = await this._dbContext.userRepository.findOne({
2624
where: { id: userId },
@@ -41,35 +39,6 @@ export class GetSecretBySlugUseCase extends AbstractUseCase<GetSecretDS, FoundSe
4139
throw new GoneException(Messages.SECRET_EXPIRED);
4240
}
4341

44-
if (secret.masterEncryption && !masterPassword) {
45-
throw new ForbiddenException(Messages.SECRET_MASTER_PASSWORD_REQUIRED);
46-
}
47-
48-
if (secret.masterEncryption && masterPassword) {
49-
const isValid = await Encryptor.verifyUserPassword(masterPassword, secret.masterHash);
50-
if (!isValid) {
51-
await this._dbContext.secretAccessLogRepository.createAccessLog(
52-
secret.id,
53-
userId,
54-
SecretActionEnum.VIEW,
55-
false,
56-
Messages.SECRET_MASTER_PASSWORD_INVALID,
57-
);
58-
throw new ForbiddenException(Messages.SECRET_MASTER_PASSWORD_INVALID);
59-
}
60-
}
61-
62-
secret.lastAccessedAt = new Date();
63-
await this._dbContext.userSecretRepository.save(secret);
64-
65-
await this._dbContext.secretAccessLogRepository.createAccessLog(secret.id, userId, SecretActionEnum.VIEW);
66-
67-
let decryptedValue = Encryptor.decryptData(secret.encryptedValue);
68-
69-
if (secret.masterEncryption && masterPassword) {
70-
decryptedValue = Encryptor.decryptDataMasterPwd(decryptedValue, masterPassword);
71-
}
72-
73-
return buildFoundSecretDS(secret, decryptedValue);
42+
return buildFoundSecretDS(secret);
7443
}
7544
}

backend/src/entities/user-secret/user-secret.controller.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,9 @@ export class UserSecretController {
128128
@ApiOperation({ summary: 'Get secret by slug' })
129129
@ApiResponse({
130130
status: 200,
131-
description: 'Returns secret details with decrypted value.',
131+
description: 'Returns secret metadata (value is never exposed).',
132132
type: FoundSecretDto,
133133
})
134-
@ApiResponse({
135-
status: 403,
136-
description: 'Master password required or incorrect.',
137-
})
138134
@ApiResponse({
139135
status: 404,
140136
description: 'Secret or user not found.',
@@ -146,15 +142,10 @@ export class UserSecretController {
146142
@ApiParam({ name: 'slug', type: String, description: 'Unique secret identifier', example: 'database-password' })
147143
@UseGuards(CompanyUserGuard)
148144
@Get('/secrets/:slug')
149-
async getSecretBySlug(
150-
@UserId() userId: string,
151-
@Param('slug') slug: string,
152-
@MasterPassword() masterPassword?: string,
153-
): Promise<FoundSecretDto> {
145+
async getSecretBySlug(@UserId() userId: string, @Param('slug') slug: string): Promise<FoundSecretDto> {
154146
const foundSecret = await this.getSecretBySlugUseCase.execute({
155147
userId,
156148
slug,
157-
masterPassword,
158149
});
159150
return buildFoundSecretDto(foundSecret);
160151
}

backend/src/entities/user-secret/utils/build-created-secret.dto.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export function buildCreatedSecretDto(ds: CreatedSecretDS): FoundSecretDto {
55
return {
66
id: ds.id,
77
slug: ds.slug,
8-
value: undefined,
98
companyId: ds.companyId,
109
createdAt: ds.createdAt,
1110
updatedAt: ds.updatedAt,

backend/src/entities/user-secret/utils/build-found-secret.ds.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { FoundSecretDS } from '../application/data-structures/found-secret.ds.js';
22
import { UserSecretEntity } from '../user-secret.entity.js';
33

4-
export function buildFoundSecretDS(secret: UserSecretEntity, decryptedValue?: string): FoundSecretDS {
4+
export function buildFoundSecretDS(secret: UserSecretEntity): FoundSecretDS {
55
return {
66
id: secret.id,
77
slug: secret.slug,
8-
value: decryptedValue,
98
companyId: secret.companyId,
109
createdAt: secret.createdAt,
1110
updatedAt: secret.updatedAt,

backend/src/entities/user-secret/utils/build-found-secret.dto.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export function buildFoundSecretDto(ds: FoundSecretDS): FoundSecretDto {
55
return {
66
id: ds.id,
77
slug: ds.slug,
8-
value: ds.value,
98
companyId: ds.companyId,
109
createdAt: ds.createdAt,
1110
updatedAt: ds.updatedAt,

backend/src/entities/user-secret/utils/build-updated-secret.dto.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export function buildUpdatedSecretDto(ds: UpdatedSecretDS): FoundSecretDto {
55
return {
66
id: ds.id,
77
slug: ds.slug,
8-
value: undefined,
98
companyId: ds.companyId,
109
createdAt: ds.createdAt,
1110
updatedAt: ds.updatedAt,

frontend/src/app/components/secrets/edit-secret-dialog/edit-secret-dialog.component.css

Lines changed: 19 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -14,68 +14,7 @@ mat-dialog-content {
1414
margin-bottom: 16px;
1515
}
1616

17-
.loading-container {
18-
display: flex;
19-
flex-direction: column;
20-
align-items: center;
21-
justify-content: center;
22-
padding: 40px;
23-
text-align: center;
24-
}
25-
26-
.loading-container p {
27-
margin-top: 16px;
28-
color: rgba(0, 0, 0, 0.54);
29-
}
30-
31-
@media (prefers-color-scheme: dark) {
32-
.loading-container p {
33-
color: rgba(255, 255, 255, 0.54);
34-
}
35-
}
36-
37-
.master-password-container {
38-
display: flex;
39-
flex-direction: column;
40-
align-items: center;
41-
text-align: center;
42-
padding: 24px;
43-
}
44-
45-
.lock-icon {
46-
font-size: 48px;
47-
width: 48px;
48-
height: 48px;
49-
color: #1976d2;
50-
margin-bottom: 16px;
51-
}
52-
53-
@media (prefers-color-scheme: dark) {
54-
.lock-icon {
55-
color: #64b5f6;
56-
}
57-
}
58-
59-
.master-password-container h3 {
60-
margin: 0 0 8px 0;
61-
}
62-
63-
.master-password-container p {
64-
color: rgba(0, 0, 0, 0.54);
65-
margin: 0 0 24px 0;
66-
}
67-
68-
@media (prefers-color-scheme: dark) {
69-
.master-password-container p {
70-
color: rgba(255, 255, 255, 0.54);
71-
}
72-
}
73-
74-
.expiration-section {
75-
margin-bottom: 16px;
76-
}
77-
78-
.encryption-note {
17+
.info-note {
7918
display: flex;
8019
align-items: flex-start;
8120
gap: 8px;
@@ -84,19 +23,34 @@ mat-dialog-content {
8423
border-radius: 8px;
8524
color: #1565c0;
8625
font-size: 14px;
87-
margin-top: 16px;
26+
margin-bottom: 20px;
8827
}
8928

90-
.encryption-note mat-icon {
29+
.info-note mat-icon {
9130
font-size: 20px;
9231
width: 20px;
9332
height: 20px;
9433
flex-shrink: 0;
9534
}
9635

9736
@media (prefers-color-scheme: dark) {
98-
.encryption-note {
37+
.info-note {
9938
background-color: rgba(100, 181, 246, 0.15);
10039
color: #64b5f6;
10140
}
10241
}
42+
43+
.expiration-section {
44+
margin-bottom: 16px;
45+
}
46+
47+
.master-password-section {
48+
margin-top: 16px;
49+
}
50+
51+
.master-password-error {
52+
color: #f44336;
53+
font-size: 12px;
54+
margin-top: -12px;
55+
margin-bottom: 8px;
56+
}

0 commit comments

Comments
 (0)