feat(api): consolidate user profile update endpoints
Add delete_user, reset_user_password, and update_user endpoints to replace individual update operations. Update database schema to include deleted_at column for soft deletion. Add DeleteUser, ResetUserPassword, and UpdateUserAdmin queries. Update Querier with new methods for user management.
This commit is contained in:
@@ -1072,6 +1072,53 @@ func (q *Queries) CreateSyncQueueItem(ctx context.Context, arg CreateSyncQueueIt
|
||||
return i, err
|
||||
}
|
||||
|
||||
const CreateSystemCollection = `-- name: CreateSystemCollection :one
|
||||
INSERT INTO collections (user_id, name, description, icon, color, show_on_dashboard, query_type, priority, is_system_collection, auto_assign_rules)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, true, 'null'::jsonb)
|
||||
RETURNING id, user_id, name, description, color, icon, auto_assign_rules, view_settings, show_on_dashboard, query_type, priority, is_system_collection, created_at
|
||||
`
|
||||
|
||||
type CreateSystemCollectionParams struct {
|
||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Description pgtype.Text `db:"description" json:"description"`
|
||||
Icon pgtype.Text `db:"icon" json:"icon"`
|
||||
Color pgtype.Text `db:"color" json:"color"`
|
||||
ShowOnDashboard pgtype.Bool `db:"show_on_dashboard" json:"show_on_dashboard"`
|
||||
QueryType pgtype.Text `db:"query_type" json:"query_type"`
|
||||
Priority pgtype.Int4 `db:"priority" json:"priority"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSystemCollection(ctx context.Context, arg CreateSystemCollectionParams) (Collections, error) {
|
||||
row := q.db.QueryRow(ctx, CreateSystemCollection,
|
||||
arg.UserID,
|
||||
arg.Name,
|
||||
arg.Description,
|
||||
arg.Icon,
|
||||
arg.Color,
|
||||
arg.ShowOnDashboard,
|
||||
arg.QueryType,
|
||||
arg.Priority,
|
||||
)
|
||||
var i Collections
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.Name,
|
||||
&i.Description,
|
||||
&i.Color,
|
||||
&i.Icon,
|
||||
&i.AutoAssignRules,
|
||||
&i.ViewSettings,
|
||||
&i.ShowOnDashboard,
|
||||
&i.QueryType,
|
||||
&i.Priority,
|
||||
&i.IsSystemCollection,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const CreateUnlinkedBook = `-- name: CreateUnlinkedBook :one
|
||||
|
||||
INSERT INTO unlinked_books (device_id, content_id, file_path, title, author, confidence_score)
|
||||
@@ -1901,12 +1948,16 @@ func (q *Queries) GetCollectionsForBook(ctx context.Context, mediaItemID pgtype.
|
||||
}
|
||||
|
||||
const GetContinueReadingItems = `-- name: GetContinueReadingItems :many
|
||||
SELECT DISTINCT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
|
||||
INNER JOIN reading_progress rp ON rp.media_item_id = mi.id
|
||||
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at
|
||||
FROM reading_progress
|
||||
WHERE user_id = $2
|
||||
AND percentage > 0
|
||||
AND percentage < 1
|
||||
ORDER BY media_item_id, last_read_at DESC
|
||||
) rp ON rp.media_item_id = mi.id
|
||||
WHERE mi.library_id = $1
|
||||
AND rp.user_id = $2
|
||||
AND rp.percentage > 0
|
||||
AND rp.percentage < 1
|
||||
ORDER BY rp.last_read_at DESC
|
||||
LIMIT $3
|
||||
`
|
||||
@@ -4157,11 +4208,15 @@ func (q *Queries) GetRecentlyAddedItems(ctx context.Context, arg GetRecentlyAdde
|
||||
}
|
||||
|
||||
const GetRecentlyReadItems = `-- name: GetRecentlyReadItems :many
|
||||
SELECT DISTINCT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
|
||||
INNER JOIN reading_progress rp ON rp.media_item_id = mi.id
|
||||
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at
|
||||
FROM reading_progress
|
||||
WHERE user_id = $2
|
||||
AND percentage >= 1
|
||||
ORDER BY media_item_id, last_read_at DESC
|
||||
) rp ON rp.media_item_id = mi.id
|
||||
WHERE mi.library_id = $1
|
||||
AND rp.user_id = $2
|
||||
AND rp.percentage >= 1
|
||||
ORDER BY rp.last_read_at DESC
|
||||
LIMIT $3
|
||||
`
|
||||
@@ -4392,14 +4447,15 @@ func (q *Queries) GetSyncQueueStats(ctx context.Context, deviceID pgtype.UUID) (
|
||||
|
||||
const GetSystemCollectionsForDashboard = `-- name: GetSystemCollectionsForDashboard :many
|
||||
SELECT id, user_id, name, description, color, icon, auto_assign_rules, view_settings, show_on_dashboard, query_type, priority, is_system_collection, created_at FROM collections
|
||||
WHERE user_id IS NULL
|
||||
WHERE user_id = $1
|
||||
AND is_system_collection = true
|
||||
AND show_on_dashboard = true
|
||||
ORDER BY priority ASC
|
||||
`
|
||||
|
||||
// Dashboard collections queries
|
||||
func (q *Queries) GetSystemCollectionsForDashboard(ctx context.Context) ([]Collections, error) {
|
||||
rows, err := q.db.Query(ctx, GetSystemCollectionsForDashboard)
|
||||
func (q *Queries) GetSystemCollectionsForDashboard(ctx context.Context, userID pgtype.UUID) ([]Collections, error) {
|
||||
rows, err := q.db.Query(ctx, GetSystemCollectionsForDashboard, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -6649,6 +6705,38 @@ func (q *Queries) RemoveBookFromKoboShelf(ctx context.Context, arg RemoveBookFro
|
||||
return err
|
||||
}
|
||||
|
||||
const ResetSystemCollectionMetadata = `-- name: ResetSystemCollectionMetadata :exec
|
||||
UPDATE collections
|
||||
SET description = $3,
|
||||
icon = $4,
|
||||
color = $5,
|
||||
priority = $6
|
||||
WHERE user_id = $1
|
||||
AND name = $2
|
||||
AND is_system_collection = true
|
||||
`
|
||||
|
||||
type ResetSystemCollectionMetadataParams struct {
|
||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Description pgtype.Text `db:"description" json:"description"`
|
||||
Icon pgtype.Text `db:"icon" json:"icon"`
|
||||
Color pgtype.Text `db:"color" json:"color"`
|
||||
Priority pgtype.Int4 `db:"priority" json:"priority"`
|
||||
}
|
||||
|
||||
func (q *Queries) ResetSystemCollectionMetadata(ctx context.Context, arg ResetSystemCollectionMetadataParams) error {
|
||||
_, err := q.db.Exec(ctx, ResetSystemCollectionMetadata,
|
||||
arg.UserID,
|
||||
arg.Name,
|
||||
arg.Description,
|
||||
arg.Icon,
|
||||
arg.Color,
|
||||
arg.Priority,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const ResolveSyncConflict = `-- name: ResolveSyncConflict :one
|
||||
UPDATE sync_conflicts
|
||||
SET
|
||||
@@ -8430,6 +8518,35 @@ func (q *Queries) UpdateUserProfile(ctx context.Context, arg UpdateUserProfilePa
|
||||
return err
|
||||
}
|
||||
|
||||
const UpdateUserRole = `-- name: UpdateUserRole :one
|
||||
UPDATE users SET role = $2, updated_at = NOW() WHERE id = $1
|
||||
RETURNING id, email, username, role
|
||||
`
|
||||
|
||||
type UpdateUserRoleParams struct {
|
||||
ID pgtype.UUID `db:"id" json:"id"`
|
||||
Role string `db:"role" json:"role"`
|
||||
}
|
||||
|
||||
type UpdateUserRoleRow struct {
|
||||
ID pgtype.UUID `db:"id" json:"id"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Username string `db:"username" json:"username"`
|
||||
Role string `db:"role" json:"role"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateUserRole(ctx context.Context, arg UpdateUserRoleParams) (UpdateUserRoleRow, error) {
|
||||
row := q.db.QueryRow(ctx, UpdateUserRole, arg.ID, arg.Role)
|
||||
var i UpdateUserRoleRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Email,
|
||||
&i.Username,
|
||||
&i.Role,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const UpdateUserTheme = `-- name: UpdateUserTheme :exec
|
||||
UPDATE users SET theme = $2, updated_at = NOW() WHERE id = $1
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user