@volontariapp/domain-post 3.6.0 → 3.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/services/comment.service.d.ts +2 -2
- package/dist/services/comment.service.d.ts.map +1 -1
- package/dist/services/comment.service.js +4 -1
- package/dist/services/comment.service.js.map +1 -1
- package/dist/test/integration/authorization.int.spec.d.ts +2 -0
- package/dist/test/integration/authorization.int.spec.d.ts.map +1 -0
- package/dist/test/integration/authorization.int.spec.js +59 -0
- package/dist/test/integration/authorization.int.spec.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PaginatedResult } from '@volontariapp/database';
|
|
2
2
|
import type { ICommentRepository, IPostRepository } from '../repositories/index.js';
|
|
3
3
|
import { CommentEntity } from '../entities/index.js';
|
|
4
|
-
import
|
|
4
|
+
import { SagaStatus, UserRoles } from '@volontariapp/shared';
|
|
5
5
|
export declare class CommentService {
|
|
6
6
|
private readonly commentRepository;
|
|
7
7
|
private readonly postRepository;
|
|
@@ -11,6 +11,6 @@ export declare class CommentService {
|
|
|
11
11
|
listPaginatedByPostId(postId: string, page: number, limit: number): Promise<PaginatedResult<CommentEntity>>;
|
|
12
12
|
create(data: Partial<CommentEntity>): Promise<CommentEntity>;
|
|
13
13
|
updateSaga(id: string, status: SagaStatus): Promise<CommentEntity>;
|
|
14
|
-
delete(id: string, actorId?: string, actorRole?:
|
|
14
|
+
delete(id: string, actorId?: string, actorRole?: UserRoles): Promise<boolean>;
|
|
15
15
|
}
|
|
16
16
|
//# sourceMappingURL=comment.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment.service.d.ts","sourceRoot":"","sources":["../../src/services/comment.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,
|
|
1
|
+
{"version":3,"file":"comment.service.d.ts","sourceRoot":"","sources":["../../src/services/comment.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE7D,qBACa,cAAc;IAKvB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc;IANjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgD;gBAIpD,iBAAiB,EAAE,kBAAkB,EAErC,cAAc,EAAE,eAAe;IAG5C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAUnD,qBAAqB,CACzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IAUpC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAkB5D,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAmBlE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;CAmBpF"}
|
|
@@ -16,6 +16,7 @@ import { Logger } from '@volontariapp/logger';
|
|
|
16
16
|
import { DATABASE_ERROR, POST_NOT_FOUND } from '@volontariapp/errors-nest';
|
|
17
17
|
import { isBaseError, ForbiddenError } from '@volontariapp/errors';
|
|
18
18
|
import { PostgresCommentRepository, PostgresPostRepository } from '../repositories/index.js';
|
|
19
|
+
import { UserRoles } from '@volontariapp/shared';
|
|
19
20
|
let CommentService = CommentService_1 = class CommentService {
|
|
20
21
|
commentRepository;
|
|
21
22
|
postRepository;
|
|
@@ -81,7 +82,7 @@ let CommentService = CommentService_1 = class CommentService {
|
|
|
81
82
|
async delete(id, actorId, actorRole) {
|
|
82
83
|
try {
|
|
83
84
|
this.logger.log(`Deleting comment ${id}`);
|
|
84
|
-
if (actorId && actorRole !==
|
|
85
|
+
if (actorId && actorRole !== UserRoles.ADMIN) {
|
|
85
86
|
const comment = await this.findById(id);
|
|
86
87
|
if (comment && comment.authorId !== actorId) {
|
|
87
88
|
throw new ForbiddenError('You are not the author of this comment');
|
|
@@ -90,6 +91,8 @@ let CommentService = CommentService_1 = class CommentService {
|
|
|
90
91
|
return await this.commentRepository.delete(id);
|
|
91
92
|
}
|
|
92
93
|
catch (error) {
|
|
94
|
+
if (isBaseError(error))
|
|
95
|
+
throw error;
|
|
93
96
|
const err = error;
|
|
94
97
|
this.logger.error(`Failed to delete comment ${id}`, err);
|
|
95
98
|
throw DATABASE_ERROR('deleting comment', err.message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment.service.js","sourceRoot":"","sources":["../../src/services/comment.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"comment.service.js","sourceRoot":"","sources":["../../src/services/comment.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.int.spec.d.ts","sourceRoot":"","sources":["../../../src/test/integration/authorization.int.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { PostgresPostRepository } from '../../repositories/postgres-post.repository.js';
|
|
4
|
+
import { PostgresCommentRepository } from '../../repositories/postgres-comment.repository.js';
|
|
5
|
+
import { PostService } from '../../services/post.service.js';
|
|
6
|
+
import { CommentService } from '../../services/comment.service.js';
|
|
7
|
+
import { UserRoles } from '@volontariapp/shared';
|
|
8
|
+
import { PostModel, CommentModel } from '../../models/index.js';
|
|
9
|
+
import { initializeTestDb, closeTestDb, truncateAll, getTestRepository } from '../data-source.js';
|
|
10
|
+
describe('Domain Post & Comment Authorization (Integration)', () => {
|
|
11
|
+
let postService;
|
|
12
|
+
let commentService;
|
|
13
|
+
let postRepository;
|
|
14
|
+
let commentRepository;
|
|
15
|
+
beforeAll(async () => {
|
|
16
|
+
await initializeTestDb();
|
|
17
|
+
postRepository = new PostgresPostRepository(getTestRepository(PostModel));
|
|
18
|
+
commentRepository = new PostgresCommentRepository(getTestRepository(CommentModel));
|
|
19
|
+
postService = new PostService(postRepository);
|
|
20
|
+
commentService = new CommentService(commentRepository, postRepository);
|
|
21
|
+
});
|
|
22
|
+
afterAll(async () => {
|
|
23
|
+
await closeTestDb();
|
|
24
|
+
});
|
|
25
|
+
beforeEach(async () => {
|
|
26
|
+
await truncateAll();
|
|
27
|
+
});
|
|
28
|
+
it('should prevent user from updating or deleting a post they do not own', async () => {
|
|
29
|
+
const authorId = randomUUID();
|
|
30
|
+
const otherUserId = randomUUID();
|
|
31
|
+
const post = await postService.create({
|
|
32
|
+
authorId,
|
|
33
|
+
title: 'Auth Test Post',
|
|
34
|
+
content: 'Auth test content',
|
|
35
|
+
});
|
|
36
|
+
await expect(postService.update(post.id, { content: 'hacked content' }, otherUserId, UserRoles.VOLUNTEER)).rejects.toThrow(/You are not the author of this post/i);
|
|
37
|
+
await expect(postService.update(post.id, { content: 'admin update' }, otherUserId, UserRoles.ADMIN)).resolves.toBeDefined();
|
|
38
|
+
await expect(postService.delete(post.id, otherUserId, UserRoles.VOLUNTEER)).rejects.toThrow(/You are not the author of this post/i);
|
|
39
|
+
await expect(postService.delete(post.id, authorId, UserRoles.VOLUNTEER)).resolves.toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
it('should prevent user from deleting a comment they do not own', async () => {
|
|
42
|
+
const authorId = randomUUID();
|
|
43
|
+
const commenterId = randomUUID();
|
|
44
|
+
const otherUserId = randomUUID();
|
|
45
|
+
const post = await postService.create({
|
|
46
|
+
authorId,
|
|
47
|
+
title: 'Auth Test Post',
|
|
48
|
+
content: 'Auth test content',
|
|
49
|
+
});
|
|
50
|
+
const comment = await commentService.create({
|
|
51
|
+
postId: post.id,
|
|
52
|
+
authorId: commenterId,
|
|
53
|
+
content: 'Auth test comment',
|
|
54
|
+
});
|
|
55
|
+
await expect(commentService.delete(comment.id, otherUserId, UserRoles.VOLUNTEER)).rejects.toThrow(/You are not the author of this comment/i);
|
|
56
|
+
await expect(commentService.delete(comment.id, otherUserId, UserRoles.ADMIN)).resolves.toBe(true);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=authorization.int.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.int.spec.js","sourceRoot":"","sources":["../../../src/test/integration/authorization.int.spec.ts"],"names":[],"mappings":"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"}
|