fix(server): add user id to comment-attachment model (#13113)

close AF-2723



#### PR Dependency Tree


* **PR #13113** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Comment attachments now track and display the user who uploaded them.

* **Tests**
* Updated tests to verify that the uploader’s information is correctly
stored and retrieved with comment attachments.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fengmk2
2025-07-09 20:16:09 +08:00
committed by GitHub
parent d4c905600b
commit 45c016af8b
6 changed files with 26 additions and 10 deletions

View File

@@ -73,7 +73,8 @@ e2e('should get comment attachment body', async t => {
docId,
key,
'test.txt',
Buffer.from('test')
Buffer.from('test'),
owner.id
);
const res = await app.GET(

View File

@@ -361,7 +361,8 @@ export class CommentResolver {
docId,
key,
attachment.filename ?? key,
buffer
buffer,
me.id
);
return this.commentAttachmentStorage.getUrl(workspaceId, docId, key);
}

View File

@@ -24,11 +24,12 @@ test.after.always(async () => {
test('should put comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
const docId = randomUUID();
const key = randomUUID();
const blob = Buffer.from('test');
await storage.put(workspace.id, docId, key, 'test.txt', blob);
await storage.put(workspace.id, docId, key, 'test.txt', blob, user.id);
const item = await models.commentAttachment.get(workspace.id, docId, key);
@@ -39,15 +40,17 @@ test('should put comment attachment', async t => {
t.is(item?.mime, 'text/plain');
t.is(item?.size, blob.length);
t.is(item?.name, 'test.txt');
t.is(item?.createdBy, user.id);
});
test('should get comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
const docId = randomUUID();
const key = randomUUID();
const blob = Buffer.from('test');
await storage.put(workspace.id, docId, key, 'test.txt', blob);
await storage.put(workspace.id, docId, key, 'test.txt', blob, user.id);
const item = await storage.get(workspace.id, docId, key);
@@ -62,11 +65,12 @@ test('should get comment attachment', async t => {
test('should get comment attachment with access url', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
const docId = randomUUID();
const key = randomUUID();
const blob = Buffer.from('test');
await storage.put(workspace.id, docId, key, 'test.txt', blob);
await storage.put(workspace.id, docId, key, 'test.txt', blob, user.id);
const url = storage.getUrl(workspace.id, docId, key);
@@ -79,11 +83,12 @@ test('should get comment attachment with access url', async t => {
test('should delete comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
const docId = randomUUID();
const key = randomUUID();
const blob = Buffer.from('test');
await storage.put(workspace.id, docId, key, 'test.txt', blob);
await storage.put(workspace.id, docId, key, 'test.txt', blob, user.id);
await storage.delete(workspace.id, docId, key);
@@ -94,11 +99,12 @@ test('should delete comment attachment', async t => {
test('should handle comment.attachment.delete event', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
const docId = randomUUID();
const key = randomUUID();
const blob = Buffer.from('test');
await storage.put(workspace.id, docId, key, 'test.txt', blob);
await storage.put(workspace.id, docId, key, 'test.txt', blob, user.id);
await storage.onCommentAttachmentDelete({
workspaceId: workspace.id,
@@ -113,14 +119,15 @@ test('should handle comment.attachment.delete event', async t => {
test('should handle workspace.deleted event', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
const docId = randomUUID();
const key1 = randomUUID();
const key2 = randomUUID();
const blob1 = Buffer.from('test');
const blob2 = Buffer.from('test2');
await storage.put(workspace.id, docId, key1, 'test.txt', blob1);
await storage.put(workspace.id, docId, key2, 'test.txt', blob2);
await storage.put(workspace.id, docId, key1, 'test.txt', blob1, user.id);
await storage.put(workspace.id, docId, key2, 'test.txt', blob2, user.id);
const count = module.event.count('comment.attachment.delete');

View File

@@ -59,7 +59,8 @@ export class CommentAttachmentStorage {
docId: string,
key: string,
name: string,
blob: Buffer
blob: Buffer,
userId: string
) {
const meta = autoMetadata(blob);
@@ -75,6 +76,7 @@ export class CommentAttachmentStorage {
name,
mime: meta.contentType ?? 'application/octet-stream',
size: blob.length,
createdBy: userId,
});
}

View File

@@ -13,6 +13,7 @@ test.after.always(async () => {
test('should upsert comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
const user = await module.create(Mockers.User);
// add
const item = await models.commentAttachment.upsert({
@@ -22,6 +23,7 @@ test('should upsert comment attachment', async t => {
name: 'test-name',
mime: 'text/plain',
size: 100,
createdBy: user.id,
});
t.is(item.workspaceId, workspace.id);
@@ -30,6 +32,7 @@ test('should upsert comment attachment', async t => {
t.is(item.mime, 'text/plain');
t.is(item.size, 100);
t.truthy(item.createdAt);
t.is(item.createdBy, user.id);
// update
const item2 = await models.commentAttachment.upsert({
@@ -46,6 +49,7 @@ test('should upsert comment attachment', async t => {
t.is(item2.key, 'test-key');
t.is(item2.mime, 'text/html');
t.is(item2.size, 200);
t.is(item2.createdBy, user.id);
// make sure only one blob is created
const items = await models.commentAttachment.list(workspace.id);

View File

@@ -32,6 +32,7 @@ export class CommentAttachmentModel extends BaseModel {
name: input.name,
mime: input.mime,
size: input.size,
createdBy: input.createdBy,
},
});
}