feat: create admin dashboard with user preferences and library settings
- Add admin dashboard at /admin route consolidating all user settings - Move user preferences (username, email, password, theme) from separate page - Add ebook library preferences section with folder management - Add scan settings (frequency and auto-scan toggle) with database persistence - Create database migration for scan_frequency_minutes and auto_scan_enabled columns - Add API endpoints for scan settings management: - PUT /api/library/scan-settings - Update scan preferences - GET /api/library/scan-settings - Get current scan settings - Update dashboard navigation to link to admin dashboard - Remove old preferences.html template (functionality moved to admin) - Create Bruno API testing files for library endpoints - Add real-time folder loading and management in admin interface - Implement scan settings persistence and retrieval from database
This commit is contained in:
@@ -588,6 +588,62 @@ func (h *AuthHandler) DeleteAccount(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, map[string]string{"message": "account deleted successfully"})
|
||||
}
|
||||
|
||||
type UpdateScanSettingsRequest struct {
|
||||
ScanFrequencyMinutes int32 `json:"scan_frequency_minutes" validate:"required,min=15,max=1440"`
|
||||
AutoScanEnabled bool `json:"auto_scan_enabled"`
|
||||
}
|
||||
|
||||
// UpdateScanSettings handles PUT /api/library/scan-settings
|
||||
func (h *AuthHandler) UpdateScanSettings(c echo.Context) error {
|
||||
userID := c.Get("user_id").(string)
|
||||
userUUID, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"})
|
||||
}
|
||||
|
||||
var req UpdateScanSettingsRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request"})
|
||||
}
|
||||
if err := c.Validate(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
err = h.db.UpdateScanSettings(c.Request().Context(), database.UpdateScanSettingsParams{
|
||||
ID: pgtype.UUID{Bytes: userUUID, Valid: true},
|
||||
ScanFrequencyMinutes: pgtype.Int4{Int32: req.ScanFrequencyMinutes, Valid: true},
|
||||
AutoScanEnabled: pgtype.Bool{Bool: req.AutoScanEnabled, Valid: true},
|
||||
})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]string{"message": "scan settings updated successfully"})
|
||||
}
|
||||
|
||||
// GetScanSettings handles GET /api/library/scan-settings
|
||||
func (h *AuthHandler) GetScanSettings(c echo.Context) error {
|
||||
userID := c.Get("user_id").(string)
|
||||
userUUID, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"})
|
||||
}
|
||||
|
||||
settings, err := h.db.GetScanSettings(c.Request().Context(), pgtype.UUID{Bytes: userUUID, Valid: true})
|
||||
if err != nil {
|
||||
// If no settings found, return defaults
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"scan_frequency_minutes": 60,
|
||||
"auto_scan_enabled": true,
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"scan_frequency_minutes": settings.ScanFrequencyMinutes.Int32,
|
||||
"auto_scan_enabled": settings.AutoScanEnabled.Bool,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) generateJWT(userID string) (string, error) {
|
||||
claims := jwtgo.MapClaims{
|
||||
"user_id": userID,
|
||||
|
||||
Reference in New Issue
Block a user