Skip to content

Implement post likes functionality and update documentation#79

Open
edigar wants to merge 4 commits into
mainfrom
feature/post-likes
Open

Implement post likes functionality and update documentation#79
edigar wants to merge 4 commits into
mainfrom
feature/post-likes

Conversation

@edigar

@edigar edigar commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Description

Implements the README TODO: "Register who liked a post, so that each user can only like each post once, in addition to having information on who liked each post."

Likes were a denormalized counter on posts (likes int), incremented with UPDATE posts SET likes = likes + 1 — with no idea who liked and no deduplication (a user could like the same post repeatedly and inflate the count; the like/unlike handlers didn't even read the authenticated user). This PR replaces that counter with a normalized post_likes join table, so each user can like a post at most once, the count is always accurate, and we can list who liked a post.

Checklist

  • Tests has been changed.
  • All tests pass.
  • Documentation has been updated.
  • Code follows style guidelines.
  • All merge conflicts have been resolved.
  • The pull request is targeted to the correct branch.

Related Issue

Closes the "Register who liked a post…" item in the README TODO. No tracking issue.

Proposed Changes

  • Schema: new post_likes(post_id, user_id, created_at) join table mirroring followers — composite PRIMARY KEY (post_id, user_id) enforces one-like-per-user at the DB, FKs ON DELETE CASCADE. The posts.likes column is dropped. New goose migration + build/initdb.sql updated.
  • Entity: Post gains LikedByMe bool (json:"likedByMe"); Likes is now a derived value.
  • Repository: Like (INSERT ... ON CONFLICT DO NOTHING), Unlike, Exists, FetchLikers; read queries derive likes (COUNT subquery) and liked_by_me (EXISTS subquery) instead of reading a stored counter.
  • Usecase: LikePost/UnLikePost keyed by the authenticated user; GetLikers; new ErrPostNotFound; current user threaded into GetById/GetUserPosts.
  • Controller/routes: LikePost/UnlikePost now extract the token user (this fixes the previously commented-out auth on like), map a missing post to 404, and return 204; new GET /api/post/{postId}/likes; GetPost/GetUserPosts return likedByMe.
  • Docs: README TODO ticked off.

API contract

Method Path Auth Success Errors
POST /api/post/{postId}/like yes 204 400 invalid id · 401 no token · 404 post not found
POST /api/post/{postId}/unlike yes 204 400 invalid id · 401 no token
GET /api/post/{postId}/likes yes 200 []User 400 invalid id · 500

Post reads (GET /api/post, GET /api/post/{postId}, GET /api/user/{userId}/posts) now include the derived likes count and a per-user likedByMe flag. Like/unlike are idempotent (liking an already-liked post or unliking a not-liked post is a no-op → 204).

Tests Performed

Run on Go 1.25 (PowerShell):
go build ./... # ok
go vet ./... # ok
go test ./... # all packages PASS
Usecase and controller layers are covered with mocks (success paths, 401/403/404/400/204/200 mapping, ErrPostNotFound, likers listing, likedByMe). Consistent with the project's convention, the repository layer has no unit tests; its new SQL is verified by integration (bring up docker-compose, then like the same post twice → count stays 1; a second user → 2; GET .../likes lists both; unlike is idempotent; like a missing post → 404).

Additional Notes

  • Behavior change: posts.likes is dropped and its (unreliable) values discarded; the count is derived from post_likes. Like/unlike now require and use the authenticated user.
  • Follow-ups (out of scope): add the new GET /api/post/{postId}/likes row to the README Usage table; make usecase.GetById return the repository error instead of swallowing it; empty list reads serialize null rather than [] (pre-existing pattern).

@edigar edigar self-assigned this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant