fix(worksheets): remove foreign key constraint to support guest users
- Remove FK constraint from worksheet_settings table via migration 0014 - Update schema definition to remove .references() call - Remove user existence check from POST /api/worksheets/settings - Guest users can now save worksheet preferences without user account - Matches pattern used by room_members table for arcade games 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
fa6c2829cc
commit
e6e9ec3e4f
|
|
@ -0,0 +1,28 @@
|
|||
-- Custom SQL migration file, put your code below! --
|
||||
|
||||
-- Remove foreign key constraint from worksheet_settings to allow guest users
|
||||
-- SQLite doesn't support DROP CONSTRAINT, so we need to recreate the table
|
||||
|
||||
-- Create new table without foreign key
|
||||
CREATE TABLE `worksheet_settings_new` (
|
||||
`id` TEXT PRIMARY KEY NOT NULL,
|
||||
`user_id` TEXT NOT NULL,
|
||||
`worksheet_type` TEXT NOT NULL,
|
||||
`config` TEXT NOT NULL,
|
||||
`created_at` INTEGER NOT NULL,
|
||||
`updated_at` INTEGER NOT NULL
|
||||
);--> statement-breakpoint
|
||||
|
||||
-- Copy existing data (if any)
|
||||
INSERT INTO `worksheet_settings_new`
|
||||
SELECT id, user_id, worksheet_type, config, created_at, updated_at
|
||||
FROM `worksheet_settings`;--> statement-breakpoint
|
||||
|
||||
-- Drop old table
|
||||
DROP TABLE `worksheet_settings`;--> statement-breakpoint
|
||||
|
||||
-- Rename new table to original name
|
||||
ALTER TABLE `worksheet_settings_new` RENAME TO `worksheet_settings`;--> statement-breakpoint
|
||||
|
||||
-- Recreate index
|
||||
CREATE INDEX `worksheet_settings_user_type_idx` ON `worksheet_settings` (`user_id`, `worksheet_type`);
|
||||
|
|
@ -116,13 +116,9 @@
|
|||
"abacus_settings_user_id_users_id_fk": {
|
||||
"name": "abacus_settings_user_id_users_id_fk",
|
||||
"tableFrom": "abacus_settings",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"columnsFrom": ["user_id"],
|
||||
"tableTo": "users",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -240,9 +236,7 @@
|
|||
"indexes": {
|
||||
"arcade_rooms_code_unique": {
|
||||
"name": "arcade_rooms_code_unique",
|
||||
"columns": [
|
||||
"code"
|
||||
],
|
||||
"columns": ["code"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
|
|
@ -339,26 +333,18 @@
|
|||
"arcade_sessions_room_id_arcade_rooms_id_fk": {
|
||||
"name": "arcade_sessions_room_id_arcade_rooms_id_fk",
|
||||
"tableFrom": "arcade_sessions",
|
||||
"columnsFrom": [
|
||||
"room_id"
|
||||
],
|
||||
"columnsFrom": ["room_id"],
|
||||
"tableTo": "arcade_rooms",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"arcade_sessions_user_id_users_id_fk": {
|
||||
"name": "arcade_sessions_user_id_users_id_fk",
|
||||
"tableFrom": "arcade_sessions",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"columnsFrom": ["user_id"],
|
||||
"tableTo": "users",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -424,9 +410,7 @@
|
|||
"indexes": {
|
||||
"players_user_id_idx": {
|
||||
"name": "players_user_id_idx",
|
||||
"columns": [
|
||||
"user_id"
|
||||
],
|
||||
"columns": ["user_id"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
|
|
@ -434,13 +418,9 @@
|
|||
"players_user_id_users_id_fk": {
|
||||
"name": "players_user_id_users_id_fk",
|
||||
"tableFrom": "players",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"columnsFrom": ["user_id"],
|
||||
"tableTo": "users",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -514,9 +494,7 @@
|
|||
"indexes": {
|
||||
"idx_room_members_user_id_unique": {
|
||||
"name": "idx_room_members_user_id_unique",
|
||||
"columns": [
|
||||
"user_id"
|
||||
],
|
||||
"columns": ["user_id"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
|
|
@ -524,13 +502,9 @@
|
|||
"room_members_room_id_arcade_rooms_id_fk": {
|
||||
"name": "room_members_room_id_arcade_rooms_id_fk",
|
||||
"tableFrom": "room_members",
|
||||
"columnsFrom": [
|
||||
"room_id"
|
||||
],
|
||||
"columnsFrom": ["room_id"],
|
||||
"tableTo": "arcade_rooms",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -605,13 +579,9 @@
|
|||
"room_member_history_room_id_arcade_rooms_id_fk": {
|
||||
"name": "room_member_history_room_id_arcade_rooms_id_fk",
|
||||
"tableFrom": "room_member_history",
|
||||
"columnsFrom": [
|
||||
"room_id"
|
||||
],
|
||||
"columnsFrom": ["room_id"],
|
||||
"tableTo": "arcade_rooms",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -713,10 +683,7 @@
|
|||
"indexes": {
|
||||
"idx_room_invitations_user_room": {
|
||||
"name": "idx_room_invitations_user_room",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"room_id"
|
||||
],
|
||||
"columns": ["user_id", "room_id"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
|
|
@ -724,13 +691,9 @@
|
|||
"room_invitations_room_id_arcade_rooms_id_fk": {
|
||||
"name": "room_invitations_room_id_arcade_rooms_id_fk",
|
||||
"tableFrom": "room_invitations",
|
||||
"columnsFrom": [
|
||||
"room_id"
|
||||
],
|
||||
"columnsFrom": ["room_id"],
|
||||
"tableTo": "arcade_rooms",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -833,13 +796,9 @@
|
|||
"room_reports_room_id_arcade_rooms_id_fk": {
|
||||
"name": "room_reports_room_id_arcade_rooms_id_fk",
|
||||
"tableFrom": "room_reports",
|
||||
"columnsFrom": [
|
||||
"room_id"
|
||||
],
|
||||
"columnsFrom": ["room_id"],
|
||||
"tableTo": "arcade_rooms",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -918,10 +877,7 @@
|
|||
"indexes": {
|
||||
"idx_room_bans_user_room": {
|
||||
"name": "idx_room_bans_user_room",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"room_id"
|
||||
],
|
||||
"columns": ["user_id", "room_id"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
|
|
@ -929,13 +885,9 @@
|
|||
"room_bans_room_id_arcade_rooms_id_fk": {
|
||||
"name": "room_bans_room_id_arcade_rooms_id_fk",
|
||||
"tableFrom": "room_bans",
|
||||
"columnsFrom": [
|
||||
"room_id"
|
||||
],
|
||||
"columnsFrom": ["room_id"],
|
||||
"tableTo": "arcade_rooms",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -998,13 +950,9 @@
|
|||
"user_stats_user_id_users_id_fk": {
|
||||
"name": "user_stats_user_id_users_id_fk",
|
||||
"tableFrom": "user_stats",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"columnsFrom": ["user_id"],
|
||||
"tableTo": "users",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"columnsTo": ["id"],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
|
|
@ -1062,16 +1010,12 @@
|
|||
"indexes": {
|
||||
"users_guest_id_unique": {
|
||||
"name": "users_guest_id_unique",
|
||||
"columns": [
|
||||
"guest_id"
|
||||
],
|
||||
"columns": ["guest_id"],
|
||||
"isUnique": true
|
||||
},
|
||||
"users_email_unique": {
|
||||
"name": "users_email_unique",
|
||||
"columns": [
|
||||
"email"
|
||||
],
|
||||
"columns": ["email"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
|
|
@ -1091,4 +1035,4 @@
|
|||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -99,6 +99,13 @@
|
|||
"when": 1762432185673,
|
||||
"tag": "0013_conscious_firebird",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"version": "6",
|
||||
"when": 1762434916279,
|
||||
"tag": "0014_remarkable_master_chief",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ export async function GET(req: NextRequest) {
|
|||
|
||||
// Only 'addition' is supported for now
|
||||
if (worksheetType !== 'addition') {
|
||||
return NextResponse.json({ error: `Unsupported worksheet type: ${worksheetType}` }, { status: 400 })
|
||||
return NextResponse.json(
|
||||
{ error: `Unsupported worksheet type: ${worksheetType}` },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Look up user's saved settings
|
||||
|
|
@ -97,20 +100,10 @@ export async function POST(req: NextRequest) {
|
|||
|
||||
// Only 'addition' is supported for now
|
||||
if (worksheetType !== 'addition') {
|
||||
return NextResponse.json({ error: `Unsupported worksheet type: ${worksheetType}` }, { status: 400 })
|
||||
}
|
||||
|
||||
// Check if user exists in database
|
||||
const [user] = await db.select().from(schema.users).where(eq(schema.users.id, viewerId)).limit(1)
|
||||
|
||||
if (!user) {
|
||||
// User doesn't exist yet - this is OK for guest users
|
||||
// Don't save settings for non-existent users
|
||||
console.log(`[Worksheet Settings] Skipping save for non-existent user: ${viewerId}`)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
message: 'Settings not saved - user account not created yet',
|
||||
})
|
||||
return NextResponse.json(
|
||||
{ error: `Unsupported worksheet type: ${worksheetType}` },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Serialize config (adds version automatically)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
||||
import { users } from './users'
|
||||
|
||||
/**
|
||||
* Worksheet generator settings table - persists user preferences per worksheet type
|
||||
|
|
@ -9,15 +8,16 @@ import { users } from './users'
|
|||
*
|
||||
* The config column stores versioned JSON that is validated at runtime
|
||||
* See src/app/create/worksheets/config-schemas.ts for schema definitions
|
||||
*
|
||||
* Note: No foreign key constraint - allows guest users to save settings
|
||||
* (matches pattern used by room_members table)
|
||||
*/
|
||||
export const worksheetSettings = sqliteTable('worksheet_settings', {
|
||||
/** Unique identifier (UUID) */
|
||||
id: text('id').primaryKey(),
|
||||
|
||||
/** Foreign key to users table */
|
||||
userId: text('user_id')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
/** User ID (may be authenticated user or guest ID) */
|
||||
userId: text('user_id').notNull(),
|
||||
|
||||
/** Type of worksheet: 'addition', 'subtraction', 'multiplication', etc. */
|
||||
worksheetType: text('worksheet_type').notNull(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue