Commit graph

77 commits

Author SHA1 Message Date
a8f59afc30
implement ClearFeaturedPost use case 2026-05-06 22:30:17 +03:00
7bd3ff78b4
test ClearFeaturedPost use case 2026-05-06 22:29:54 +03:00
ee95bcafc9
implement SetFeaturedPost use case 2026-05-06 22:29:34 +03:00
13ca655f9b
test SetFeaturedPost use case 2026-05-06 22:29:09 +03:00
f73e5a1af5
extend Post entity with feature slot
Adds nullable feature_slot column (unique) plus repo
findByFeatureSlot/findFeatured/update methods so admins can
pin a post into one of two slots.
2026-05-06 22:28:45 +03:00
64a334c63e
test Post entity feature slot 2026-05-06 22:27:18 +03:00
ec4f729c63
merge post-comment-controllers 2026-05-06 22:26:40 +03:00
59d4ed88c4
implement post and comment controllers
Wires PostController (recent, show, create, delete, listByUser)
and CommentController (listForPost, create, delete) to the
existing use cases. Posts and comments expose author display
names alongside user IDs. CommentRepository binding added to
RepositoryServiceProvider.
2026-05-06 22:26:35 +03:00
8614858558
test post and comment controllers
Adds AuthenticatesUsers feature trait that runs the full
signup -> confirm -> login flow and exposes the resulting auth
cookie. Bumps phpunit defaultTimeLimit to 30 seconds so the
multi-bcrypt-per-test feature flow finishes inside the limit.
2026-05-06 22:26:10 +03:00
fa63005db7
merge comment-domain 2026-05-06 22:16:43 +03:00
d24bde3761
implement DeleteComment use case 2026-05-06 22:16:34 +03:00
5bbef871db
test DeleteComment use case 2026-05-06 22:16:10 +03:00
a59fc4890f
implement ListCommentsForPost use case
Renames seed() helper to seedComment() to avoid clashing with
Illuminate\Foundation\Testing\TestCase::seed().
2026-05-06 22:15:49 +03:00
f9e2529994
test ListCommentsForPost use case 2026-05-06 22:15:10 +03:00
e8d2ff3fdf
implement CreateComment use case 2026-05-06 22:14:55 +03:00
2557c9b6a9
test CreateComment use case 2026-05-06 22:14:31 +03:00
93da08756c
add Comment persistence: model, migration, eloquent + fake repo 2026-05-06 22:14:11 +03:00
0d589340d9
add Comment entity, dto, repository interface 2026-05-06 22:13:37 +03:00
015e61caf7
merge auth-controller-and-routes 2026-05-06 22:12:56 +03:00
9049f1581b
implement auth controller and routes
Wires AuthController (signup, confirmEmail, login, me, logout)
to the existing auth use cases. Routes mounted under /api with
AuthMiddleware on logout/me. RepositoryServiceProvider gains
EmailConfirmationToken and Post bindings; AppServiceProvider
binds the Emailer/EmailFactory and constructs SignupUser with
the configured from-address.
2026-05-06 22:12:51 +03:00
0ffc4b546c
test auth controller signup, confirm-email, login, me, logout 2026-05-06 22:12:27 +03:00
99433a21c2
merge signup-flow-rewrite 2026-05-06 22:08:58 +03:00
f3c6e2e000
implement SignupUser two-step confirm flow
Signup now collects only email + displayName, creates an
unconfirmed user with empty password hash, mints an
EmailConfirmationToken, and dispatches a confirmation email.
Password is set during ConfirmUserEmail.
2026-05-06 22:08:54 +03:00
11f2823a30
test SignupUser two-step confirm flow 2026-05-06 22:08:25 +03:00
edb0bc0478
merge email-confirmation-domain 2026-05-06 22:07:38 +03:00
6823bdeb50
implement ConfirmUserEmail use case 2026-05-06 22:07:30 +03:00
60308988f7
test ConfirmUserEmail use case 2026-05-06 22:07:08 +03:00
2890781a56
add Emailer and EmailFactory interfaces with laravel + fake impls 2026-05-06 22:06:30 +03:00
e16cb45387
add EmailConfirmationToken persistence: model, migration, eloquent + fake repo 2026-05-06 22:05:52 +03:00
9747d07c31
test EmailConfirmationToken entity 2026-05-06 22:04:57 +03:00
03a1f02843
merge extend-user-entity 2026-05-06 22:03:56 +03:00
4b1689d17e
implement SignupUser displayname requirement 2026-05-06 22:03:49 +03:00
4829a02aac
test SignupUser displayname requirement
Adds displayname to existing assertions and new tests covering:
null/short/invalid-charset displayname, duplicate displayname,
findability by displayname. AuthenticateUser tests pick up the
seedUser displayname argument.
2026-05-06 22:03:40 +03:00
298b8634ec
extend User entity with displayname and email confirmation
Add display_name (unique) and email_confirmed_at columns plus
matching getters, DTO fields, repo methods (findByDisplayName,
update), and migration. Existing auth tests updated to construct
User with the new params.
2026-05-06 22:03:19 +03:00
d547ec2c61
test User entity displayname and email confirmation 2026-05-06 22:00:22 +03:00
eecda40273
merge post-domain 2026-05-06 21:58:29 +03:00
e9ac16377f
implement DeletePost use case 2026-05-06 21:58:25 +03:00
yisroel
fd91da6bab
test DeletePost use case
7 cases: zero postId or requesterId -> BadRequest; unknown post
is idempotent no-op; author can delete own post; admin can
delete anyone's post; non-author non-admin -> ForbiddenException;
forbidden attempts leave post intact.
2026-05-06 15:26:28 +03:00
yisroel
7fda18dde3
implement GetPost use case
validates id > 0, delegates to PostRepository->find. 58 tests
pass.
2026-05-06 15:25:56 +03:00
yisroel
eb0ebc6f63
test GetPost use case
4 cases: zero/negative id -> BadRequest; unknown id -> null
(controller maps to 404); existing id returns the Post.
GetPost takes int id directly (no Request object - the value is
trivial and controllers pull it from a route param).
2026-05-06 15:25:36 +03:00
yisroel
32cbf4229c
implement ListUserPosts use case
validates userId > 0, delegates to PostRepository->findByUserId.
54 tests pass.
2026-05-06 15:25:07 +03:00
yisroel
e97ca28237
test ListUserPosts use case
5 cases: zero/negative userId -> BadRequest; user with no posts
-> []; returns only requested user's posts (filters out other
authors); ordered newest-first by createdAt. fails red.
2026-05-06 15:24:41 +03:00
yisroel
7ec46aa8f9
implement ListRecentPosts use case
validates limit > 0 (zero or negative -> BadRequest), then
delegates to PostRepository->findRecent. 49 tests pass.
2026-05-06 15:24:15 +03:00
yisroel
e9779d8459
test ListRecentPosts use case
5 cases: zero/negative limit -> BadRequest; empty repo -> [];
returns posts ordered newest-first; respects limit truncation.
fails red - ListRecentPosts class missing.
2026-05-06 15:23:53 +03:00
yisroel
4a4e046de4
implement CreatePost use case
trims title and body, rejects empty (post-trim) values with
BadRequest. supplies createdAt from injected Clock. persists
through PostRepository->create and returns the resulting Post.
44 tests pass.
2026-05-06 15:23:21 +03:00
yisroel
504554bf7f
test CreatePost use case
7 cases: null + whitespace title -> BadRequest; null +
whitespace body -> BadRequest; valid request returns Post with
correct userId/title/body and createdAt = clock.now(); the post
is findable via the repo afterwards; title and body get trimmed
of leading/trailing whitespace. fails red - CreatePost class
absent.
2026-05-06 15:22:57 +03:00
yisroel
e3dddc60aa
add Post persistence: model, migration, eloquent + fake repo
PostModel maps posts table (id, user_id fk, title, body text,
created_at indexed). EloquentPostRepository: create, find,
findByUserId (desc by created_at), findRecent (limit, desc),
delete - chain via ::query() to keep larastan happy.
FakePostRepository sorts on read (defensive copy each return).
cascade-on-delete on user_id so removing a user nukes their
posts.

