Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 50 additions & 39 deletions db/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
erDiagram
Achievement {
timestamp_with_time_zone createdAt "{NOT_NULL}"
timestamp_with_time_zone deletedAt
text description
timestamp_with_time_zone deletedAt
text description
uuid id PK "{NOT_NULL}"
boolean isActive
boolean isActive
Tag leaderboard "<Patina,Hunter,Nyu,Baruch,Rpi,Gwc,Sbu,Ccny,Columbia,Cornell,Bmcc,MHCPlusPlus>"
uuid leaderboardId FK "{NOT_NULL}"
AchievementPlaceEnum place "<ONE,TWO,THREE> {NOT_NULL}"
character_varying title "{NOT_NULL}"
uuid userId FK "{NOT_NULL}"
Expand All @@ -19,7 +20,7 @@ erDiagram
timestamp_with_time_zone expiresAt "{NOT_NULL}"
uuid id PK "{NOT_NULL}"
text message "{NOT_NULL}"
boolean showTimer
boolean showTimer
}

ApiKey {
Expand All @@ -39,72 +40,72 @@ erDiagram

Auth {
timestamp_with_time_zone createdAt "{NOT_NULL}"
text csrf
text csrf
uuid id PK "{NOT_NULL}"
text token "{NOT_NULL}"
}

BackgroundTask {
timestamp_with_time_zone completedAt "{NOT_NULL}"
uuid id PK "{NOT_NULL}"
BackgroundTaskEnum task "<LEETCODE_QUESTION_BANK> {NOT_NULL}"
BackgroundTaskEnum task "<LEETCODE_QUESTION_BANK,USER_METRICS> {NOT_NULL}"
}

Club {
text description
text description
uuid id PK "{NOT_NULL}"
character_varying name "{NOT_NULL}"
character_varying password "{NOT_NULL}"
character_varying slug UK "{NOT_NULL}"
character_varying splashIconUrl
character_varying splashIconUrl
Tag tag "<Patina,Hunter,Nyu,Baruch,Rpi,Gwc,Sbu,Ccny,Columbia,Cornell,Bmcc,MHCPlusPlus> {NOT_NULL}"
}

DiscordClub {
timestamp_with_time_zone createdAt "{NOT_NULL}"
timestamp_with_time_zone deletedAt
text description
timestamp_with_time_zone deletedAt
text description
uuid id PK "{NOT_NULL}"
text name "{NOT_NULL}"
Tag tag "<Patina,Hunter,Nyu,Baruch,Rpi,Gwc,Sbu,Ccny,Columbia,Cornell,Bmcc,MHCPlusPlus> {NOT_NULL}"
}

DiscordClubMetadata {
uuid discordClubId FK "{NOT_NULL}"
text guildId
text guildId
uuid id PK "{NOT_NULL}"
text leaderboardChannelId
text leaderboardChannelId
}

Job {
integer attempts "{NOT_NULL}"
timestamp_with_time_zone completedAt
timestamp_with_time_zone completedAt
timestamp_with_time_zone createdAt "{NOT_NULL}"
uuid id PK "{NOT_NULL}"
timestamp_with_time_zone nextAttemptAt "{NOT_NULL}"
timestamp_with_time_zone processedAt
timestamp_with_time_zone processedAt
character_varying questionId "{NOT_NULL}"
JobStatus status "<COMPLETE,PROCESSING,INCOMPLETE> {NOT_NULL}"
}

Leaderboard {
timestamp_with_time_zone createdAt "{NOT_NULL}"
timestamp_with_time_zone deletedAt
timestamp_with_time_zone deletedAt
uuid id PK "{NOT_NULL}"
character_varying name "{NOT_NULL}"
timestamp_with_time_zone shouldExpireBy
text syntaxHighlightingLanguage
timestamp_with_time_zone shouldExpireBy
text syntaxHighlightingLanguage
}

Lobby {
timestamp_with_time_zone createdAt "{NOT_NULL}"
timestamp_with_time_zone expiresAt
timestamp_with_time_zone expiresAt
uuid id PK "{NOT_NULL}"
text joinCode "{NOT_NULL}"
integer playerCount "{NOT_NULL}"
LobbyStatusEnum status "<CLOSED,AVAILABLE,ACTIVE,COMPLETED> {NOT_NULL}"
boolean tie "{NOT_NULL}"
uuid winnerId FK
uuid winnerId FK
}

LobbyPlayer {
Expand All @@ -117,8 +118,8 @@ erDiagram
LobbyPlayerQuestion {
uuid id PK "{NOT_NULL}"
uuid lobbyPlayerId FK,UK "{NOT_NULL}"
integer points
uuid questionId FK,UK
integer points
uuid questionId FK,UK
}

LobbyQuestion {
Expand Down Expand Up @@ -147,28 +148,28 @@ erDiagram

Question {
double_precision acceptanceRate "{NOT_NULL}"
text code
text code
timestamp_with_time_zone createdAt "{NOT_NULL}"
text description
text description
uuid id PK "{NOT_NULL}"
text language
character_varying memory
integer pointsAwarded
text language
character_varying memory
integer pointsAwarded
question_difficulty questionDifficulty "<Easy,Medium,Hard> {NOT_NULL}"
text questionLink "{NOT_NULL}"
smallint questionNumber "{NOT_NULL}"
character_varying questionSlug "{NOT_NULL}"
text questionTitle "{NOT_NULL}"
character_varying runtime
text submissionId UK
character_varying runtime
text submissionId UK
timestamp_with_time_zone submittedAt "{NOT_NULL}"
uuid userId FK "{NOT_NULL}"
}

QuestionBank {
real acceptanceRate "{NOT_NULL}"
timestamp_with_time_zone createdAt "{NOT_NULL}"
text description
text description
uuid id PK "{NOT_NULL}"
question_difficulty questionDifficulty "<Easy,Medium,Hard> {NOT_NULL}"
text questionLink "{NOT_NULL}"
Expand All @@ -189,7 +190,7 @@ erDiagram
Report {
timestamp_with_time_zone createdAt "{NOT_NULL}"
text description "{NOT_NULL}"
character_varying email
character_varying email
uuid id PK "{NOT_NULL}"
character_varying title "{NOT_NULL}"
}
Expand All @@ -205,11 +206,19 @@ erDiagram
character_varying discordId UK "{NOT_NULL}"
character_varying discordName "{NOT_NULL}"
uuid id PK "{NOT_NULL}"
character_varying leetcodeUsername UK
character_varying nickname
character_varying profileUrl
character_varying schoolEmail
text verifyKey
character_varying leetcodeUsername UK
character_varying nickname
character_varying profileUrl
character_varying schoolEmail
text verifyKey
}

UserMetrics {
timestamp_with_time_zone createdAt "{NOT_NULL}"
timestamp_with_time_zone deletedAt
uuid id PK "{NOT_NULL}"
integer points "{NOT_NULL}"
uuid userId FK "{NOT_NULL}"
}

UserTag {
Expand All @@ -225,7 +234,7 @@ erDiagram
}

flyway_schema_history {
integer checksum
integer checksum
character_varying description "{NOT_NULL}"
integer execution_time "{NOT_NULL}"
character_varying installed_by "{NOT_NULL}"
Expand All @@ -234,9 +243,10 @@ erDiagram
character_varying script "{NOT_NULL}"
boolean success "{NOT_NULL}"
character_varying type "{NOT_NULL}"
character_varying version
character_varying version
}

Achievement }o--|| Leaderboard : "leaderboardId"
Achievement }o--|| User : "userId"
ApiKey }o--|| User : "updatedBy"
ApiKeyAccess }o--|| ApiKey : "apiKeyId"
Expand All @@ -254,6 +264,7 @@ erDiagram
QuestionTopic }o--|| Question : "questionId"
QuestionTopic }o--|| QuestionBank : "questionBankId"
Session }o--|| User : "userId"
UserMetrics }o--|| User : "userId"
UserTag }o--|| User : "userId"
```

Expand All @@ -264,12 +275,12 @@ erDiagram
</p>
<p align="center">
<i>
Also view in <a href="https://mermaid.live/edit#pako:eNrtWm1v2zgS_iuGP1NFk6abTbBYwHF0Ta5uksZOizsUMGiKlrimSC1f4qjd_PcdUpYtxZZst9kUB1zQpBY9M5x5ZjgzJPWtS2REu6ddqs4ZjhVOv4gO_PRIwug9TakwnW_FkPsxLKXa4DQbz5lJxu5x_FUK2iGKYkOjnul86X67uh6Nr-4Gg8cv3R1YI8qpZ63Q0gcD45oolhkmxeoba1nUgX837xsnmkjJKRYdpnvEsHu6-maE4w58FVE1kVhFIOG3G2yYwOjCCkMVusotOsPKkgTdZgy9mxM0nFjUJyJHfcltOmEYPihBOUdnKSHow0X_hlvtfn-vKlHB74ZjQkNh007mPrlZr69CNPp8jUYXt2H4e6ez2RCSYIUJ6DW-xypnIgYMDaeNhntsrKbqMur8azM-j18WWPaEkFaQF3EwfciYorqFdQev-pCACTSO6VbX60TORzC_emp1xt7TvGavE4v98AXWSefu_f72_XRomqTbLNqiWBEyBdlZvj1qPFA9QsAPVRSr4z7ScUHi0fzt3ef--DbsnY_P_jO-G4a3aBQOR-NPvcFdc-x7xQq_-GhGLY7ZAtFKe2uS54p1FzZEq-n-MWzkjIp2Rc8wmcUK1mc0wnq2m8oyzRZp9EdCqT6zd6VxKoAXB2E46l-fh-OPd-C-y-ur8Vnv6v1GBy4N6XM7WVtt35vX19OhwCndgzzDWs-lz_u7smhu47acsIEDkrxOLokUd4rXS4-B32cuOa3onzNNwNw1J_wP1HDP3OrenwzoB2owZE1cBdbbFa1omsvw0sTYMh5dRvtjU2lj-gkWYEwpZantv2XN7QzQianqYGNomhn9HXVulWOeJZp-pLQJAKFXWPI98Zop6QpU3ZT1xfynBXaI3cvmnAEoDw02Vnd08R8EZP_6w80gHIXo5va6Hw6Hl1fv0OVVOdoeY4NKf_ryi_b503Dj7NCjWR6FvgE6y5-Et86FwQ8XLE44_MLyjgdYxBZ6v6dwyckkf7EGdv91-odkog87rEaqcllC2cip6kPpbVbQG1tEmy_NlYgbXA_Dc9T71Lsc9M4GIer1R5efQlTG3Hljo1W2zIZt2VjMGWSZYmuxyQc3Xv-1dNgOkSfhjr09V3q6AqF2wiWaAHtDituk9sfFOv9u9W9WurV1qnX1ngiqJBsvZZO6mxT9ZzPwXi4qTTjDYrabo9x2dSj5PY2aQ38Jwaai-xLWr1LybkYZaTAfQhvwPHv1m-vRebPJ0prntjqSdsLpOFOUMO2iLbXcsIwzsG3P3nl38uazjSUQm6J_TVe39cwMFoTeAhJbdnCQmZ9vP_hDzS6v1bfNEKU0lSpvSie9OQQorfSS5WocR2w6ZQR8mC_HzldDUD5CrHP0gUbMpugCpDRWC69qKWPAxKzRKJ1izkGtJfUVdN57xU_JOGyLo5pCo9bjsfUZFGQccPLT3sNOUqZ1kYnLNNzeyjgOs8tJy24L_mMljVZjHcKQ7xzfPymY_x90zf4cyYyRFy5eayW56E_CB7Cb5x03mZw-pZKq2o2kVpvOBPZcUgTCcv6qc7nGwfTya9QxCTwab6yiU6rcQwcvWToTF9fl06tGlberW1d1oUqruvuqukoGNT0HlBpXPLxHi2MyL6M48ASXkhlynUqgDXgyRYr-QYkTGGjwNoRojGIqU2pUjohrfNwILDkWCwR70wmeMM5MHmARBa7LZ6AN0ShlgqU2DXQGW35gCUA6RSCOBnpOaYaEj_fAJBQKBVLSrYY4SLBOkKaxO-wvWCaMSGjnIfSjwG3rAVdhUCqFNFIwEhQWMFgZ2EiFAA5LkcIRewi0VAZNLJlRU3zWiTtJcbWJfcXORgRGO3ugJk8dA6xvmI1YpaggucdlgjUFRmAHnIMMG9APHhwXaDwDrTiYjDRnkTMA9h6RnCNtp04gVgqDGFf486BGDuDwQgUJpVDBuKYGxQpnCUrdJOVwijMUw7a1RCrKYRMLdgP27g4sdYpAR2GV83wFlwIIEKXYAxBAOr-XTK2cmlIV0wIWgHXChIPPec6Vapdq2L0DX0C2KRyhwMMyZV9pBMMmxXqGJhAxkUmCKVOAjaZYkWQBKehtSOKjB5ijHGixkwxoKjQBlxmYY-a-B2FALFhWAmKFi74pAFnOX0gu1DBzGfguAlYAWuALVeaJEtRyqhgWAWGKWGbQIpYq4pyiUsTgmE0BRiE-XUg5hRKKM8CbAT4Q6AWwEbtnEfVRD-wwppCL3WBqBSmY3BOEDweVFYM_MpNcxoxgXqD-p2VkpimHmUvFwGT6AGp4ZcvFVlBbMRNyLtorj1_ZjfVgmeRvaQYin_N-oVKC96hgNMWM_-CJzg69-JD6rLiTvdtvudZV2KG07dhN3en6uUR54oEjWOZ7aLQ42fVN4f5sV22HZN_lJL6oQc4-fwRX7VU3nNLBwnBkrTckSk4Zp7Wbiw0bO5IAhGE9znzE3kN6mObvab7BBe7A_sVan_J2oKjH__QFwXpENh0CLRH5TOmM5x8W99kvgsty7inP5zgfgxshV4yhAYIalW-6KgACSKY2bQ3vHZJUKQ_SMLF-c-DM2icZCICEcxqNJ_mOO576schKwA5qroiVa1T3WpQFGNtfULDFBfkeKTnP9kEMVqJebt1WN-CVt3oeZRD89VeRHU9BchG7pdTFmxJrROWrAnW6xRsBC-oFr6Mvb_BL8k03aAuu6m2lY61dpJX8T5mqtyWOqXZUVzIVdwRPTSnPs2tUi1PsUrpn9HKLA9Aa7fI0aifquuSlFuWh9gbajfIXYpaz3OzOv3x2zKv9UKtNtZOIKl-x12pyS0NQPZW-hazYLu-mfSvPFu3LVqZdq7KGNVN1UTdWLOqeGgW9bBc6XSiR8Nj1qfVLF_YaUH67PrixmjmWR-CBvdx_pUxLNiVtnHRPp5jDFmmx4Bav5i1JKLS0xV1R9_TgzVsvo3v6rfvQPQ1-ffv61dvD129Ojo6ODk5Ojg5RN--ensDgweuT48PXB8cHh8cHvzyi7lc_6-GrX4-P3xwcHRyfHP3y-u2RE1fMGkYMKsNSFWyNHOaCFFo8_g2cdDko"><code>mermaid.live</code></a>
Also view in <a href="https://mermaid.live/edit#pako:eNrtWntv2zgS_yqC_6aKptemabBYwHG0Ta7Oo7HT4hYBDFqiJa4pUstHHLWb775DyZIl25LlNJveAVc0bSzPDOfx4zxIfe_5IiC94x6RpxSHEsd33IE_fT-i5J7EhGvne_7I_tE0JkrjOJksqI4m9uPkm-DE8SXBmgR97dz1vl9ejSeXt8Ph412vA2tAGFmyrojJg4YvlC9poqngla-MoYEDf68_NS41FYIRzB2q-r6m96TCPcahA98FRE4FlgGI-OUaa8oxOjNcE4kuU4NOsDR-hG4Sij4ufDSaGjTweYoGgpl4SjH8IjlhDJ3Evo8uzgbXzCj782tVi0zRylrngfNbs84Vh18z7BOPm9hJ7G9Wx6tLD42_XqHx2Y3n_eo422X4EZbYBysm91imlIfgdM1I45qZhkYR2aza4x1fAoJzYbj_IoggDwmVRLWwdgBBBiFYQOGQ7ESKisRiDOtLZ93shH4iac1gKxdnj8-wipzbT_sb-NN90yTdJMEOxXLM5GQn6W7YZI7q-z4EourF6vMM6jgnybz5y8evg8mN1z-dnPxncjvybtDYG40nX_rD22bwZ4rlccngjFoCs8NFK-2Njp4L7BY2vpIzZ38UazEnvF3TE-zPQwk7NBhjNe-ms4iTMvM-HUv1lbNYaqsChHHoeePB1ak3-XwL8Tu_upyc9C8hMBDRyYU3vjkfjLaGs7RqwMx0Y-89uSxspkeOY7IHeYKVWoisanRlUcyEbSliCwckfRWd-4LfSrZWuTT8PHPFavX_KVU-2LsRhv-JLiDjbo3wT3bpBdEY8iiuujazK1jRtDcNmYmhocw2F_s7p9KcDCLMwZpSTKnvv0Ut9BT8E0KZxFqTONHqCbWvmnaeA1I_Uu84uKGfm_IU0CZS2Kq1Zsvmnv7TAD8A-Lw5dYCfRxproxyV_wegHFxdXA-9sYeub64G3mh0fvkRnV8WT9txNqw0uT9h6z5_Om5cHno3wwIv64ugI1nDuEq5xg9nNIwY_MAmD4eYhyZrCtc8JqbT9AVb27236x-C8gFMa41UxeaECpISOYCa3KxhZm2OuKxmV1A3vBp5p6j_pX8-7J8MPdQfjM-_eKjA3WljC1Z005rumDkWFJJNMXVsicJ1ZsBGXmz3UT5vWfb2pJnR5S5qJyzdCX5vyHTb1P683OxPVv96pVtbE7uuXl1SJeUsxWxReJuq_2wm3itIhQ0nmM-7hcoOsyPB7knQjP7SBdvq70tY3_VIoDBKC43ZCDqC55nkr6_Gp80mC6Of2-pAmCkjk0QSnyqLttgwTRNG7bi9Xyfdnbz55KN0xDb0b-hq59JEY-6TG_DEjvEuS87PNi3-WOfL6mVuu5diEgtZrZn1pNJfAEhJtbUstuQkoLMZ9SGQafnsdPUIyoiHVYouSEBNjM5ATGPVyLQtZAwpnzfapWLMGOhVUl9CJ74XiArGURuYagqNW0_QNleQkHZoTDbaEDONqVJ5Qi6zcXtfY1l0l9OYbvv-cyWbViEPYGSdYf6zIP1_3DUHdCwS6r9wEdsozXmn4j2A3Sx17GJitk4lZLUtiY3SzhRmMMFdbhh75ZxvcFBVfo0cHcFHnRkryYxI-8HBJYsztcAuPr1qVHm3unVVl6q0qruvqqt0UNNzSIi2RSSLaH6UlsnIT0UhpP4c2Y7FVRoiGSNJ_iC-FegqiDZANEQhETHRMkW-bYDsE9hzNOQIZtUpnlJGdepiHri24aegja9QTDmNTeyqBHMOLC5IJwjEEVctCEkQz_Du6ohAtUBS2N0QuhFWEVIktFcCOcuU-gI6e4B-4No5H_zKNYoFF1pw6ru5BRR2BtZCInCHIUjigD64SkiNpsafE53_riJ7uGILFP2GrY0IjLb2QG2eWQbY37Cab6Qk3E8zv0yxIsAI7OBnN8Ea9IMPlgs0noNWDExGitHAGgBjSCAWSJmZFYilxCDGNgCpWyMH57BcBQHlUMJzRTQKJU4iFNtFiscxTlAIQ2zhqSCFkRbsBt_bq7XYKgKdhZE28hW_5I4AUZI-AAHk83tB5SqoMZEhyd0Cbp1Sbt1nI2fLtU019N46n0O2yQMhIcIipt9IAI91jNUcTQExgY7cGZXgG0Ww9KOlS0Fv7UcZeoA5SIEWW8ngTYmmEDINa8zt9yAMiDlNCocYbtE3A0cW6-eSczX0QrhZJwE7AC39C2VmTQliGJEUc9en0jdUoyWWKuKsooKHEJhtACOATwspq1BEcAL-puAfAHru2IDe04BkqAd2eCaRxa47M9zPmewngA8DlSWFf0QimAipj1nu9T8N9eeKMFi5UAxMJg-gRqZssdlyasPnXCx4e-XJdnZjPSiT_A1JQORzXkLUanDnCkZiTNmPHvB0aMpHJEuLnQzefRe2qUKH2taxn7pV9SOK4vQDB7DP99Boedq77Av3ZbtsOzN7UpDYsghZ-7ITuVq7uuXUDrZGfnLXdnUixYwyUr_S2DLk-RF40VvDWgbbe8gRs9Rexm6JA4zyNh_-l550djhIegr47PXFi3V9xV1J3or809clm-5oOgkrPfKVkDlLL5YX_i_il3LtGUsXOJ0AeiFNTqD303aq3nJtAgRQR6Cva93ZHRJ0IRBKkG-ywSifOrvnQQ4-YYwEk2nacSPUj4ZWAjqouSKWtknfKx_lztj9CofJ3yDYoxqlyT4egwSkVnPr6h2ByptSj8J1__qrdvdyDCvUTvyKRbbwZRXFMuSoLynzd1A2iIqXMOp0y3ctltRLXktfvBtRkG-7iVxyVe99LWvtQrLgX2fqZHV-ybJuSnEfUKNaXgIU0jPGTG5-elyjLY_yOlHXJZdaFHcCW2i3yl-KKVe57s5ffrbMqyGy1aba-U2VLx9Qm8LSAKp16TvI8jOGbtq38uzQvmj_2rWqlvzdlLZ0NVP1UC-UNOgdawmjQg8GCeg-4GMvS993PRjlYnLXs0ww4pkHN8ByDnMEE9KyPwI_jM2_CxEXIqQwYdQ7nmEG0-hymy5friyfwswaLK_oesfv3rzPhPSOv_ceesdHB69eH3x4d_ivd4eHhwevj96iXto7Pnj_7tXBwdH7g7cfDg4PX797e_iIet-yZV-_Ojo6enN0ePD-w9Gbt2_h98e_Aa8Xti4"><code>mermaid.live</code></a>
</i>
</p>
<p align="center">
<i>
Last updated: 02/15/2026
Last updated: 09/26/2026
</i>
</p>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- check only applies to new rows not being null, not old rows

ALTER TABLE IF EXISTS "User"
ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;

ALTER TABLE IF EXISTS "User"
ALTER COLUMN "createdAt" SET DEFAULT NOW();

ALTER TABLE IF EXISTS "User"
ADD CONSTRAINT "ck_user_createdAt_not_null" CHECK ("createdAt" IS NOT NULL) NOT VALID;

ALTER TABLE IF EXISTS "Session"
ADD COLUMN "createdAt" TIMESTAMP WITH TIME ZONE;

ALTER TABLE IF EXISTS "Session"
ALTER COLUMN "createdAt" SET DEFAULT NOW();

ALTER TABLE IF EXISTS "Session"
ADD CONSTRAINT "ck_session_createdAt_not_null" CHECK ("createdAt" IS NOT NULL) NOT VALID;
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package org.patinanetwork.codebloom.common.db.models;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.Optional;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.patinanetwork.codebloom.common.db.helper.annotations.NotNullColumn;
import org.patinanetwork.codebloom.common.db.helper.annotations.NullColumn;

@Getter
@Setter
Expand All @@ -25,6 +27,10 @@ public class Session {
@NotNullColumn
private LocalDateTime expiresAt;

/** can be null if it's an old entry */
@NullColumn
private OffsetDateTime createdAt;

// public Session(final String userId, final LocalDateTime expiresAt) {
// this.userId = userId;
// this.expiresAt = expiresAt;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.patinanetwork.codebloom.common.db.models.user;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import lombok.Builder;
Expand Down Expand Up @@ -50,6 +51,10 @@ public class User {
@NullColumn
private String schoolEmail;

/** can be null if it's an old entry */
@NullColumn
private OffsetDateTime createdAt;

/**
* If you want to update tags in the database, you have to use the
* {@link org.patinanetwork.codebloom.common.db.repos.usertag.UserTagRepository}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.patinanetwork.codebloom.common.db.repos.session;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.patinanetwork.codebloom.common.db.models.Session;
import org.patinanetwork.codebloom.common.time.StandardizedOffsetDateTime;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Component;
Expand All @@ -15,6 +18,7 @@ public class SessionSqlRepository implements SessionRepository {
.id(Optional.of(rs.getString("id")))
.userId(rs.getString("userId"))
.expiresAt(rs.getTimestamp("expiresAt").toLocalDateTime())
.createdAt(StandardizedOffsetDateTime.normalize(rs.getObject("createdAt", OffsetDateTime.class)))
.build();

private JdbcClient jdbcClient;
Expand All @@ -25,7 +29,8 @@ public SessionSqlRepository(final JdbcClient jdbcClient) {

@Override
public void createSession(final Session session) {
String sql = "INSERT INTO \"Session\" (id, \"userId\", \"expiresAt\") VALUES (?, ?, ?) RETURNING \"id\"";
String sql =
"INSERT INTO \"Session\" (id, \"userId\", \"expiresAt\") VALUES (?, ?, ?) RETURNING \"id\", \"createdAt\"";
// Don't want dashes inside of the cookie, so better to just remove it from the
// ID altogether.
session.setId(Optional.of(UUID.randomUUID().toString().replace("-", "")));
Expand All @@ -39,21 +44,24 @@ public void createSession(final Session session) {
() -> new IllegalStateException("Session ID must be present for insertion.")))
.param(2, UUID.fromString(session.getUserId()))
.param(3, session.getExpiresAt())
.query((rs, rowNum) -> rs.getString("id"))
.query((rs, rowNum) -> Map.entry(rs.getString("id"), rs.getObject("createdAt", OffsetDateTime.class)))
.optional()
.ifPresent(id -> session.setId(Optional.of(id)));
.ifPresent(entry -> {
session.setId(Optional.of(entry.getKey()));
session.setCreatedAt(StandardizedOffsetDateTime.normalize(entry.getValue()));
});
}

@Override
public Optional<Session> getSessionById(final String id) {
String sql = "SELECT id, \"userId\", \"expiresAt\" FROM \"Session\" WHERE id=?";
String sql = "SELECT id, \"userId\", \"expiresAt\", \"createdAt\" FROM \"Session\" WHERE id=?";

return jdbcClient.sql(sql).param(1, id).query(SESSION_ROW_MAPPER).optional();
}

@Override
public ArrayList<Session> getSessionsByUserId(final String id) {
String sql = "SELECT id, \"userId\", \"expiresAt\" FROM \"Session\" WHERE \"userId\"=?";
String sql = "SELECT id, \"userId\", \"expiresAt\", \"createdAt\" FROM \"Session\" WHERE \"userId\"=?";

return new ArrayList<>(jdbcClient
.sql(sql)
Expand Down
Loading
Loading