Add timezone support to database schema and queries
- Add timezone column (VARCHAR(50) DEFAULT 'UTC') to users table - Add default_timezone row to system_settings seed data - Add idx_users_timezone index for user timezone lookups - Add UpdateUserTimezone and GetSystemTimezone queries - Regenerate sqlc code (models, querier, queries.sql.go) - Reuse existing UpdateSystemSetting for system timezone updates instead of creating a redundant UpdateSystemTimezone query
This commit is contained in:
@@ -32,6 +32,7 @@ CREATE TABLE IF NOT EXISTS users (
|
|||||||
theme VARCHAR(50) DEFAULT 'tokyo-night',
|
theme VARCHAR(50) DEFAULT 'tokyo-night',
|
||||||
max_devices INTEGER DEFAULT 10,
|
max_devices INTEGER DEFAULT 10,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
timezone VARCHAR(50) DEFAULT 'UTC',
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -47,7 +48,8 @@ CREATE TABLE IF NOT EXISTS system_settings (
|
|||||||
-- Insert default system settings
|
-- Insert default system settings
|
||||||
INSERT INTO system_settings (setting_key, setting_value, description) VALUES
|
INSERT INTO system_settings (setting_key, setting_value, description) VALUES
|
||||||
('scan_poll_interval_seconds', '60', 'How often to scan all libraries in minutes'),
|
('scan_poll_interval_seconds', '60', 'How often to scan all libraries in minutes'),
|
||||||
('auto_scan_enabled', 'true', 'Whether auto-scanning is enabled system-wide')
|
('auto_scan_enabled', 'true', 'Whether auto-scanning is enabled system-wide'),
|
||||||
|
('default_timezone', 'UTC', 'System default timezone')
|
||||||
ON CONFLICT (setting_key) DO NOTHING;
|
ON CONFLICT (setting_key) DO NOTHING;
|
||||||
|
|
||||||
-- Create refresh_tokens table
|
-- Create refresh_tokens table
|
||||||
@@ -457,6 +459,7 @@ CREATE TABLE IF NOT EXISTS reading_history (
|
|||||||
-- Create indexes for better query performance
|
-- Create indexes for better query performance
|
||||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||||
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_users_timezone ON users(timezone);
|
||||||
CREATE INDEX IF NOT EXISTS idx_library_types_name ON library_types(name);
|
CREATE INDEX IF NOT EXISTS idx_library_types_name ON library_types(name);
|
||||||
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token ON refresh_tokens(token);
|
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token ON refresh_tokens(token);
|
||||||
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id);
|
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id);
|
||||||
|
|||||||
@@ -507,5 +507,6 @@ type Users struct {
|
|||||||
Theme pgtype.Text `db:"theme" json:"theme"`
|
Theme pgtype.Text `db:"theme" json:"theme"`
|
||||||
MaxDevices pgtype.Int4 `db:"max_devices" json:"max_devices"`
|
MaxDevices pgtype.Int4 `db:"max_devices" json:"max_devices"`
|
||||||
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
||||||
|
Timezone pgtype.Text `db:"timezone" json:"timezone"`
|
||||||
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ type Querier interface {
|
|||||||
GetSystemConfig(ctx context.Context, key string) (SystemConfig, error)
|
GetSystemConfig(ctx context.Context, key string) (SystemConfig, error)
|
||||||
// System Settings queries
|
// System Settings queries
|
||||||
GetSystemSetting(ctx context.Context, settingKey string) (string, error)
|
GetSystemSetting(ctx context.Context, settingKey string) (string, error)
|
||||||
|
GetSystemTimezone(ctx context.Context) (string, error)
|
||||||
// Get universal progress for a book
|
// Get universal progress for a book
|
||||||
GetUniversalProgress(ctx context.Context, arg GetUniversalProgressParams) (GetUniversalProgressRow, error)
|
GetUniversalProgress(ctx context.Context, arg GetUniversalProgressParams) (GetUniversalProgressRow, error)
|
||||||
// Get unlinked book by ContentId
|
// Get unlinked book by ContentId
|
||||||
@@ -373,6 +374,7 @@ type Querier interface {
|
|||||||
UpdateUserProfile(ctx context.Context, arg UpdateUserProfileParams) error
|
UpdateUserProfile(ctx context.Context, arg UpdateUserProfileParams) error
|
||||||
UpdateUserRole(ctx context.Context, arg UpdateUserRoleParams) (UpdateUserRoleRow, error)
|
UpdateUserRole(ctx context.Context, arg UpdateUserRoleParams) (UpdateUserRoleRow, error)
|
||||||
UpdateUserTheme(ctx context.Context, arg UpdateUserThemeParams) error
|
UpdateUserTheme(ctx context.Context, arg UpdateUserThemeParams) error
|
||||||
|
UpdateUserTimezone(ctx context.Context, arg UpdateUserTimezoneParams) error
|
||||||
UpdateUsername(ctx context.Context, arg UpdateUsernameParams) error
|
UpdateUsername(ctx context.Context, arg UpdateUsernameParams) error
|
||||||
UpsertDashboardPreferences(ctx context.Context, arg UpsertDashboardPreferencesParams) (UserDashboardPreferences, error)
|
UpsertDashboardPreferences(ctx context.Context, arg UpsertDashboardPreferencesParams) (UserDashboardPreferences, error)
|
||||||
UpsertPanelData(ctx context.Context, arg UpsertPanelDataParams) (PanelData, error)
|
UpsertPanelData(ctx context.Context, arg UpsertPanelDataParams) (PanelData, error)
|
||||||
|
|||||||
@@ -5408,6 +5408,17 @@ func (q *Queries) GetSystemSetting(ctx context.Context, settingKey string) (stri
|
|||||||
return setting_value, err
|
return setting_value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GetSystemTimezone = `-- name: GetSystemTimezone :one
|
||||||
|
SELECT setting_value FROM system_settings WHERE setting_key = 'default_timezone'
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetSystemTimezone(ctx context.Context) (string, error) {
|
||||||
|
row := q.db.QueryRow(ctx, GetSystemTimezone)
|
||||||
|
var setting_value string
|
||||||
|
err := row.Scan(&setting_value)
|
||||||
|
return setting_value, err
|
||||||
|
}
|
||||||
|
|
||||||
const GetUniversalProgress = `-- name: GetUniversalProgress :one
|
const GetUniversalProgress = `-- name: GetUniversalProgress :one
|
||||||
SELECT
|
SELECT
|
||||||
rp.id,
|
rp.id,
|
||||||
@@ -10256,7 +10267,7 @@ func (q *Queries) UpdateUniversalProgress(ctx context.Context, arg UpdateUnivers
|
|||||||
|
|
||||||
const UpdateUserMaxDevices = `-- name: UpdateUserMaxDevices :one
|
const UpdateUserMaxDevices = `-- name: UpdateUserMaxDevices :one
|
||||||
UPDATE users SET max_devices = $2, updated_at = NOW() WHERE id = $1
|
UPDATE users SET max_devices = $2, updated_at = NOW() WHERE id = $1
|
||||||
RETURNING id, email, username, password_hash, first_name, last_name, role, theme, max_devices, created_at, updated_at
|
RETURNING id, email, username, password_hash, first_name, last_name, role, theme, max_devices, created_at, timezone, updated_at
|
||||||
`
|
`
|
||||||
|
|
||||||
type UpdateUserMaxDevicesParams struct {
|
type UpdateUserMaxDevicesParams struct {
|
||||||
@@ -10278,6 +10289,7 @@ func (q *Queries) UpdateUserMaxDevices(ctx context.Context, arg UpdateUserMaxDev
|
|||||||
&i.Theme,
|
&i.Theme,
|
||||||
&i.MaxDevices,
|
&i.MaxDevices,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
|
&i.Timezone,
|
||||||
&i.UpdatedAt,
|
&i.UpdatedAt,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
@@ -10341,6 +10353,20 @@ func (q *Queries) UpdateUserTheme(ctx context.Context, arg UpdateUserThemeParams
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UpdateUserTimezone = `-- name: UpdateUserTimezone :exec
|
||||||
|
UPDATE users SET timezone = $2, updated_at = NOW() WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateUserTimezoneParams struct {
|
||||||
|
ID pgtype.UUID `db:"id" json:"id"`
|
||||||
|
Timezone pgtype.Text `db:"timezone" json:"timezone"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateUserTimezone(ctx context.Context, arg UpdateUserTimezoneParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, UpdateUserTimezone, arg.ID, arg.Timezone)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
const UpdateUsername = `-- name: UpdateUsername :exec
|
const UpdateUsername = `-- name: UpdateUsername :exec
|
||||||
UPDATE users SET username = $2, updated_at = NOW() WHERE id = $1
|
UPDATE users SET username = $2, updated_at = NOW() WHERE id = $1
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -300,6 +300,12 @@ RETURNING *;
|
|||||||
UPDATE users SET role = $2, updated_at = NOW() WHERE id = $1
|
UPDATE users SET role = $2, updated_at = NOW() WHERE id = $1
|
||||||
RETURNING id, email, username, role;
|
RETURNING id, email, username, role;
|
||||||
|
|
||||||
|
-- name: UpdateUserTimezone :exec
|
||||||
|
UPDATE users SET timezone = $2, updated_at = NOW() WHERE id = $1;
|
||||||
|
|
||||||
|
-- name: GetSystemTimezone :one
|
||||||
|
SELECT setting_value FROM system_settings WHERE setting_key = 'default_timezone';
|
||||||
|
|
||||||
-- name: CountUserDevices :one
|
-- name: CountUserDevices :one
|
||||||
SELECT COUNT(*) FROM devices WHERE user_id = $1;
|
SELECT COUNT(*) FROM devices WHERE user_id = $1;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user