tududi/backend/migrations/20260420000004-make-password-optional.js
Chris ca77222eae
fix: resolve OIDC session loss and migration failures (#1023)
* fix: resolve OIDC session loss and migration failures

This commit fixes three critical issues affecting OIDC/SSO authentication:

1. Session Not Saved Before Redirect
   - Added explicit req.session.save() callback in OIDC callback handler
   - Ensures session is persisted before redirecting to /today
   - Prevents 401 errors after successful SSO authentication

2. Migration Resilience
   - Added DROP TABLE IF EXISTS users_new in migration
   - Prevents "table already exists" errors from failed migrations
   - Created cleanup script for orphaned migration tables

3. Trust Proxy Documentation
   - Documented TUDUDI_TRUST_PROXY requirement for reverse proxy deployments
   - Added troubleshooting guide for session loss issues
   - Updated .env.example with OIDC configuration examples

Fixes session loss when deployed behind reverse proxies (nginx, Traefik, etc.)

Changes:
- backend/modules/oidc/controller.js: Add session.save() before redirect
- backend/migrations/20260420000004-make-password-optional.js: Add DROP TABLE IF EXISTS
- backend/scripts/cleanup-failed-migration.js: New cleanup utility
- backend/.env.example: Add OIDC and trust proxy examples
- docs/10-oidc-sso.md: Add trust proxy configuration and troubleshooting
- docs/feature-plans/00-oidc-sso.md: Document required environment variables

* fix: prettier formatting in cleanup script
2026-04-14 07:53:55 +03:00

125 lines
5.4 KiB
JavaScript

'use strict';
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.sequelize.query('PRAGMA foreign_keys = OFF;');
await queryInterface.sequelize.query('DROP TABLE IF EXISTS users_new;');
await queryInterface.sequelize.query(`
CREATE TABLE users_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uid VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255),
surname VARCHAR(255),
email VARCHAR(255) NOT NULL UNIQUE,
password_digest VARCHAR(255),
appearance VARCHAR(255) NOT NULL DEFAULT 'light',
language VARCHAR(255) NOT NULL DEFAULT 'en',
timezone VARCHAR(255) NOT NULL DEFAULT 'UTC',
first_day_of_week INTEGER NOT NULL DEFAULT 1,
avatar_image VARCHAR(255),
telegram_bot_token VARCHAR(255),
telegram_chat_id VARCHAR(255),
task_summary_enabled TINYINT(1) NOT NULL DEFAULT 0,
task_summary_frequency VARCHAR(255) DEFAULT 'daily',
task_summary_last_run DATETIME,
task_summary_next_run DATETIME,
telegram_allowed_users TEXT,
task_intelligence_enabled TINYINT(1) NOT NULL DEFAULT 1,
auto_suggest_next_actions_enabled TINYINT(1) NOT NULL DEFAULT 0,
pomodoro_enabled TINYINT(1) NOT NULL DEFAULT 1,
productivity_assistant_enabled TINYINT(1) NOT NULL DEFAULT 1,
next_task_suggestion_enabled TINYINT(1) NOT NULL DEFAULT 1,
today_settings JSON,
sidebar_settings JSON,
ui_settings JSON,
notification_preferences JSON,
keyboard_shortcuts JSON,
email_verified TINYINT(1) NOT NULL DEFAULT 1,
email_verification_token VARCHAR(255),
email_verification_token_expires_at DATETIME,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
ai_provider VARCHAR(255) NOT NULL DEFAULT 'openai',
openai_api_key VARCHAR(255),
ollama_base_url VARCHAR(255) DEFAULT 'http://localhost:11434',
ollama_model VARCHAR(255) DEFAULT 'llama3'
);
`);
await queryInterface.sequelize.query(`
INSERT INTO users_new
SELECT * FROM users;
`);
await queryInterface.sequelize.query('DROP TABLE users;');
await queryInterface.sequelize.query(
'ALTER TABLE users_new RENAME TO users;'
);
await queryInterface.sequelize.query('PRAGMA foreign_keys = ON;');
},
async down(queryInterface, Sequelize) {
await queryInterface.sequelize.query('PRAGMA foreign_keys = OFF;');
await queryInterface.sequelize.query('DROP TABLE IF EXISTS users_new;');
await queryInterface.sequelize.query(`
CREATE TABLE users_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uid VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255),
surname VARCHAR(255),
email VARCHAR(255) NOT NULL UNIQUE,
password_digest VARCHAR(255) NOT NULL,
appearance VARCHAR(255) NOT NULL DEFAULT 'light',
language VARCHAR(255) NOT NULL DEFAULT 'en',
timezone VARCHAR(255) NOT NULL DEFAULT 'UTC',
first_day_of_week INTEGER NOT NULL DEFAULT 1,
avatar_image VARCHAR(255),
telegram_bot_token VARCHAR(255),
telegram_chat_id VARCHAR(255),
task_summary_enabled TINYINT(1) NOT NULL DEFAULT 0,
task_summary_frequency VARCHAR(255) DEFAULT 'daily',
task_summary_last_run DATETIME,
task_summary_next_run DATETIME,
telegram_allowed_users TEXT,
task_intelligence_enabled TINYINT(1) NOT NULL DEFAULT 1,
auto_suggest_next_actions_enabled TINYINT(1) NOT NULL DEFAULT 0,
pomodoro_enabled TINYINT(1) NOT NULL DEFAULT 1,
productivity_assistant_enabled TINYINT(1) NOT NULL DEFAULT 1,
next_task_suggestion_enabled TINYINT(1) NOT NULL DEFAULT 1,
today_settings JSON,
sidebar_settings JSON,
ui_settings JSON,
notification_preferences JSON,
keyboard_shortcuts JSON,
email_verified TINYINT(1) NOT NULL DEFAULT 1,
email_verification_token VARCHAR(255),
email_verification_token_expires_at DATETIME,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
ai_provider VARCHAR(255) NOT NULL DEFAULT 'openai',
openai_api_key VARCHAR(255),
ollama_base_url VARCHAR(255) DEFAULT 'http://localhost:11434',
ollama_model VARCHAR(255) DEFAULT 'llama3'
);
`);
await queryInterface.sequelize.query(`
INSERT INTO users_new
SELECT * FROM users;
`);
await queryInterface.sequelize.query('DROP TABLE users;');
await queryInterface.sequelize.query(
'ALTER TABLE users_new RENAME TO users;'
);
await queryInterface.sequelize.query('PRAGMA foreign_keys = ON;');
},
};