Skip to content

Commit 61a72da

Browse files
delete attachments on delete comment
1 parent a44d331 commit 61a72da

File tree

9 files changed

+115
-43
lines changed

9 files changed

+115
-43
lines changed

backend/Bugget.BO/Services/Attachments/AttachmentService.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
namespace Bugget.BO.Services.Attachments;
1414

1515
public sealed class AttachmentService(
16-
AttachmentOptimizator attachmentOptimizator,
1716
AttachmentDbClient attachmentDbClient,
1817
ITaskQueue taskQueue,
1918
AttachmentEventsService attachmentEventsService,
@@ -113,6 +112,23 @@ await taskQueue.EnqueueAsync(async () =>
113112
return;
114113
}
115114

115+
public async Task DeleteCommentAttachmentsInternalAsync(
116+
int commentId)
117+
{
118+
var attachmentsDbModels = await attachmentDbClient.DeleteCommentAttachmentsAsync(commentId);
119+
if (attachmentsDbModels.Length == 0)
120+
return;
121+
122+
foreach (var attachmentDbModel in attachmentsDbModels)
123+
{
124+
await fileStorageClient.DeleteAsync(attachmentDbModel.StorageKey);
125+
if( attachmentDbModel.HasPreview.Value)
126+
{
127+
await fileStorageClient.DeleteAsync(keyGen.GetPreviewKey(attachmentDbModel.StorageKey));
128+
}
129+
}
130+
}
131+
116132
public Task<MonadeStruct<AttachmentDbModel>> SaveBugAttachmentAsync(
117133
UserIdentity user,
118134
int reportId,
Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
1+
using Bugget.BO.Services.Attachments;
12
using Bugget.DA.WebSockets;
23
using Bugget.Entities.Authentication;
34
using Bugget.Entities.DbModels.Comment;
45

56
public class CommentEventsService(
6-
IReportPageHubClient reportPageHubClient
7+
IReportPageHubClient reportPageHubClient,
8+
AttachmentService attachmentService
79
)
10+
{
11+
public async Task HandleCommentCreateEventAsync(int reportId, UserIdentity user, CommentSummaryDbModel commentSummaryDbModel)
812
{
9-
public async Task HandleCommentCreateEventAsync(int reportId, UserIdentity user, CommentSummaryDbModel commentSummaryDbModel)
10-
{
11-
await Task.WhenAll(
12-
reportPageHubClient.SendCommentCreateAsync(reportId, commentSummaryDbModel, user.SignalRConnectionId)
13-
);
14-
}
13+
await Task.WhenAll(
14+
reportPageHubClient.SendCommentCreateAsync(reportId, commentSummaryDbModel, user.SignalRConnectionId)
15+
);
16+
}
1517

16-
public async Task HandleCommentDeleteEventAsync(int reportId, UserIdentity user, int bugId, int commentId)
17-
{
18-
await Task.WhenAll(
19-
reportPageHubClient.SendCommentDeleteAsync(reportId, bugId, commentId, user.SignalRConnectionId)
20-
);
21-
}
18+
public async Task HandleCommentDeleteEventAsync(int reportId, UserIdentity user, int bugId, int commentId)
19+
{
20+
await Task.WhenAll(
21+
reportPageHubClient.SendCommentDeleteAsync(reportId, bugId, commentId, user.SignalRConnectionId),
22+
attachmentService.DeleteCommentAttachmentsInternalAsync(commentId)
23+
);
24+
}
2225

23-
public async Task HandleCommentUpdateEventAsync(int reportId, UserIdentity user, CommentSummaryDbModel commentSummaryDbModel)
24-
{
25-
await Task.WhenAll(
26-
reportPageHubClient.SendCommentUpdateAsync(reportId, commentSummaryDbModel, user.SignalRConnectionId)
27-
);
28-
}
26+
public async Task HandleCommentUpdateEventAsync(int reportId, UserIdentity user, CommentSummaryDbModel commentSummaryDbModel)
27+
{
28+
await Task.WhenAll(
29+
reportPageHubClient.SendCommentUpdateAsync(reportId, commentSummaryDbModel, user.SignalRConnectionId)
30+
);
2931
}
32+
}
3033

backend/Bugget.BO/Services/LimitsService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public sealed class LimitsService(
4141
int commentId)
4242
{
4343
var commentAttachmentsCount = await attachmentDbClient.GetCommentAttachmentsCountAsync(
44+
user.Id,
4445
user.OrganizationId,
4546
reportId,
4647
bugId,

backend/Bugget.DA/Postgres/AttachmentDbClient.cs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,21 @@
33

44
namespace Bugget.DA.Postgres;
55

6-
public class AttachmentDbClient: PostgresClient
6+
public class AttachmentDbClient : PostgresClient
77
{
8+
public async Task<AttachmentDbModel[]> DeleteCommentAttachmentsAsync(int commentId)
9+
{
10+
await using var connection = await DataSource.OpenConnectionAsync();
11+
12+
return (await connection.QueryAsync<AttachmentDbModel>(
13+
"SELECT * FROM public.delete_comment_attachments_internal(@commentId)",
14+
new
15+
{
16+
commentId
17+
}
18+
)).ToArray();
19+
}
20+
821
public async Task<AttachmentDbModel> UpdateAttachmentAsync(UpdateAttachmentDbModel updateAttachmentDbModel)
922
{
1023
await using var connection = await DataSource.OpenConnectionAsync();
@@ -25,7 +38,8 @@ public async Task<AttachmentDbModel> UpdateAttachmentAsync(UpdateAttachmentDbMod
2538
);
2639
}
2740

28-
public async Task<AttachmentDbModel?> GetBugAttachmentAsync(string? organizationId, int reportId, int bugId, int attachmentId){
41+
public async Task<AttachmentDbModel?> GetBugAttachmentAsync(string? organizationId, int reportId, int bugId, int attachmentId)
42+
{
2943
await using var connection = await DataSource.OpenConnectionAsync();
3044

3145
return await connection.QuerySingleOrDefaultAsync<AttachmentDbModel>(
@@ -40,7 +54,8 @@ public async Task<AttachmentDbModel> UpdateAttachmentAsync(UpdateAttachmentDbMod
4054
);
4155
}
4256

43-
public async Task<AttachmentDbModel?> GetCommentAttachmentAsync(string? organizationId, int reportId, int bugId, int commentId, int attachmentId){
57+
public async Task<AttachmentDbModel?> GetCommentAttachmentAsync(string? organizationId, int reportId, int bugId, int commentId, int attachmentId)
58+
{
4459
await using var connection = await DataSource.OpenConnectionAsync();
4560

4661
return await connection.QuerySingleOrDefaultAsync<AttachmentDbModel>(
@@ -59,7 +74,7 @@ public async Task<AttachmentDbModel> UpdateAttachmentAsync(UpdateAttachmentDbMod
5974
public async Task<int> GetBugAttachmentsCountAsync(string? organizationId, int reportId, int bugId, int attachType)
6075
{
6176
await using var connection = await DataSource.OpenConnectionAsync();
62-
77+
6378
var result = await connection.ExecuteScalarAsync<int>(
6479
"SELECT public.get_bug_attachments_count(@organizationId, @reportId, @bugId, @attachType)",
6580
new
@@ -74,14 +89,15 @@ public async Task<int> GetBugAttachmentsCountAsync(string? organizationId, int r
7489
return result;
7590
}
7691

77-
public async Task<int> GetCommentAttachmentsCountAsync(string? organizationId, int reportId, int bugId, int commentId)
92+
public async Task<int> GetCommentAttachmentsCountAsync(string userId, string? organizationId, int reportId, int bugId, int commentId)
7893
{
7994
await using var connection = await DataSource.OpenConnectionAsync();
80-
95+
8196
var result = await connection.ExecuteScalarAsync<int>(
82-
"SELECT public.get_comment_attachments_count(@organizationId, @reportId, @bugId, @commentId)",
97+
"SELECT public.get_comment_attachments_count(@userId, @organizationId, @reportId, @bugId, @commentId)",
8398
new
8499
{
100+
userId,
85101
organizationId,
86102
reportId,
87103
bugId,

backend/Bugget/Controllers/Comments/CommentAttachmentsController copy.cs renamed to backend/Bugget/Controllers/Comments/CommentAttachmentsController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ CancellationToken ct
5353
bugId,
5454
commentId,
5555
fileStream,
56-
new FileMeta(file.FileName, file.Length, file.ContentType),
56+
new FileMeta(file.FileName, file.Length, mimeType),
5757
ct)
5858
.AsActionResultAsync();
5959
}

devops/migrator/sql/001_ddl.sql

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ CREATE TABLE IF NOT EXISTS public.attachments (
4444
bug_id INT NOT NULL,
4545
path TEXT NOT NULL,
4646
created_at timestamp with time zone not null default now(),
47-
attach_type INT NOT NULL,
48-
49-
CONSTRAINT fk_attachments_bugs
50-
FOREIGN KEY (bug_id)
51-
REFERENCES public.bugs(id)
47+
attach_type INT NOT NULL
5248
);
5349

5450
-- Таблица комментариев

devops/migrator/sql/012_ddl_attachment_v2.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ ALTER TABLE public.attachments
88
ADD COLUMN IF NOT EXISTS mime_type text DEFAULT NULL,
99
ADD COLUMN IF NOT EXISTS has_preview boolean DEFAULT false,
1010
ADD COLUMN IF NOT EXISTS is_gzip_compressed boolean DEFAULT false,
11-
ADD COLUMN IF NOT EXISTS updated_at timestamp with time zone DEFAULT now();
11+
ADD COLUMN IF NOT EXISTS updated_at timestamp with time zone DEFAULT now();
12+
13+
ALTER TABLE public.attachments
14+
DROP CONSTRAINT IF EXISTS fk_attachments_bugs;
15+

devops/migrator/sql/013_dml_attachment_v2.sql

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ BEGIN
1919
END;
2020
$$;
2121

22-
CREATE OR REPLACE PROCEDURE public.check_comment_access(IN _comment_id integer, IN _bug_id integer, IN _report_id integer, IN _organization_id text)
22+
CREATE OR REPLACE PROCEDURE public.check_comment_access(IN _user_id text, IN _comment_id integer, IN _bug_id integer, IN _report_id integer, IN _organization_id text)
2323
LANGUAGE plpgsql
2424
AS $$
2525
BEGIN
@@ -35,7 +35,8 @@ BEGIN
3535
AND b.id = _bug_id
3636
AND b.report_id = _report_id
3737
AND(_organization_id IS NULL
38-
OR r.creator_organization_id = _organization_id)) THEN
38+
OR r.creator_organization_id = _organization_id)
39+
AND c.creator_user_id = _user_id) THEN
3940
RAISE EXCEPTION 'Comment % not found or access denied', _comment_id
4041
USING ERRCODE = 'P0404';
4142
END IF;
@@ -60,13 +61,13 @@ END;
6061
$$
6162
LANGUAGE plpgsql;
6263

63-
CREATE OR REPLACE FUNCTION public.get_comment_attachments_count(_organization_id text, _report_id int, _bug_id int, _comment_id int)
64+
CREATE OR REPLACE FUNCTION public.get_comment_attachments_count(_user_id text, _organization_id text, _report_id int, _bug_id int, _comment_id int)
6465
RETURNS int
6566
AS $$
6667
DECLARE
6768
_comment_attach_type int = 2;
6869
BEGIN
69-
CALL check_comment_access(_comment_id, _bug_id, _report_id, _organization_id);
70+
CALL check_comment_access(_user_id, _comment_id, _bug_id, _report_id, _organization_id);
7071
RETURN (
7172
SELECT
7273
COUNT(*)

devops/migrator/sql/014_dml_comment_v2.sql

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ CREATE OR REPLACE FUNCTION public.delete_comment_v2(_organization_id text, _user
2828
AS $$
2929
BEGIN
3030
-- Проверка доступа
31-
CALL check_comment_access(_comment_id, _bug_id, _report_id, _organization_id);
31+
CALL check_comment_access(_user_id, _comment_id, _bug_id, _report_id, _organization_id);
3232
-- Удаляем комментарий
3333
DELETE FROM public.comments
34-
WHERE public.comments.id = _comment_id
35-
AND public.comments.creator_user_id = _user_id;
34+
WHERE public.comments.id = _comment_id;
3635
END;
3736
$$;
3837

@@ -48,7 +47,7 @@ CREATE OR REPLACE FUNCTION public.update_comment_v2(_organization_id text, _user
4847
AS $$
4948
BEGIN
5049
-- 1) Проверяем, что комментарий существует и вы имеете к нему доступ
51-
CALL check_comment_access(_comment_id, _bug_id, _report_id, _organization_id);
50+
CALL check_comment_access(_user_id, _comment_id, _bug_id, _report_id, _organization_id);
5251
-- 2) Обновляем и сразу возвращаем новые значения
5352
RETURN QUERY UPDATE
5453
public.comments c
@@ -57,7 +56,6 @@ BEGIN
5756
updated_at = now()
5857
WHERE
5958
c.id = _comment_id
60-
AND c.creator_user_id = _user_id
6159
RETURNING
6260
c.id,
6361
c.bug_id,
@@ -68,3 +66,40 @@ BEGIN
6866
END;
6967
$$;
7068

69+
CREATE OR REPLACE FUNCTION public.delete_comment_attachments_internal(_comment_id integer)
70+
RETURNS TABLE(
71+
id integer,
72+
attach_type integer,
73+
entity_id integer,
74+
storage_key text,
75+
storage_kind integer,
76+
creator_user_id text,
77+
length_bytes bigint,
78+
file_name text,
79+
mime_type text,
80+
has_preview boolean,
81+
is_gzip_compressed boolean,
82+
created_at timestamp with time zone,
83+
updated_at timestamp with time zone)
84+
LANGUAGE plpgsql
85+
AS $$
86+
BEGIN
87+
RETURN QUERY DELETE FROM public.attachments a
88+
WHERE a.entity_id = _comment_id
89+
RETURNING
90+
a.id,
91+
a.attach_type,
92+
a.entity_id,
93+
a.storage_key,
94+
a.storage_kind,
95+
a.creator_user_id,
96+
a.length_bytes,
97+
a.file_name,
98+
a.mime_type,
99+
a.has_preview,
100+
a.is_gzip_compressed,
101+
a.created_at,
102+
a.updated_at;
103+
END;
104+
$$;
105+

0 commit comments

Comments
 (0)