aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/dev/roadmap.md2
-rw-r--r--src/server/repositories/sync.ts9
2 files changed, 6 insertions, 5 deletions
diff --git a/docs/dev/roadmap.md b/docs/dev/roadmap.md
index d877d78..ed45ea6 100644
--- a/docs/dev/roadmap.md
+++ b/docs/dev/roadmap.md
@@ -197,7 +197,7 @@ Smaller features first to enable early MVP validation.
- [x] Configure CORS middleware
### Medium Priority
-- [ ] Fix card update authorization in sync push (verify existing card ownership)
+- [x] Fix card update authorization in sync push (verify existing card ownership)
- [ ] Unify password length requirement (add-user.ts: 8 chars → 15 chars)
### Low Priority
diff --git a/src/server/repositories/sync.ts b/src/server/repositories/sync.ts
index a1b6648..3e9f8ed 100644
--- a/src/server/repositories/sync.ts
+++ b/src/server/repositories/sync.ts
@@ -171,18 +171,18 @@ export const syncRepository: SyncRepository = {
for (const cardData of data.cards) {
const clientUpdatedAt = new Date(cardData.updatedAt);
- // Verify deck belongs to user
+ // Verify target deck belongs to user
const deckCheck = await db
.select({ id: decks.id })
.from(decks)
.where(and(eq(decks.id, cardData.deckId), eq(decks.userId, userId)));
if (deckCheck.length === 0) {
- // Deck doesn't belong to user, skip
+ // Target deck doesn't belong to user, skip
continue;
}
- // Check if card exists
+ // Check if card exists AND belongs to user (via deck ownership)
const existing = await db
.select({
id: cards.id,
@@ -190,7 +190,8 @@ export const syncRepository: SyncRepository = {
syncVersion: cards.syncVersion,
})
.from(cards)
- .where(eq(cards.id, cardData.id));
+ .innerJoin(decks, eq(cards.deckId, decks.id))
+ .where(and(eq(cards.id, cardData.id), eq(decks.userId, userId)));
if (existing.length === 0) {
// New card - insert