Skip to content

Commit 8c2c377

Browse files
committed
secure /listing/x/publish endpoint, add business rules for listing publication
1 parent 981ed90 commit 8c2c377

File tree

6 files changed

+43
-15
lines changed

6 files changed

+43
-15
lines changed

src/api/routers/catalog.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ async def create_listing(
5757
current_user: Annotated[User, Depends(get_authenticated_user)],
5858
):
5959
"""
60-
Creates a new listing.
60+
Creates a new listing
6161
"""
6262
command = CreateListingDraftCommand(
6363
listing_id=uuid.uuid4(),
@@ -83,7 +83,7 @@ async def delete_listing(
8383
current_user: Annotated[User, Depends(get_authenticated_user)],
8484
):
8585
"""
86-
Delete listing
86+
Deletes a listing
8787
"""
8888
command = DeleteListingDraftCommand(
8989
listing_id=listing_id,
@@ -100,13 +100,16 @@ async def delete_listing(
100100
)
101101
@inject
102102
async def publish_listing(
103-
listing_id: UUID, app: Annotated[Application, Depends(get_application)]
103+
listing_id: UUID,
104+
app: Annotated[Application, Depends(get_application)],
105+
current_user: Annotated[User, Depends(get_authenticated_user)],
104106
):
105107
"""
106-
Creates a new listing.
108+
Publishes a listing
107109
"""
108110
command = PublishListingDraftCommand(
109111
listing_id=listing_id,
112+
seller_id=current_user.id,
110113
)
111114
app.execute_command(command)
112115

src/api/tests/test_bidding.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ def setup_app_for_bidding_tests(app, listing_id, seller_id, bidder_id):
3636
seller_id=seller_id,
3737
)
3838
)
39-
app.execute_command(PublishListingDraftCommand(listing_id=listing_id))
39+
app.execute_command(
40+
PublishListingDraftCommand(listing_id=listing_id, seller_id=seller_id)
41+
)
4042
logger.info("test setup complete")
4143

4244

src/api/tests/test_catalog.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,44 +111,47 @@ def test_catalog_delete_non_existing_draft_returns_404(authenticated_api_client)
111111

112112

113113
@pytest.mark.integration
114-
def test_catalog_publish_listing_draft(app, api_client):
114+
def test_catalog_publish_listing_draft(app, authenticated_api_client):
115115
# arrange
116+
current_user = authenticated_api_client.current_user
116117
listing_id = UUID(int=1)
117118
app.execute_command(
118119
CreateListingDraftCommand(
119120
listing_id=listing_id,
120121
title="Listing to be published",
121122
description="...",
122123
ask_price=Money(10),
123-
seller_id=UUID("00000000000000000000000000000002"),
124+
seller_id=current_user.id,
124125
)
125126
)
126127

127128
# act
128-
response = api_client.post(f"/catalog/{listing_id}/publish")
129+
response = authenticated_api_client.post(f"/catalog/{listing_id}/publish")
129130

130131
# assert that the listing was published
131132
assert response.status_code == 200
132133

133134

134-
def test_published_listing_appears_in_biddings(app, api_client):
135+
def test_published_listing_appears_in_biddings(app, authenticated_api_client):
135136
# arrange
136137
listing_id = UUID(int=1)
138+
current_user = authenticated_api_client.current_user
137139
app.execute_command(
138140
CreateListingDraftCommand(
139141
listing_id=listing_id,
140142
title="Listing to be published",
141143
description="...",
142144
ask_price=Money(10),
143-
seller_id=UUID("00000000000000000000000000000002"),
145+
seller_id=current_user.id,
144146
)
145147
)
146148
app.execute_command(
147149
PublishListingDraftCommand(
148150
listing_id=listing_id,
151+
seller_id=current_user.id,
149152
)
150153
)
151154

152155
url = f"/bidding/{listing_id}"
153-
response = api_client.get(url)
156+
response = authenticated_api_client.get(url)
154157
assert response.status_code == 200

src/modules/catalog/application/command/publish_listing_draft.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
from modules.catalog.application import catalog_module
44
from modules.catalog.domain.entities import Listing
55
from modules.catalog.domain.repositories import ListingRepository
6-
from modules.catalog.domain.value_objects import ListingId
6+
from modules.catalog.domain.rules import OnlyListingOwnerCanPublishListing
7+
from modules.catalog.domain.value_objects import ListingId, SellerId
78
from seedwork.application.command_handlers import CommandResult
89
from seedwork.application.commands import Command
10+
from seedwork.domain.mixins import check_rule
911

1012

1113
@dataclass
1214
class PublishListingDraftCommand(Command):
1315
"""A command for publishing a draft of a listing"""
1416

15-
listing_id: ListingId
16-
# seller_id: SellerId
17+
listing_id: ListingId # a listing to be published
18+
seller_id: SellerId # a seller, who is publishing a listing
1719

1820

1921
@catalog_module.command_handler
@@ -23,6 +25,12 @@ def publish_listing_draft(
2325
):
2426
listing: Listing = listing_repository.get_by_id(command.listing_id)
2527

28+
check_rule(
29+
OnlyListingOwnerCanPublishListing(
30+
listing_seller_id=listing.seller_id, current_seller_id=command.seller_id
31+
)
32+
)
33+
2634
events = listing.publish()
2735

2836
listing_repository.persist_all()

src/modules/catalog/domain/rules.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,18 @@ def is_broken(self) -> bool:
5252
return self.status == ListingStatus.PUBLISHED
5353

5454

55+
class OnlyListingOwnerCanPublishListing(BusinessRule):
56+
__message = "Only listing owner can publish a listing"
57+
58+
listing_seller_id: ListingId
59+
current_seller_id: SellerId
60+
61+
def is_broken(self) -> bool:
62+
return self.listing_seller_id != self.current_seller_id
63+
64+
5565
class OnlyListingOwnerCanDeleteListing(BusinessRule):
56-
__message = "Only listing owner can delete listing"
66+
__message = "Only listing owner can delete a listing"
5767

5868
listing_seller_id: ListingId
5969
current_seller_id: SellerId

src/modules/catalog/tests/application/test_publish_listing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def test_publish_listing():
3030

3131
command = PublishListingDraftCommand(
3232
listing_id=listing.id,
33+
seller_id=seller.id,
3334
)
3435

3536
# act
@@ -62,6 +63,7 @@ def test_publish_listing_and_break_business_rule():
6263

6364
command = PublishListingDraftCommand(
6465
listing_id=listing.id,
66+
seller_id=seller.id,
6567
)
6668

6769
# act

0 commit comments

Comments
 (0)