Add tests, and fix the authorization, credential and concurrency defects they found - #1
Merged
Merged
Conversation
Every rule sat on a single line beginning with ##, so git read the whole file as one comment and ignored nothing. Rewritten with real newlines, plus entries for test results and coverage output.
AdminController carried no [Authorize] attribute, so every action on the management area answered anonymous requests -- including KursSil and EgitmenSil, which delete rows and cascade. It now requires the Admin role. Administrator credentials were compared against string literals in the login action, so the working password shipped with the source. Administrators are now rows in Yoneticiler, seeded from configuration; development generates a random password and logs it once, production refuses to seed without one. Student passwords were stored and compared in clear text. They are now PBKDF2-HMAC-SHA256 with a per-password salt and a fixed-time comparison, with the iteration count embedded in the stored hash so it can be raised later. Cancelling an application took an id and deleted it with no ownership check, letting any signed-in student cancel anyone else's place. Cancellation now compares the owner against the caller's NameIdentifier claim. Capacity was checked by counting applications, comparing against Kontenjan, and then inserting -- concurrent requests could all read the same count. A Kurs.KayitliSayisi counter is now claimed with a conditional UPDATE, so the check and the write are one statement; measured against the old logic, 15 concurrent applications to a capacity-5 course enrolled all 15. Also: identity is read from the NameIdentifier claim instead of the display name, antiforgery validation is global rather than per-action, returnUrl is restricted to local URLs, logout is a POST, registration binds to a view model instead of the entity, and uniqueness checks run in SQL rather than after pulling the table into memory.
62 tests. Each creates its own SQLite file and runs the real migrations against it; the in-memory provider supports neither transactions nor ExecuteUpdate, which are the mechanisms the capacity fix depends on. AuthorizationIntegrationTests hosts the application through WebApplicationFactory so routing, model binding, cookie authentication, authorization and the antiforgery filter all run. A missing [Authorize] attribute fails these; calling a controller method directly would not. EnrollmentServiceTests includes a 15-way concurrent enrolment against a capacity-5 course. The harness was verified by reproducing the original count-then-insert logic under it, which enrolled all 15.
CI builds in Release, runs the tests and collects coverage. A second job fails the build on any package with a known advisory, including transitive ones -- the vulnerable SQLite native bundle in this project arrived through EF Core rather than through a direct reference. README documents what the tests found and how capacity is enforced now, rather than restating the feature list.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a test suite to the project, and fixes what it found.
What the tests found
AdminControllerhad no[Authorize]POST /Admin/KursSildeleted a course and cascaded to its applications with no session.kullaniciAdi == "admin" && sifre == "1234"in the login action — the working password was published with the source.o.Sifre == sifre. Reading the database was reading every password.The capacity bug, measured
The original logic was reproduced under the new test harness: 15 concurrent applications to a capacity-5 course enrolled all 15. Capacity is now claimed with a conditional
UPDATE ... WHERE KayitliSayisi < Kontenjan, so the check and the write are a single statement. Same test, same load: exactly 5.Also in this PR
.gitignorehad no line endings — the whole file parsed as one comment, so nothing was ignored.returnUrlrestricted to local URLs..ToList().Any(...)over the whole table.(KursId, OgrenciId); instructor deletes areRestrict.Upgrading
The migration drops the clear-text
Sifrecolumn. A hash cannot be derived from it, so existing student accounts must be created again.🤖 Generated with Claude Code