@volontariapp/domain-post 3.5.3 → 3.6.1
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 +9 -2
- package/dist/services/comment.service.js.map +1 -1
- package/dist/services/post.service.d.ts +3 -3
- package/dist/services/post.service.d.ts.map +1 -1
- package/dist/services/post.service.js +16 -3
- package/dist/services/post.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,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.6.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies: @volontariapp/shared@0.1.3
|
|
8
|
+
|
|
9
|
+
## 3.6.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Security: Enforce authorization checks for updating and deleting posts and comments.
|
|
14
|
+
|
|
3
15
|
## 3.5.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -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): Promise<boolean>;
|
|
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;CAkBpF"}
|
|
@@ -14,8 +14,9 @@ var CommentService_1;
|
|
|
14
14
|
import { Inject, Injectable } from '@nestjs/common';
|
|
15
15
|
import { Logger } from '@volontariapp/logger';
|
|
16
16
|
import { DATABASE_ERROR, POST_NOT_FOUND } from '@volontariapp/errors-nest';
|
|
17
|
-
import { isBaseError } from '@volontariapp/errors';
|
|
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;
|
|
@@ -78,9 +79,15 @@ let CommentService = CommentService_1 = class CommentService {
|
|
|
78
79
|
throw DATABASE_ERROR('updating comment saga status', err.message);
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
|
-
async delete(id) {
|
|
82
|
+
async delete(id, actorId, actorRole) {
|
|
82
83
|
try {
|
|
83
84
|
this.logger.log(`Deleting comment ${id}`);
|
|
85
|
+
if (actorId && actorRole !== UserRoles.ADMIN) {
|
|
86
|
+
const comment = await this.findById(id);
|
|
87
|
+
if (comment && comment.authorId !== actorId) {
|
|
88
|
+
throw new ForbiddenError('You are not the author of this comment');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
84
91
|
return await this.commentRepository.delete(id);
|
|
85
92
|
}
|
|
86
93
|
catch (error) {
|
|
@@ -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,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"comment.service.js","sourceRoot":"","sources":["../../src/services/comment.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PaginatedResult } from '@volontariapp/database';
|
|
2
2
|
import type { IPostRepository } from '../repositories/index.js';
|
|
3
|
-
import { SagaStatus } from '@volontariapp/shared';
|
|
3
|
+
import { SagaStatus, UserRoles } from '@volontariapp/shared';
|
|
4
4
|
import { PostEntity } from '../entities/index.js';
|
|
5
5
|
export declare class PostService {
|
|
6
6
|
private readonly postRepository;
|
|
@@ -11,9 +11,9 @@ export declare class PostService {
|
|
|
11
11
|
findAll(): Promise<PostEntity[]>;
|
|
12
12
|
listPosts(page: number, limit: number, authorId?: string): Promise<PaginatedResult<PostEntity>>;
|
|
13
13
|
create(data: Partial<PostEntity>): Promise<PostEntity>;
|
|
14
|
-
update(id: string, data: Partial<PostEntity
|
|
14
|
+
update(id: string, data: Partial<PostEntity>, actorId?: string, actorRole?: UserRoles): Promise<PostEntity>;
|
|
15
15
|
updateSaga(id: string, status: SagaStatus): Promise<PostEntity>;
|
|
16
|
-
delete(id: string): Promise<void>;
|
|
16
|
+
delete(id: string, actorId?: string, actorRole?: UserRoles): Promise<void>;
|
|
17
17
|
deleteByAuthorId(authorId: string): Promise<number>;
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=post.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.service.d.ts","sourceRoot":"","sources":["../../src/services/post.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"post.service.d.ts","sourceRoot":"","sources":["../../src/services/post.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,qBACa,WAAW;IAGsB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAF3E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6C;gBAEP,cAAc,EAAE,eAAe;IAEtF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAezC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAWvD,OAAO,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAUhC,SAAS,CACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAWjC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAkBtD,MAAM,CACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,EACzB,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CAAC,UAAU,CAAC;IA2BhB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAgB/D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB1E,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAiB1D"}
|
|
@@ -14,7 +14,8 @@ var PostService_1;
|
|
|
14
14
|
import { Inject, Injectable } from '@nestjs/common';
|
|
15
15
|
import { Logger } from '@volontariapp/logger';
|
|
16
16
|
import { DATABASE_ERROR, POST_ALREADY_EXISTS, POST_NOT_FOUND } from '@volontariapp/errors-nest';
|
|
17
|
-
import { isDatabaseDriverError, isBaseError } from '@volontariapp/errors';
|
|
17
|
+
import { isDatabaseDriverError, isBaseError, ForbiddenError } from '@volontariapp/errors';
|
|
18
|
+
import { UserRoles } from '@volontariapp/shared';
|
|
18
19
|
import { PostgresPostRepository } from '../repositories/index.js';
|
|
19
20
|
let PostService = PostService_1 = class PostService {
|
|
20
21
|
postRepository;
|
|
@@ -88,8 +89,14 @@ let PostService = PostService_1 = class PostService {
|
|
|
88
89
|
throw DATABASE_ERROR('creating post', err.message);
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
|
-
async update(id, data) {
|
|
92
|
+
async update(id, data, actorId, actorRole) {
|
|
92
93
|
try {
|
|
94
|
+
if (actorId && actorRole !== UserRoles.ADMIN) {
|
|
95
|
+
const post = await this.findById(id);
|
|
96
|
+
if (post.authorId !== actorId) {
|
|
97
|
+
throw new ForbiddenError('You are not the author of this post');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
93
100
|
const updated = await this.postRepository.update(id, data);
|
|
94
101
|
if (!updated) {
|
|
95
102
|
throw POST_NOT_FOUND(id);
|
|
@@ -124,9 +131,15 @@ let PostService = PostService_1 = class PostService {
|
|
|
124
131
|
throw DATABASE_ERROR(`updating post saga status: ${id}`, err.message);
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
|
-
async delete(id) {
|
|
134
|
+
async delete(id, actorId, actorRole) {
|
|
128
135
|
try {
|
|
129
136
|
this.logger.log(`Deleting post: ${id}`);
|
|
137
|
+
if (actorId && actorRole !== UserRoles.ADMIN) {
|
|
138
|
+
const post = await this.findById(id);
|
|
139
|
+
if (post.authorId !== actorId) {
|
|
140
|
+
throw new ForbiddenError('You are not the author of this post');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
130
143
|
const deleted = await this.postRepository.deleteWithPostDeleted(id);
|
|
131
144
|
if (!deleted) {
|
|
132
145
|
throw POST_NOT_FOUND(id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.service.js","sourceRoot":"","sources":["../../src/services/post.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,mBAAmB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChG,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"post.service.js","sourceRoot":"","sources":["../../src/services/post.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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"}
|