To make it easier to review, I create a script at src/scripts/member-jwt.js to generate JWT.
You need to make sure:
secretequals to configAUTH_SECRETissis in configVALID_ISSUERSexpis a timestamp is after current time so this token is not expired
After that, you can change the payload by yourself.
For example, you want to udpate member profile as user "Ghostar", you need to
- query Ghostar's user id in db
- update jwt payload userId field
- generate new jwt with this script
Sometimes the application will check authUser.userId === member.userId.
You can setup seed data to test these features. Here are some useful tips.
In this endpoint, user may update email.
If user updates email, following things will happen:
- member table
newEmail,emailVerifyToken,emailVerifyTokenDatenewEmailVerifyToken,newEmailVerifyTokenDatewill be updated- tokens are new uuid and used in verifyEmail endpoint.
- Use GET /members//verify?token= to verify token.
- user need to verify both email and new email
- after both emails are verified, user's email value will be updated to new email
There are a lot of S3 operations in this endpoint that are not updated.
To make it all working, it will take you much time and efforts.
To test this endpoint, you can comment them all and directly set photoUrl to db.
That is the only thing I update in this challenge.
All endpoints are simple CRUD. You should be able to check them by yourself.
Just be careful about the schemas used for different kind of trait.
There are some changes to prisma schema.
- Add memberTraits.hobby
- Update memberSkill.displayMode to optional
- Remove displayMode.memberSkills @ignore
- Add stats fields as discussed in forum
- Required env vars:
DATABASE_URLfor the member databaseCHALLENGES_DB_URLfor the challenges databaseREVIEW_DB_URLfor the review database;recalculateMemberStats.jsnow reads review-apichallengeResultrows during aggregate backfill and history supplementation, not just during rerates
- Challenge catalog prerequisite:
- Deploy the
challenge-api-v6migration that seeds hidden legacyChallengeTyperows for historical subtracks likeARCHITECTURE,ASSEMBLY_COMPETITION, andSRM
- Deploy the
- Optional toggle:
STATS_READ_SOURCE=legacykeeps reads on legacy stats tables during backfill and parity validationSTATS_READ_SOURCE=unifiedswitches reads to the new unified stats tables
Run node src/scripts/verifyStatsMigration.js --samples 50 and review the output fields. Values above 50 are clamped by the script, so rerun --samples 50 for additional random-user coverage:
- Table availability map: confirms whether each legacy and unified table needed for comparison is reachable
- Row counts per table: confirms expected population levels before cutover
- Sampled violation breakdown:
track-summaryrating-mismatchhistory-counthistory-orderrank-completeness
mostRecentviolation groups: reports(trackId, typeId)groups where thememberStatsHistorydata does not have exactly onemostRecent: truerow- Legacy subtype resolution: the script should no longer emit
Skipping legacy ... subTrack ...warnings for challenge types that now exist inchallenge-api-v6as hidden legacy records
Use the violation categories to guide investigation:
track-summary: compare legacy and unified aggregate counts for the sampled member, track, and typerating-mismatch: compare legacy rating values againstmemberStatsand the correspondingmemberStatsHistorymost-recent rowhistory-count: compare the number of legacy history rows to the migratedmemberStatsHistoryrowshistory-order: inspect chronological ordering and verify the history is sorted correctlyrank-completeness: verify rated members have rank fields populated in unified statsmostRecentviolation groups: inspect grouped history rows for duplicate or missingmostRecent: trueflags
GET /members/:handle/stats- Verify
develop,design, anddataSciencesub-objects are present - Verify
rating,maxRating,volatility, andrankfields are non-null for rated members
- Verify
GET /members/:handle/stats/history- Verify the
historyarray is ordered bydatedescending - Verify exactly one entry per
(trackId, typeId)hasmostRecent: true
- Verify the
GET /members/stats/distribution- Verify the response shape is unchanged
POST /members/:handle/stats/refresh- Requires
refresh:member_statsscope or admin JWT - Body:
{ "challengeId": "<uuid>" }(optional) - Verify a 200 response with a summary object
- Requires
POST /members/:handle/stats/rerate- Requires
rerate:member_statsscope or admin JWT - Body:
{ "challengeId": "<uuid>", "trackId": "DEVELOP", "typeId": "Challenge" } challengeIdis required; use the earliest applicable challenge when you need a full-history rerate for a track/type- Use
DEVELOPorDATA_SCIENCEfortrackId, andChallengeorMARATHON_MATCHfortypeId; these are enum names, not DB UUIDs - Verify a 200 response
- Verify
memberStatsHistoryrows are updated for the member
- Requires
- For a known Development track rated member:
- Verify
ratinginmemberStatsmatches the expected value - Verify
memberStatsHistorycontains a row withmostRecent: trueand matchingnewRating
- Verify
- For a known Marathon Match rated member:
- Verify
ratinginmemberStatsmatches the expected value for the DATA_SCIENCE / MARATHON_MATCH track - Verify
memberStatsHistorycontains a row withmostRecent: trueand matchingnewRating
- Verify
- For a member with unrated challenges:
- Verify those challenges are absent from
memberStatsHistoryrating rows
- Verify those challenges are absent from
- Run a known report from
reports-api-v6that reads member stats and verify rating fields are non-null - Compare the output against a legacy baseline captured before cutover