diff --git a/src/MyWebLog.Data/SQLite/SQLitePageData.fs b/src/MyWebLog.Data/SQLite/SQLitePageData.fs index 2f194f4..5dbb71e 100644 --- a/src/MyWebLog.Data/SQLite/SQLitePageData.fs +++ b/src/MyWebLog.Data/SQLite/SQLitePageData.fs @@ -328,7 +328,7 @@ type SQLitePageData (conn : SqliteConnection) = is_in_page_list = @isInPageList, template = @template, page_text = @text - WHERE id = @pageId + WHERE id = @id AND web_log_id = @webLogId""" addPageParameters cmd page do! write cmd diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs index 4fb7822..7013583 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs @@ -320,6 +320,7 @@ type SQLiteWebLogData (conn : SqliteConnection) = copyright = @copyright WHERE id = @id""" addWebLogRssParameters cmd webLog + cmd.Parameters.AddWithValue ("@id", WebLogId.toString webLog.Id) |> ignore do! write cmd do! updateCustomFeeds webLog } diff --git a/src/MyWebLog/Handlers/Admin.fs b/src/MyWebLog/Handlers/Admin.fs index 6e5023e..1302bcc 100644 --- a/src/MyWebLog/Handlers/Admin.fs +++ b/src/MyWebLog/Handlers/Admin.fs @@ -198,31 +198,20 @@ open Microsoft.AspNetCore.Http // ~~ TAG MAPPINGS ~~ -/// Get the hash necessary to render the tag mapping list -let private tagMappingHash (ctx : HttpContext) = task { +/// Add tag mappings to the given hash +let private withTagMappings (ctx : HttpContext) hash = task { let! mappings = ctx.Data.TagMap.FindByWebLog ctx.WebLog.Id - return! - hashForPage "Tag Mappings" - |> withAntiCsrf ctx - |> addToHash "mappings" mappings + return + addToHash "mappings" mappings hash |> addToHash "mapping_ids" (mappings |> List.map (fun it -> { Name = it.Tag; Value = TagMapId.toString it.Id })) - |> addViewContext ctx } // GET /admin/settings/tag-mappings let tagMappings : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> task { - match! TemplateCache.get adminTheme "tag-mapping-list-body" ctx.Data with - | Ok listTemplate -> - let! hash = tagMappingHash ctx - return! - addToHash "tag_mapping_list" (listTemplate.Render hash) hash - |> adminView "tag-mapping-list" next ctx - | Error message -> return! Error.server message next ctx -} - -// GET /admin/settings/tag-mappings/bare -let tagMappingsBare : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> task { - let! hash = tagMappingHash ctx + let! hash = + hashForPage "" + |> withAntiCsrf ctx + |> withTagMappings ctx return! adminBareView "tag-mapping-list-body" next ctx hash } @@ -253,7 +242,7 @@ let saveMapping : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> ta | Some tm -> do! data.TagMap.Save { tm with Tag = model.Tag.ToLower (); UrlValue = model.UrlValue.ToLower () } do! addMessage ctx { UserMessage.success with Message = "Tag mapping saved successfully" } - return! tagMappingsBare next ctx + return! tagMappings next ctx | None -> return! Error.notFound next ctx } @@ -262,7 +251,7 @@ let deleteMapping tagMapId : HttpHandler = requireAccess WebLogAdmin >=> fun nex match! ctx.Data.TagMap.Delete (TagMapId tagMapId) ctx.WebLog.Id with | true -> do! addMessage ctx { UserMessage.success with Message = "Tag mapping deleted successfully" } | false -> do! addMessage ctx { UserMessage.error with Message = "Tag mapping not found; nothing deleted" } - return! tagMappingsBare next ctx + return! tagMappings next ctx } // ~~ THEMES ~~ @@ -433,35 +422,45 @@ let settings : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> task let data = ctx.Data match! TemplateCache.get adminTheme "user-list-body" data with | Ok userTemplate -> - let! allPages = data.Page.All ctx.WebLog.Id - let! themes = data.Theme.All () - let! users = data.WebLogUser.FindByWebLog ctx.WebLog.Id - let! hash = - hashForPage "Web Log Settings" - |> withAntiCsrf ctx - |> addToHash ViewContext.Model (SettingsModel.fromWebLog ctx.WebLog) - |> addToHash "pages" ( - seq { - KeyValuePair.Create ("posts", "- First Page of Posts -") - yield! allPages - |> List.sortBy (fun p -> p.Title.ToLower ()) - |> List.map (fun p -> KeyValuePair.Create (PageId.toString p.Id, p.Title)) - } - |> Array.ofSeq) - |> addToHash "themes" ( - themes - |> Seq.ofList - |> Seq.map (fun it -> KeyValuePair.Create (ThemeId.toString it.Id, $"{it.Name} (v{it.Version})")) - |> Array.ofSeq) - |> addToHash "upload_values" [| - KeyValuePair.Create (UploadDestination.toString Database, "Database") - KeyValuePair.Create (UploadDestination.toString Disk, "Disk") - |] - |> addToHash "users" (users |> List.map (DisplayUser.fromUser ctx.WebLog) |> Array.ofList) - |> addViewContext ctx - return! - addToHash "user_list" (userTemplate.Render hash) hash - |> adminView "settings" next ctx + match! TemplateCache.get adminTheme "tag-mapping-list-body" ctx.Data with + | Ok tagMapTemplate -> + let! allPages = data.Page.All ctx.WebLog.Id + let! themes = data.Theme.All () + let! users = data.WebLogUser.FindByWebLog ctx.WebLog.Id + let! hash = + hashForPage "Web Log Settings" + |> withAntiCsrf ctx + |> addToHash ViewContext.Model (SettingsModel.fromWebLog ctx.WebLog) + |> addToHash "pages" ( + seq { + KeyValuePair.Create ("posts", "- First Page of Posts -") + yield! allPages + |> List.sortBy (fun p -> p.Title.ToLower ()) + |> List.map (fun p -> KeyValuePair.Create (PageId.toString p.Id, p.Title)) + } + |> Array.ofSeq) + |> addToHash "themes" ( + themes + |> Seq.ofList + |> Seq.map (fun it -> KeyValuePair.Create (ThemeId.toString it.Id, $"{it.Name} (v{it.Version})")) + |> Array.ofSeq) + |> addToHash "upload_values" [| + KeyValuePair.Create (UploadDestination.toString Database, "Database") + KeyValuePair.Create (UploadDestination.toString Disk, "Disk") + |] + |> addToHash "users" (users |> List.map (DisplayUser.fromUser ctx.WebLog) |> Array.ofList) + |> addToHash "rss_model" (EditRssModel.fromRssOptions ctx.WebLog.Rss) + |> addToHash "custom_feeds" ( + ctx.WebLog.Rss.CustomFeeds + |> List.map (DisplayCustomFeed.fromFeed (CategoryCache.get ctx)) + |> Array.ofList) + |> addViewContext ctx + let! hash' = withTagMappings ctx hash + return! + addToHash "user_list" (userTemplate.Render hash') hash' + |> addToHash "tag_mapping_list" (tagMapTemplate.Render hash') + |> adminView "settings" next ctx + | Error message -> return! Error.server message next ctx | Error message -> return! Error.server message next ctx } diff --git a/src/MyWebLog/Handlers/Feed.fs b/src/MyWebLog/Handlers/Feed.fs index ef40a44..7efec6b 100644 --- a/src/MyWebLog/Handlers/Feed.fs +++ b/src/MyWebLog/Handlers/Feed.fs @@ -414,17 +414,6 @@ let generate (feedType : FeedType) postCount : HttpHandler = fun next ctx -> bac // ~~ FEED ADMINISTRATION ~~ -// GET /admin/settings/rss -let editSettings : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> - hashForPage "RSS Settings" - |> withAntiCsrf ctx - |> addToHash ViewContext.Model (EditRssModel.fromRssOptions ctx.WebLog.Rss) - |> addToHash "custom_feeds" ( - ctx.WebLog.Rss.CustomFeeds - |> List.map (DisplayCustomFeed.fromFeed (CategoryCache.get ctx)) - |> Array.ofList) - |> adminView "rss-settings" next ctx - // POST /admin/settings/rss let saveSettings : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> task { let data = ctx.Data @@ -435,7 +424,7 @@ let saveSettings : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> t do! data.WebLog.UpdateRssOptions webLog WebLogCache.set webLog do! addMessage ctx { UserMessage.success with Message = "RSS settings updated successfully" } - return! redirectToGet "admin/settings/rss" next ctx + return! redirectToGet "admin/settings#rss-settings" next ctx | None -> return! Error.notFound next ctx } @@ -507,6 +496,6 @@ let deleteCustomFeed feedId : HttpHandler = requireAccess WebLogAdmin >=> fun ne do! addMessage ctx { UserMessage.success with Message = "Custom feed deleted successfully" } else do! addMessage ctx { UserMessage.warning with Message = "Custom feed not found; no action taken" } - return! redirectToGet "admin/settings/rss" next ctx + return! redirectToGet "admin/settings#rss-settings" next ctx | None -> return! Error.notFound next ctx } diff --git a/src/MyWebLog/Handlers/Helpers.fs b/src/MyWebLog/Handlers/Helpers.fs index 01e62dd..77b6241 100644 --- a/src/MyWebLog/Handlers/Helpers.fs +++ b/src/MyWebLog/Handlers/Helpers.fs @@ -343,7 +343,6 @@ let validateCsrf : HttpHandler = fun next ctx -> task { | false -> return! RequestErrors.BAD_REQUEST "CSRF token invalid" earlyReturn ctx } - /// Require a user to be logged on let requireUser : HttpHandler = requiresAuthentication Error.notAuthorized diff --git a/src/MyWebLog/Handlers/Routes.fs b/src/MyWebLog/Handlers/Routes.fs index b04bff1..f0a5b8d 100644 --- a/src/MyWebLog/Handlers/Routes.fs +++ b/src/MyWebLog/Handlers/Routes.fs @@ -131,19 +131,14 @@ let router : HttpHandler = choose [ routef "/%s/revisions" Post.editRevisions ]) subRoute "/settings" (choose [ - route "" >=> Admin.settings - subRoute "/rss" (choose [ - route "" >=> Feed.editSettings - routef "/%s/edit" Feed.editCustomFeed - ]) + route "" >=> Admin.settings + routef "/rss/%s/edit" Feed.editCustomFeed subRoute "/user" (choose [ - route "s" >=> User.all - routef "/%s/edit" User.edit - + route "s" >=> User.all + routef "/%s/edit" User.edit ]) subRoute "/tag-mapping" (choose [ route "s" >=> Admin.tagMappings - route "s/bare" >=> Admin.tagMappingsBare routef "/%s/edit" Admin.editMapping ]) ]) diff --git a/src/admin-theme/_layout.liquid b/src/admin-theme/_layout.liquid index bf2418c..c9df14c 100644 --- a/src/admin-theme/_layout.liquid +++ b/src/admin-theme/_layout.liquid @@ -26,7 +26,7 @@ {%- endif %}