-- +goose Up -- +goose StatementBegin -- ========================================= -- ТАБЛИЦА: refresh_tokens - JWT Refresh токены -- ========================================= CREATE TABLE refresh_tokens ( id BIGSERIAL PRIMARY KEY, -- Пользователь user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, -- Токен token VARCHAR(512) NOT NULL UNIQUE, expires_at TIMESTAMP WITH TIME ZONE NOT NULL, -- Метаданные запроса user_agent TEXT, ip_address INET, -- Отзыв токена revoked BOOLEAN DEFAULT FALSE, revoked_at TIMESTAMP WITH TIME ZONE, -- Аудит created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- Комментарии COMMENT ON TABLE refresh_tokens IS 'Refresh токены для JWT аутентификации'; COMMENT ON COLUMN refresh_tokens.token IS 'Хеш refresh токена'; COMMENT ON COLUMN refresh_tokens.revoked IS 'Токен отозван (для принудительного логаута)'; -- Индексы CREATE UNIQUE INDEX idx_refresh_tokens_token ON refresh_tokens(token) WHERE revoked = FALSE; CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id) WHERE revoked = FALSE; CREATE INDEX idx_refresh_tokens_expires_at ON refresh_tokens(expires_at); -- ========================================= -- ТАБЛИЦА: user_sessions - Активные сессии пользователей -- ========================================= CREATE TABLE user_sessions ( id BIGSERIAL PRIMARY KEY, -- Пользователь user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, session_token VARCHAR(512) NOT NULL UNIQUE, -- Связь с refresh токеном refresh_token_id BIGINT REFERENCES refresh_tokens(id), -- Сессия expires_at TIMESTAMP WITH TIME ZONE NOT NULL, last_activity_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- Метаданные user_agent TEXT, ip_address INET, device_info JSONB, -- Информация об устройстве в JSON -- Аудит created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- Комментарии COMMENT ON TABLE user_sessions IS 'Активные сессии пользователей для отслеживания активности'; COMMENT ON COLUMN user_sessions.device_info IS 'Информация об устройстве: ОС, браузер, версия и т.д.'; COMMENT ON COLUMN user_sessions.last_activity_at IS 'Последняя активность пользователя в сессии'; -- Индексы CREATE UNIQUE INDEX idx_user_sessions_token ON user_sessions(session_token); CREATE INDEX idx_user_sessions_user_id ON user_sessions(user_id); CREATE INDEX idx_user_sessions_expires_at ON user_sessions(expires_at); CREATE INDEX idx_user_sessions_last_activity ON user_sessions(last_activity_at DESC); -- +goose StatementEnd -- +goose Down -- +goose StatementBegin DROP TABLE IF EXISTS user_sessions CASCADE; DROP TABLE IF EXISTS refresh_tokens CASCADE; -- +goose StatementEnd