5.2 KiB
5.2 KiB
QA procedure: roles_permissions_foundation
Package: test (black-box). Name new fakes uniquely, for example mockRoleRepo, rolesFoundationUserRepo.
Do not copy the old Role == checks into new code.
Deferred to later slices
- 2a: permission-based route and middleware checks, API keys on the creator's live role, admin relaxations, 403 missing_permission, Writer effective.
- 2b: own/all enforcement after loading the item, publish separate from update, Draft and "Ask an editor to publish."
- 3: /v1/role CRUD, reassign, no-escalation, role_locked, role_has_members, role_name_taken, role_conflict, per-type content override keys
content.<action>:<type_key>, role events. - 4: PUT /v1/user/{id}/role, invite role (default Writer), transfer ownership, protected owner, removal of the legacy role string.
- 5-7: all SPA states in docs/design/screens/roles.md.
Design note for the user
The "Owner-only items" state in docs/design/screens/roles.md disables View roles and Manage roles for an admin. This slice follows the user's decision that Admin keeps roles.view and roles.manage (29 of 34 keys), matching the catalogue table. roles.md needs a design fix by the user; no stage edits docs/design.
Test infrastructure needed first
mockRoleRepoimplementing the role domainRepositoryin memory. Seed it with the three built-ins through the same Go function the migration uses, or assert it matches the Background tables.- Extend the user fake with
RoleID, and the article fake withCreatedBy. - The persistence tests use an in-memory SQLite DSN (as
TestBackfillUserRolesintest/user_roles_test.go), never a file. Registermodels.Role,models.RolePermission,models.User,models.Articleandmodels.Entryviadatabase.Migratewhere the whole sequence is asserted, and via targeted AutoMigrate for single-backfill tests.
A. Domain (pure Go, no HTTP, no GORM)
- Table-test
Role.Allowswith the Examples of "Role.Allows evaluates scope and ownership", plus the absent-key and unknown-key cases. Asserterrors.Is(err, role.ErrUnknownPermission)for the lookup. - Catalogue test: length 34, group order, key order, the 5 owner-only keys, the 9 scoped keys, and
per_typeonly for the 5 content keys. A unique-keys check guards against duplicates. - A hygiene test that
internal/domain/roleimports only the stdlib (grep the import list, as in the existing*_hygiene_test.gofiles).
B. Persistence (in-memory SQLite)
- Seed on an empty DB: assert 3 roles, flags, versions, and the 34 / 29 / 9 grant counts and scopes. Run again: still 3 roles with the same ids and 72 role_permission rows.
- Edited built-in: bump Writer's
versionto 4 and addmedia.delete=own, seed again, assert untouched. - Name collision: pre-insert a custom "Writer" (built_in false), seed, assert no error and the row is unchanged.
BackfillUserRoleIDs: cases for owner/admin mapping, the legacy string unchanged, an existingrole_idkept, double run, empty DB.- Full
database.Migrateon a DB created with the old schema (users.role = "", norole_id): assert ordering (legacy role first, then role_id). BackfillCreatedBy: articles and entries with 0, entries with an existing value, double run, no owner.- Portability: assert there is no raw SQL specific to SQLite in the new repositories (code review item); MySQL and PostgreSQL are not exercised here.
C. Use cases (fakes only)
GetMyAccessUseCase: owner, admin, writer, custom role, legacy fallback (role_id 0 with "owner" and "admin"), live change after a grant edit, unresolvable role (expect a non-sentinel error).ListPermissionsUseCase: returns the domain catalogue unchanged.CreateArticleUseCasesetsCreatedByto the acting user id.
D. HTTP (httptest, fresh chi.NewRouter() mirroring api/router.go)
- Call
validator.InitValidator(). Use the token helper the current/metests use. Mint cookies asget_current_user.qa.mdstep 7 does. - Mount
/v1/auth/meas inNewAuthRouter(Verifier, apiKeyAuth, Authenticator, RequireCurrentToken) withauth.NewMeHandler(getUser, getMyAuthor, getMyAccess). Re-run allget_current_usercases unchanged (additive field) and add the access cases: owner, admin, writer, custom, fallback, live change, unverified, unresolvable role (500). - Mount
/v1/permissionas in the newNewPermissionRouter(adds RequireVerifiedUser). Cases: Writer 200 with the full shape, Owner and Writer bodies equal, API key 200, no cookie 401, stale token 401, unverified 403. - "Unchanged behaviour" Outline: build the existing
NewUserRouter,NewSettingsRouter,NewContentTypeRouterandNewSystemRoutergroups over users carrying role_id, and assert the statuses are as before. The simplest source is the existing router tests; add a seeded-role_id variant.
Manual verification
- Start a dev build (
task dev:api) on a copy of a database created before this change. Check that the startup migration succeeds, that no data is lost, and thatGET /v1/auth/meandGET /v1/permissionrespond for the existing owner and admin. - MySQL and PostgreSQL migration of the new tables is a manual item; the repo has no CI and no automated run for it.
- The SPA is untouched in this slice. SPA states in docs/design/screens/roles.md are informational.