phpstan.neon suppresses staticMethod.dynamicCall under
app/*/Eloquent*Repository.php - phpstan-strict-rules flags
Eloquent's fluent builder idiom (Model::query()->orderBy())
because the static methods become instance calls mid-chain.
suppression scoped to repo files only so the rule still
applies elsewhere.
2026-05-06 15:22:22 +03:00
yisroel
73a3acd39f
add Post entity, dto, repository interface
Post: id, userId (fk -> User), title, body, createdAt as
DateTimeImmutable. CreatePostDto readonly with explicit
createdAt (use case supplies it via Clock; entity remains pure).
PostRepository: create, find, findByUserId, findRecent (limit),
delete.
2026-05-06 15:19:00 +03:00
Yisroel Baum
9ca58f3a9d
merge user-and-auth-domains
phase 2: User + Auth foundations.

User domain: entity (id, email, passwordHash, isAdmin), dto,
repository interface, eloquent + fake impls, users migration,
SignupUser use case (validates email, length, uniqueness; hashes
password; isAdmin always false on signup).

Auth domain: Clock + TokenGenerator + PasswordHasher utility
interfaces with system + bcrypt + random impls and matching
fakes. Session entity + dto + repository interface, eloquent +
fake impls, sessions migration (token primary, fk user_id
cascade, expires_at indexed). AuthenticateUser, CreateSession,
Logout use cases. AuthMiddleware reads auth_token cookie and
attaches User to request attributes.

bindings wired in AppServiceProvider + new
RepositoryServiceProvider.

37 tests, 59 assertions; stan + cs clean.
2026-05-06 15:18:23 +03:00
yisroel
2e3265e568
wire repository and utility bindings
AppServiceProvider binds Clock -> SystemClock, TokenGenerator ->
RandomTokenGenerator, PasswordHasher -> BcryptPasswordHasher.
new RepositoryServiceProvider binds UserRepository ->
EloquentUserRepository, SessionRepository ->
EloquentSessionRepository. bootstrap/providers.php registers
both. verified container resolves: app(Clock::class) returns
SystemClock. migrations create users + sessions tables with
proper unique/foreign-key/index constraints (sqlite roundtrip
confirmed).
2026-05-06 15:18:06 +03:00