From 98eb2b17851b4d21274143bcb84ede71c6b2a1af Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 16 Apr 2022 23:06:38 -0400 Subject: [PATCH] WIP on DotLiquid support --- src/{MyWebLog => MyWebLog.CS}/Db/.gitignore | 0 .../Features/Admin/AdminController.cs | 0 .../Features/Admin/DashboardModel.cs | 0 .../Features/Admin/Index.cshtml | 0 .../Features/Admin/Settings.cshtml | 0 .../Features/Admin/SettingsModel.cs | 0 .../Features/Categories/CategoryController.cs | 0 .../Features/FeatureSupport.cs | 0 .../Features/Pages/All.cshtml | 0 .../Features/Pages/Edit.cshtml | 0 .../Features/Pages/EditPageModel.cs | 0 .../Features/Pages/PageController.cs | 0 .../Features/Pages/PageListModel.cs | 0 .../Features/Pages/SinglePageModel.cs | 0 .../Features/Posts/MultiplePostModel.cs | 0 .../Features/Posts/PostController.cs | 0 .../Features/Shared/MyWebLogController.cs | 0 .../Features/Shared/MyWebLogModel.cs | 0 .../Shared/TagHelpers/ImageTagHelper.cs | 0 .../Shared/TagHelpers/LinkTagHelper.cs | 0 .../Shared/TagHelpers/YesNoTagHelper.cs | 0 .../Features/Shared/_AdminLayout.cshtml | 0 .../Features/Shared/_LogOnOffPartial.cshtml | 0 .../Features/ThemeSupport.cs | 0 .../Features/Users/LogOn.cshtml | 0 .../Features/Users/LogOnModel.cs | 0 .../Features/Users/UserController.cs | 0 .../Features/_ViewImports.cshtml | 0 src/{MyWebLog => MyWebLog.CS}/GlobalUsings.cs | 0 .../MyWebLog.CS.csproj} | 0 src/{MyWebLog => MyWebLog.CS}/Program.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties}/Resources.resx | 0 .../Properties/launchSettings.json | 0 .../Default/Shared/_DefaultFooter.cshtml | 0 .../Default/Shared/_DefaultHeader.cshtml | 0 .../Themes/Default/Shared/_Layout.cshtml | 0 .../Themes/Default/SinglePage.cshtml | 0 .../Themes/_ViewImports.cshtml | 0 .../WebLogMiddleware.cs | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../wwwroot/css/admin.css | 0 .../wwwroot/img/logo-dark.png | Bin .../wwwroot/img/logo-light.png | Bin src/MyWebLog.Data/Converters.fs | 15 +- src/MyWebLog.Data/Data.fs | 58 ++++++- src/MyWebLog.Domain/DataTypes.fs | 2 +- src/MyWebLog.Domain/MyWebLog.Domain.fsproj | 1 + src/MyWebLog.Domain/SupportTypes.fs | 2 +- src/MyWebLog.Domain/ViewModels.fs | 32 ++++ .../Features/Admin/AdminController.fs | 1 - .../Features/Admin/AdminTypes.fs | 0 .../Features/Admin/Index.cshtml | 0 .../Features/Pages/PageTypes.fs | 0 .../Features/Posts/PostController.fs | 0 .../Features/Posts/PostTypes.fs | 0 .../Features/Shared/SharedTypes.fs | 0 src/MyWebLog.FS.Old/Handlers.fs | 2 + .../MyWebLog.FS.Old.fsproj} | 1 + .../Program.fs | 0 .../Properties/launchSettings.json | 0 .../Resources.resx | 0 .../WebLogCache.fs | 0 .../appsettings.Development.json | 0 src/MyWebLog.FS.Old/appsettings.json | 9 ++ .../MyWebLog.Themes.BitBadger.csproj | 7 - src/MyWebLog.sln | 34 ++-- src/MyWebLog/Handlers.fs | 59 +++++++ src/MyWebLog/MyWebLog.fsproj | 32 ++++ src/MyWebLog/Program.fs | 150 ++++++++++++++++++ src/MyWebLog/WebLogCache.fs | 24 +++ src/MyWebLog/appsettings.json | 13 +- src/MyWebLog/themes/default/_html-head.liquid | 11 ++ src/MyWebLog/themes/default/_page-foot.liquid | 6 + src/MyWebLog/themes/default/_page-head.liquid | 18 +++ .../themes/default/single-page.liquid | 14 ++ src/MyWebLog/wwwroot/admin/admin.css | 5 + 78 files changed, 451 insertions(+), 45 deletions(-) rename src/{MyWebLog => MyWebLog.CS}/Db/.gitignore (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Admin/AdminController.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Admin/DashboardModel.cs (100%) rename src/{MyWebLog.FS => MyWebLog.CS}/Features/Admin/Index.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Admin/Settings.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Admin/SettingsModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Categories/CategoryController.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/FeatureSupport.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Pages/All.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Pages/Edit.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Pages/EditPageModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Pages/PageController.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Pages/PageListModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Pages/SinglePageModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Posts/MultiplePostModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Posts/PostController.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/MyWebLogController.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/MyWebLogModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/TagHelpers/ImageTagHelper.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/TagHelpers/LinkTagHelper.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/TagHelpers/YesNoTagHelper.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/_AdminLayout.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Shared/_LogOnOffPartial.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/ThemeSupport.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Users/LogOn.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Users/LogOnModel.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/Users/UserController.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Features/_ViewImports.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/GlobalUsings.cs (100%) rename src/{MyWebLog/MyWebLog.csproj => MyWebLog.CS/MyWebLog.CS.csproj} (100%) rename src/{MyWebLog => MyWebLog.CS}/Program.cs (100%) rename src/{MyWebLog => MyWebLog.CS}/Properties/Resources.Designer.cs (100%) rename src/{MyWebLog.FS => MyWebLog.CS/Properties}/Resources.resx (100%) rename src/{MyWebLog => MyWebLog.CS}/Properties/launchSettings.json (100%) rename src/{MyWebLog => MyWebLog.CS}/Themes/Default/Shared/_DefaultFooter.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Themes/Default/Shared/_DefaultHeader.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Themes/Default/Shared/_Layout.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Themes/Default/SinglePage.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/Themes/_ViewImports.cshtml (100%) rename src/{MyWebLog => MyWebLog.CS}/WebLogMiddleware.cs (100%) rename src/{MyWebLog.FS => MyWebLog.CS}/appsettings.Development.json (100%) rename src/{MyWebLog.FS => MyWebLog.CS}/appsettings.json (100%) rename src/{MyWebLog => MyWebLog.CS}/wwwroot/css/admin.css (100%) rename src/{MyWebLog => MyWebLog.CS}/wwwroot/img/logo-dark.png (100%) rename src/{MyWebLog => MyWebLog.CS}/wwwroot/img/logo-light.png (100%) create mode 100644 src/MyWebLog.Domain/ViewModels.fs rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Features/Admin/AdminController.fs (97%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Features/Admin/AdminTypes.fs (100%) rename src/{MyWebLog => MyWebLog.FS.Old}/Features/Admin/Index.cshtml (100%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Features/Pages/PageTypes.fs (100%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Features/Posts/PostController.fs (100%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Features/Posts/PostTypes.fs (100%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Features/Shared/SharedTypes.fs (100%) create mode 100644 src/MyWebLog.FS.Old/Handlers.fs rename src/{MyWebLog.FS/MyWebLog.FS.fsproj => MyWebLog.FS.Old/MyWebLog.FS.Old.fsproj} (96%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Program.fs (100%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/Properties/launchSettings.json (100%) rename src/{MyWebLog/Properties => MyWebLog.FS.Old}/Resources.resx (100%) rename src/{MyWebLog.FS => MyWebLog.FS.Old}/WebLogCache.fs (100%) rename src/{MyWebLog => MyWebLog.FS.Old}/appsettings.Development.json (100%) create mode 100644 src/MyWebLog.FS.Old/appsettings.json create mode 100644 src/MyWebLog/Handlers.fs create mode 100644 src/MyWebLog/MyWebLog.fsproj create mode 100644 src/MyWebLog/Program.fs create mode 100644 src/MyWebLog/WebLogCache.fs create mode 100644 src/MyWebLog/themes/default/_html-head.liquid create mode 100644 src/MyWebLog/themes/default/_page-foot.liquid create mode 100644 src/MyWebLog/themes/default/_page-head.liquid create mode 100644 src/MyWebLog/themes/default/single-page.liquid create mode 100644 src/MyWebLog/wwwroot/admin/admin.css diff --git a/src/MyWebLog/Db/.gitignore b/src/MyWebLog.CS/Db/.gitignore similarity index 100% rename from src/MyWebLog/Db/.gitignore rename to src/MyWebLog.CS/Db/.gitignore diff --git a/src/MyWebLog/Features/Admin/AdminController.cs b/src/MyWebLog.CS/Features/Admin/AdminController.cs similarity index 100% rename from src/MyWebLog/Features/Admin/AdminController.cs rename to src/MyWebLog.CS/Features/Admin/AdminController.cs diff --git a/src/MyWebLog/Features/Admin/DashboardModel.cs b/src/MyWebLog.CS/Features/Admin/DashboardModel.cs similarity index 100% rename from src/MyWebLog/Features/Admin/DashboardModel.cs rename to src/MyWebLog.CS/Features/Admin/DashboardModel.cs diff --git a/src/MyWebLog.FS/Features/Admin/Index.cshtml b/src/MyWebLog.CS/Features/Admin/Index.cshtml similarity index 100% rename from src/MyWebLog.FS/Features/Admin/Index.cshtml rename to src/MyWebLog.CS/Features/Admin/Index.cshtml diff --git a/src/MyWebLog/Features/Admin/Settings.cshtml b/src/MyWebLog.CS/Features/Admin/Settings.cshtml similarity index 100% rename from src/MyWebLog/Features/Admin/Settings.cshtml rename to src/MyWebLog.CS/Features/Admin/Settings.cshtml diff --git a/src/MyWebLog/Features/Admin/SettingsModel.cs b/src/MyWebLog.CS/Features/Admin/SettingsModel.cs similarity index 100% rename from src/MyWebLog/Features/Admin/SettingsModel.cs rename to src/MyWebLog.CS/Features/Admin/SettingsModel.cs diff --git a/src/MyWebLog/Features/Categories/CategoryController.cs b/src/MyWebLog.CS/Features/Categories/CategoryController.cs similarity index 100% rename from src/MyWebLog/Features/Categories/CategoryController.cs rename to src/MyWebLog.CS/Features/Categories/CategoryController.cs diff --git a/src/MyWebLog/Features/FeatureSupport.cs b/src/MyWebLog.CS/Features/FeatureSupport.cs similarity index 100% rename from src/MyWebLog/Features/FeatureSupport.cs rename to src/MyWebLog.CS/Features/FeatureSupport.cs diff --git a/src/MyWebLog/Features/Pages/All.cshtml b/src/MyWebLog.CS/Features/Pages/All.cshtml similarity index 100% rename from src/MyWebLog/Features/Pages/All.cshtml rename to src/MyWebLog.CS/Features/Pages/All.cshtml diff --git a/src/MyWebLog/Features/Pages/Edit.cshtml b/src/MyWebLog.CS/Features/Pages/Edit.cshtml similarity index 100% rename from src/MyWebLog/Features/Pages/Edit.cshtml rename to src/MyWebLog.CS/Features/Pages/Edit.cshtml diff --git a/src/MyWebLog/Features/Pages/EditPageModel.cs b/src/MyWebLog.CS/Features/Pages/EditPageModel.cs similarity index 100% rename from src/MyWebLog/Features/Pages/EditPageModel.cs rename to src/MyWebLog.CS/Features/Pages/EditPageModel.cs diff --git a/src/MyWebLog/Features/Pages/PageController.cs b/src/MyWebLog.CS/Features/Pages/PageController.cs similarity index 100% rename from src/MyWebLog/Features/Pages/PageController.cs rename to src/MyWebLog.CS/Features/Pages/PageController.cs diff --git a/src/MyWebLog/Features/Pages/PageListModel.cs b/src/MyWebLog.CS/Features/Pages/PageListModel.cs similarity index 100% rename from src/MyWebLog/Features/Pages/PageListModel.cs rename to src/MyWebLog.CS/Features/Pages/PageListModel.cs diff --git a/src/MyWebLog/Features/Pages/SinglePageModel.cs b/src/MyWebLog.CS/Features/Pages/SinglePageModel.cs similarity index 100% rename from src/MyWebLog/Features/Pages/SinglePageModel.cs rename to src/MyWebLog.CS/Features/Pages/SinglePageModel.cs diff --git a/src/MyWebLog/Features/Posts/MultiplePostModel.cs b/src/MyWebLog.CS/Features/Posts/MultiplePostModel.cs similarity index 100% rename from src/MyWebLog/Features/Posts/MultiplePostModel.cs rename to src/MyWebLog.CS/Features/Posts/MultiplePostModel.cs diff --git a/src/MyWebLog/Features/Posts/PostController.cs b/src/MyWebLog.CS/Features/Posts/PostController.cs similarity index 100% rename from src/MyWebLog/Features/Posts/PostController.cs rename to src/MyWebLog.CS/Features/Posts/PostController.cs diff --git a/src/MyWebLog/Features/Shared/MyWebLogController.cs b/src/MyWebLog.CS/Features/Shared/MyWebLogController.cs similarity index 100% rename from src/MyWebLog/Features/Shared/MyWebLogController.cs rename to src/MyWebLog.CS/Features/Shared/MyWebLogController.cs diff --git a/src/MyWebLog/Features/Shared/MyWebLogModel.cs b/src/MyWebLog.CS/Features/Shared/MyWebLogModel.cs similarity index 100% rename from src/MyWebLog/Features/Shared/MyWebLogModel.cs rename to src/MyWebLog.CS/Features/Shared/MyWebLogModel.cs diff --git a/src/MyWebLog/Features/Shared/TagHelpers/ImageTagHelper.cs b/src/MyWebLog.CS/Features/Shared/TagHelpers/ImageTagHelper.cs similarity index 100% rename from src/MyWebLog/Features/Shared/TagHelpers/ImageTagHelper.cs rename to src/MyWebLog.CS/Features/Shared/TagHelpers/ImageTagHelper.cs diff --git a/src/MyWebLog/Features/Shared/TagHelpers/LinkTagHelper.cs b/src/MyWebLog.CS/Features/Shared/TagHelpers/LinkTagHelper.cs similarity index 100% rename from src/MyWebLog/Features/Shared/TagHelpers/LinkTagHelper.cs rename to src/MyWebLog.CS/Features/Shared/TagHelpers/LinkTagHelper.cs diff --git a/src/MyWebLog/Features/Shared/TagHelpers/YesNoTagHelper.cs b/src/MyWebLog.CS/Features/Shared/TagHelpers/YesNoTagHelper.cs similarity index 100% rename from src/MyWebLog/Features/Shared/TagHelpers/YesNoTagHelper.cs rename to src/MyWebLog.CS/Features/Shared/TagHelpers/YesNoTagHelper.cs diff --git a/src/MyWebLog/Features/Shared/_AdminLayout.cshtml b/src/MyWebLog.CS/Features/Shared/_AdminLayout.cshtml similarity index 100% rename from src/MyWebLog/Features/Shared/_AdminLayout.cshtml rename to src/MyWebLog.CS/Features/Shared/_AdminLayout.cshtml diff --git a/src/MyWebLog/Features/Shared/_LogOnOffPartial.cshtml b/src/MyWebLog.CS/Features/Shared/_LogOnOffPartial.cshtml similarity index 100% rename from src/MyWebLog/Features/Shared/_LogOnOffPartial.cshtml rename to src/MyWebLog.CS/Features/Shared/_LogOnOffPartial.cshtml diff --git a/src/MyWebLog/Features/ThemeSupport.cs b/src/MyWebLog.CS/Features/ThemeSupport.cs similarity index 100% rename from src/MyWebLog/Features/ThemeSupport.cs rename to src/MyWebLog.CS/Features/ThemeSupport.cs diff --git a/src/MyWebLog/Features/Users/LogOn.cshtml b/src/MyWebLog.CS/Features/Users/LogOn.cshtml similarity index 100% rename from src/MyWebLog/Features/Users/LogOn.cshtml rename to src/MyWebLog.CS/Features/Users/LogOn.cshtml diff --git a/src/MyWebLog/Features/Users/LogOnModel.cs b/src/MyWebLog.CS/Features/Users/LogOnModel.cs similarity index 100% rename from src/MyWebLog/Features/Users/LogOnModel.cs rename to src/MyWebLog.CS/Features/Users/LogOnModel.cs diff --git a/src/MyWebLog/Features/Users/UserController.cs b/src/MyWebLog.CS/Features/Users/UserController.cs similarity index 100% rename from src/MyWebLog/Features/Users/UserController.cs rename to src/MyWebLog.CS/Features/Users/UserController.cs diff --git a/src/MyWebLog/Features/_ViewImports.cshtml b/src/MyWebLog.CS/Features/_ViewImports.cshtml similarity index 100% rename from src/MyWebLog/Features/_ViewImports.cshtml rename to src/MyWebLog.CS/Features/_ViewImports.cshtml diff --git a/src/MyWebLog/GlobalUsings.cs b/src/MyWebLog.CS/GlobalUsings.cs similarity index 100% rename from src/MyWebLog/GlobalUsings.cs rename to src/MyWebLog.CS/GlobalUsings.cs diff --git a/src/MyWebLog/MyWebLog.csproj b/src/MyWebLog.CS/MyWebLog.CS.csproj similarity index 100% rename from src/MyWebLog/MyWebLog.csproj rename to src/MyWebLog.CS/MyWebLog.CS.csproj diff --git a/src/MyWebLog/Program.cs b/src/MyWebLog.CS/Program.cs similarity index 100% rename from src/MyWebLog/Program.cs rename to src/MyWebLog.CS/Program.cs diff --git a/src/MyWebLog/Properties/Resources.Designer.cs b/src/MyWebLog.CS/Properties/Resources.Designer.cs similarity index 100% rename from src/MyWebLog/Properties/Resources.Designer.cs rename to src/MyWebLog.CS/Properties/Resources.Designer.cs diff --git a/src/MyWebLog.FS/Resources.resx b/src/MyWebLog.CS/Properties/Resources.resx similarity index 100% rename from src/MyWebLog.FS/Resources.resx rename to src/MyWebLog.CS/Properties/Resources.resx diff --git a/src/MyWebLog/Properties/launchSettings.json b/src/MyWebLog.CS/Properties/launchSettings.json similarity index 100% rename from src/MyWebLog/Properties/launchSettings.json rename to src/MyWebLog.CS/Properties/launchSettings.json diff --git a/src/MyWebLog/Themes/Default/Shared/_DefaultFooter.cshtml b/src/MyWebLog.CS/Themes/Default/Shared/_DefaultFooter.cshtml similarity index 100% rename from src/MyWebLog/Themes/Default/Shared/_DefaultFooter.cshtml rename to src/MyWebLog.CS/Themes/Default/Shared/_DefaultFooter.cshtml diff --git a/src/MyWebLog/Themes/Default/Shared/_DefaultHeader.cshtml b/src/MyWebLog.CS/Themes/Default/Shared/_DefaultHeader.cshtml similarity index 100% rename from src/MyWebLog/Themes/Default/Shared/_DefaultHeader.cshtml rename to src/MyWebLog.CS/Themes/Default/Shared/_DefaultHeader.cshtml diff --git a/src/MyWebLog/Themes/Default/Shared/_Layout.cshtml b/src/MyWebLog.CS/Themes/Default/Shared/_Layout.cshtml similarity index 100% rename from src/MyWebLog/Themes/Default/Shared/_Layout.cshtml rename to src/MyWebLog.CS/Themes/Default/Shared/_Layout.cshtml diff --git a/src/MyWebLog/Themes/Default/SinglePage.cshtml b/src/MyWebLog.CS/Themes/Default/SinglePage.cshtml similarity index 100% rename from src/MyWebLog/Themes/Default/SinglePage.cshtml rename to src/MyWebLog.CS/Themes/Default/SinglePage.cshtml diff --git a/src/MyWebLog/Themes/_ViewImports.cshtml b/src/MyWebLog.CS/Themes/_ViewImports.cshtml similarity index 100% rename from src/MyWebLog/Themes/_ViewImports.cshtml rename to src/MyWebLog.CS/Themes/_ViewImports.cshtml diff --git a/src/MyWebLog/WebLogMiddleware.cs b/src/MyWebLog.CS/WebLogMiddleware.cs similarity index 100% rename from src/MyWebLog/WebLogMiddleware.cs rename to src/MyWebLog.CS/WebLogMiddleware.cs diff --git a/src/MyWebLog.FS/appsettings.Development.json b/src/MyWebLog.CS/appsettings.Development.json similarity index 100% rename from src/MyWebLog.FS/appsettings.Development.json rename to src/MyWebLog.CS/appsettings.Development.json diff --git a/src/MyWebLog.FS/appsettings.json b/src/MyWebLog.CS/appsettings.json similarity index 100% rename from src/MyWebLog.FS/appsettings.json rename to src/MyWebLog.CS/appsettings.json diff --git a/src/MyWebLog/wwwroot/css/admin.css b/src/MyWebLog.CS/wwwroot/css/admin.css similarity index 100% rename from src/MyWebLog/wwwroot/css/admin.css rename to src/MyWebLog.CS/wwwroot/css/admin.css diff --git a/src/MyWebLog/wwwroot/img/logo-dark.png b/src/MyWebLog.CS/wwwroot/img/logo-dark.png similarity index 100% rename from src/MyWebLog/wwwroot/img/logo-dark.png rename to src/MyWebLog.CS/wwwroot/img/logo-dark.png diff --git a/src/MyWebLog/wwwroot/img/logo-light.png b/src/MyWebLog.CS/wwwroot/img/logo-light.png similarity index 100% rename from src/MyWebLog/wwwroot/img/logo-light.png rename to src/MyWebLog.CS/wwwroot/img/logo-light.png diff --git a/src/MyWebLog.Data/Converters.fs b/src/MyWebLog.Data/Converters.fs index 803c955..0542f49 100644 --- a/src/MyWebLog.Data/Converters.fs +++ b/src/MyWebLog.Data/Converters.fs @@ -60,13 +60,14 @@ open Microsoft.FSharpLu.Json /// All converters to use for data conversion let all () : JsonConverter seq = seq { - CategoryIdConverter () - CommentIdConverter () - PermalinkConverter () - PageIdConverter () - PostIdConverter () - WebLogIdConverter () - WebLogUserIdConverter () + // Our converters + CategoryIdConverter () + CommentIdConverter () + PermalinkConverter () + PageIdConverter () + PostIdConverter () + WebLogIdConverter () + WebLogUserIdConverter () // Handles DUs with no associated data, as well as option fields CompactUnionJsonConverter () } diff --git a/src/MyWebLog.Data/Data.fs b/src/MyWebLog.Data/Data.fs index a9f3a9c..b2b734a 100644 --- a/src/MyWebLog.Data/Data.fs +++ b/src/MyWebLog.Data/Data.fs @@ -43,11 +43,19 @@ module Helpers = fun conn -> task { match! f conn with Some it when (prop it) = webLogId -> return Some it | _ -> return None } + + /// Get the first item from a list, or None if the list is empty + let tryFirst<'T> (f : IConnection -> Task<'T list>) = + fun conn -> task { + let! results = f conn + return results |> List.tryHead + } open RethinkDb.Driver.FSharp open Microsoft.Extensions.Logging +/// Start up checks to ensure the database, tables, and indexes exist module Startup = /// Ensure field indexes exist, as well as special indexes for selected tables @@ -151,6 +159,16 @@ module Category = /// Functions to manipulate pages module Page = + /// Add a new page + let add (page : Page) = + rethink { + withTable Table.Page + insert page + write + withRetryDefault + ignoreResult + } + /// Count all pages for a web log let countAll (webLogId : WebLogId) = rethink { @@ -195,14 +213,15 @@ module Page = /// Find a page by its permalink let findByPermalink (permalink : Permalink) (webLogId : WebLogId) = - rethink { + rethink { withTable Table.Page getAll [ r.Array (webLogId, permalink) ] (nameof permalink) without [ "priorPermalinks", "revisions" ] limit 1 - resultOption + result withRetryDefault } + |> tryFirst /// Find a page by its ID (including permalinks and revisions) let findByFullId (pageId : PageId) webLogId = @@ -243,14 +262,15 @@ module Post = /// Find a post by its permalink let findByPermalink (permalink : Permalink) (webLogId : WebLogId) = - rethink { + rethink { withTable Table.Post getAll [ r.Array(permalink, webLogId) ] (nameof permalink) without [ "priorPermalinks", "revisions" ] limit 1 - resultOption + result withRetryDefault } + |> tryFirst /// Find posts to be displayed on a page let findPageOfPublishedPosts (webLogId : WebLogId) pageNbr postsPerPage = @@ -270,15 +290,26 @@ module Post = /// Functions to manipulate web logs module WebLog = + /// Add a web log + let add (webLog : WebLog) = + rethink { + withTable Table.WebLog + insert webLog + write + withRetryOnce + ignoreResult + } + /// Retrieve web log details by the URL base let findByHost (url : string) = - rethink { + rethink { withTable Table.WebLog getAll [ url ] "urlBase" limit 1 - resultOption + result withRetryDefault } + |> tryFirst /// Update web log settings let updateSettings (webLog : WebLog) = @@ -296,3 +327,18 @@ module WebLog = withRetryDefault ignoreResult } + + +/// Functions to manipulate web log users +module WebLogUser = + + /// Add a web log user + let add (user : WebLogUser) = + rethink { + withTable Table.WebLogUser + insert user + write + withRetryDefault + ignoreResult + } + \ No newline at end of file diff --git a/src/MyWebLog.Domain/DataTypes.fs b/src/MyWebLog.Domain/DataTypes.fs index d840820..d430749 100644 --- a/src/MyWebLog.Domain/DataTypes.fs +++ b/src/MyWebLog.Domain/DataTypes.fs @@ -248,7 +248,7 @@ module WebLog = subtitle = None defaultPage = "" postsPerPage = 10 - themePath = "Default" + themePath = "default" urlBase = "" timeZone = "" } diff --git a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj index 409e3bc..de029e7 100644 --- a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj +++ b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj @@ -8,6 +8,7 @@ + diff --git a/src/MyWebLog.Domain/SupportTypes.fs b/src/MyWebLog.Domain/SupportTypes.fs index fa0a1af..f955bf1 100644 --- a/src/MyWebLog.Domain/SupportTypes.fs +++ b/src/MyWebLog.Domain/SupportTypes.fs @@ -9,7 +9,7 @@ module private Helpers = /// Create a new ID (short GUID) // https://www.madskristensen.net/blog/A-shorter-and-URL-friendly-GUID let newId() = - Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-')[..22] + Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-').Substring (0, 22) /// An identifier for a category diff --git a/src/MyWebLog.Domain/ViewModels.fs b/src/MyWebLog.Domain/ViewModels.fs new file mode 100644 index 0000000..3d421f0 --- /dev/null +++ b/src/MyWebLog.Domain/ViewModels.fs @@ -0,0 +1,32 @@ +namespace MyWebLog.ViewModels + +open MyWebLog + +/// Base model class for myWebLog views +type MyWebLogModel (webLog : WebLog) = + + /// The details for the web log + member val WebLog = webLog with get + + +/// The model to use to allow a user to log on +[] +type LogOnModel = + { /// The user's e-mail address + emailAddress : string + + /// The user's password + password : string + } + + +/// The model used to render a single page +type SinglePageModel = + { /// The page to be rendered + page : Page + + /// The web log to which the page belongs + webLog : WebLog + } + /// Is this the home page? + member this.isHome with get () = PageId.toString this.page.id = this.webLog.defaultPage diff --git a/src/MyWebLog.FS/Features/Admin/AdminController.fs b/src/MyWebLog.FS.Old/Features/Admin/AdminController.fs similarity index 97% rename from src/MyWebLog.FS/Features/Admin/AdminController.fs rename to src/MyWebLog.FS.Old/Features/Admin/AdminController.fs index 32898f0..be3bdfb 100644 --- a/src/MyWebLog.FS/Features/Admin/AdminController.fs +++ b/src/MyWebLog.FS.Old/Features/Admin/AdminController.fs @@ -20,7 +20,6 @@ type AdminController () = let! posts = Data.Post.countByStatus Published |> getCount let! drafts = Data.Post.countByStatus Draft |> getCount let! pages = Data.Page.countAll |> getCount - let! pages = Data.Page.countAll |> getCount let! listed = Data.Page.countListed |> getCount let! cats = Data.Category.countAll |> getCount let! topCats = Data.Category.countTopLevel |> getCount diff --git a/src/MyWebLog.FS/Features/Admin/AdminTypes.fs b/src/MyWebLog.FS.Old/Features/Admin/AdminTypes.fs similarity index 100% rename from src/MyWebLog.FS/Features/Admin/AdminTypes.fs rename to src/MyWebLog.FS.Old/Features/Admin/AdminTypes.fs diff --git a/src/MyWebLog/Features/Admin/Index.cshtml b/src/MyWebLog.FS.Old/Features/Admin/Index.cshtml similarity index 100% rename from src/MyWebLog/Features/Admin/Index.cshtml rename to src/MyWebLog.FS.Old/Features/Admin/Index.cshtml diff --git a/src/MyWebLog.FS/Features/Pages/PageTypes.fs b/src/MyWebLog.FS.Old/Features/Pages/PageTypes.fs similarity index 100% rename from src/MyWebLog.FS/Features/Pages/PageTypes.fs rename to src/MyWebLog.FS.Old/Features/Pages/PageTypes.fs diff --git a/src/MyWebLog.FS/Features/Posts/PostController.fs b/src/MyWebLog.FS.Old/Features/Posts/PostController.fs similarity index 100% rename from src/MyWebLog.FS/Features/Posts/PostController.fs rename to src/MyWebLog.FS.Old/Features/Posts/PostController.fs diff --git a/src/MyWebLog.FS/Features/Posts/PostTypes.fs b/src/MyWebLog.FS.Old/Features/Posts/PostTypes.fs similarity index 100% rename from src/MyWebLog.FS/Features/Posts/PostTypes.fs rename to src/MyWebLog.FS.Old/Features/Posts/PostTypes.fs diff --git a/src/MyWebLog.FS/Features/Shared/SharedTypes.fs b/src/MyWebLog.FS.Old/Features/Shared/SharedTypes.fs similarity index 100% rename from src/MyWebLog.FS/Features/Shared/SharedTypes.fs rename to src/MyWebLog.FS.Old/Features/Shared/SharedTypes.fs diff --git a/src/MyWebLog.FS.Old/Handlers.fs b/src/MyWebLog.FS.Old/Handlers.fs new file mode 100644 index 0000000..24e4bf5 --- /dev/null +++ b/src/MyWebLog.FS.Old/Handlers.fs @@ -0,0 +1,2 @@ +module MyWebLog.Handlers + diff --git a/src/MyWebLog.FS/MyWebLog.FS.fsproj b/src/MyWebLog.FS.Old/MyWebLog.FS.Old.fsproj similarity index 96% rename from src/MyWebLog.FS/MyWebLog.FS.fsproj rename to src/MyWebLog.FS.Old/MyWebLog.FS.Old.fsproj index d809981..f2687b2 100644 --- a/src/MyWebLog.FS/MyWebLog.FS.fsproj +++ b/src/MyWebLog.FS.Old/MyWebLog.FS.Old.fsproj @@ -5,6 +5,7 @@ + diff --git a/src/MyWebLog.FS/Program.fs b/src/MyWebLog.FS.Old/Program.fs similarity index 100% rename from src/MyWebLog.FS/Program.fs rename to src/MyWebLog.FS.Old/Program.fs diff --git a/src/MyWebLog.FS/Properties/launchSettings.json b/src/MyWebLog.FS.Old/Properties/launchSettings.json similarity index 100% rename from src/MyWebLog.FS/Properties/launchSettings.json rename to src/MyWebLog.FS.Old/Properties/launchSettings.json diff --git a/src/MyWebLog/Properties/Resources.resx b/src/MyWebLog.FS.Old/Resources.resx similarity index 100% rename from src/MyWebLog/Properties/Resources.resx rename to src/MyWebLog.FS.Old/Resources.resx diff --git a/src/MyWebLog.FS/WebLogCache.fs b/src/MyWebLog.FS.Old/WebLogCache.fs similarity index 100% rename from src/MyWebLog.FS/WebLogCache.fs rename to src/MyWebLog.FS.Old/WebLogCache.fs diff --git a/src/MyWebLog/appsettings.Development.json b/src/MyWebLog.FS.Old/appsettings.Development.json similarity index 100% rename from src/MyWebLog/appsettings.Development.json rename to src/MyWebLog.FS.Old/appsettings.Development.json diff --git a/src/MyWebLog.FS.Old/appsettings.json b/src/MyWebLog.FS.Old/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/src/MyWebLog.FS.Old/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/MyWebLog.Themes.BitBadger/MyWebLog.Themes.BitBadger.csproj b/src/MyWebLog.Themes.BitBadger/MyWebLog.Themes.BitBadger.csproj index 617ddca..0fc96fe 100644 --- a/src/MyWebLog.Themes.BitBadger/MyWebLog.Themes.BitBadger.csproj +++ b/src/MyWebLog.Themes.BitBadger/MyWebLog.Themes.BitBadger.csproj @@ -20,13 +20,6 @@ - - - false - runtime - - - diff --git a/src/MyWebLog.sln b/src/MyWebLog.sln index cef5a9c..d3d3242 100644 --- a/src/MyWebLog.sln +++ b/src/MyWebLog.sln @@ -3,17 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWebLog", "MyWebLog\MyWebLog.csproj", "{3139DA09-C999-465A-BC98-02FEC3BD7E88}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWebLog.Themes.BitBadger", "MyWebLog.Themes.BitBadger\MyWebLog.Themes.BitBadger.csproj", "{729F7AB3-2300-4390-B972-71D32FBBBF50}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MyWebLog.FS", "MyWebLog.FS\MyWebLog.FS.fsproj", "{4D62F235-73BA-42A6-8AA1-29D0D046E115}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyWebLog.Domain", "MyWebLog.Domain\MyWebLog.Domain.fsproj", "{8CA99122-888A-4524-8C1B-685F0A4B7B4B}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MyWebLog.Domain", "MyWebLog.Domain\MyWebLog.Domain.fsproj", "{8CA99122-888A-4524-8C1B-685F0A4B7B4B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWebLog.DataCS", "MyWebLog.DataCS\MyWebLog.DataCS.csproj", "{C9129BED-E4AE-41BB-BDB2-5418B7F924CC}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyWebLog.Data", "MyWebLog.Data\MyWebLog.Data.fsproj", "{D284584D-2CB2-40C8-B605-6D0FD84D9D3D}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MyWebLog.Data", "MyWebLog.Data\MyWebLog.Data.fsproj", "{D284584D-2CB2-40C8-B605-6D0FD84D9D3D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWebLog.CS", "MyWebLog.CS\MyWebLog.CS.csproj", "{B23A8093-28B1-4CB5-93F1-B4659516B74F}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MyWebLog.FS.Old", "MyWebLog.FS.Old\MyWebLog.FS.Old.fsproj", "{C0AD7194-572E-4112-87C4-5235987C90C1}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyWebLog", "MyWebLog\MyWebLog.fsproj", "{5655B63D-429F-4CCD-A14C-FBD74D987ECB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,18 +23,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3139DA09-C999-465A-BC98-02FEC3BD7E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3139DA09-C999-465A-BC98-02FEC3BD7E88}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3139DA09-C999-465A-BC98-02FEC3BD7E88}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3139DA09-C999-465A-BC98-02FEC3BD7E88}.Release|Any CPU.Build.0 = Release|Any CPU {729F7AB3-2300-4390-B972-71D32FBBBF50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {729F7AB3-2300-4390-B972-71D32FBBBF50}.Debug|Any CPU.Build.0 = Debug|Any CPU {729F7AB3-2300-4390-B972-71D32FBBBF50}.Release|Any CPU.ActiveCfg = Release|Any CPU {729F7AB3-2300-4390-B972-71D32FBBBF50}.Release|Any CPU.Build.0 = Release|Any CPU - {4D62F235-73BA-42A6-8AA1-29D0D046E115}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D62F235-73BA-42A6-8AA1-29D0D046E115}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D62F235-73BA-42A6-8AA1-29D0D046E115}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D62F235-73BA-42A6-8AA1-29D0D046E115}.Release|Any CPU.Build.0 = Release|Any CPU {8CA99122-888A-4524-8C1B-685F0A4B7B4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CA99122-888A-4524-8C1B-685F0A4B7B4B}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CA99122-888A-4524-8C1B-685F0A4B7B4B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -45,6 +39,18 @@ Global {D284584D-2CB2-40C8-B605-6D0FD84D9D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU {D284584D-2CB2-40C8-B605-6D0FD84D9D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU {D284584D-2CB2-40C8-B605-6D0FD84D9D3D}.Release|Any CPU.Build.0 = Release|Any CPU + {B23A8093-28B1-4CB5-93F1-B4659516B74F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B23A8093-28B1-4CB5-93F1-B4659516B74F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B23A8093-28B1-4CB5-93F1-B4659516B74F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B23A8093-28B1-4CB5-93F1-B4659516B74F}.Release|Any CPU.Build.0 = Release|Any CPU + {C0AD7194-572E-4112-87C4-5235987C90C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0AD7194-572E-4112-87C4-5235987C90C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0AD7194-572E-4112-87C4-5235987C90C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0AD7194-572E-4112-87C4-5235987C90C1}.Release|Any CPU.Build.0 = Release|Any CPU + {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/MyWebLog/Handlers.fs b/src/MyWebLog/Handlers.fs new file mode 100644 index 0000000..262e2b7 --- /dev/null +++ b/src/MyWebLog/Handlers.fs @@ -0,0 +1,59 @@ +[] +module MyWebLog.Handlers + +open Giraffe +open MyWebLog +open MyWebLog.ViewModels +open System + +[] +module private Helpers = + + open DotLiquid + open System.Collections.Concurrent + open System.IO + + /// Cache for parsed templates + let private themeViews = ConcurrentDictionary () + + /// Return a view for a theme + let themedView<'T> (template : string) (model : obj) : HttpHandler = fun next ctx -> task { + let webLog = WebLogCache.getByCtx ctx + let templatePath = $"themes/{webLog.themePath}/{template}" + match themeViews.ContainsKey templatePath with + | true -> () + | false -> + let! file = File.ReadAllTextAsync $"{templatePath}.liquid" + themeViews[templatePath] <- Template.Parse file + let view = themeViews[templatePath].Render (Hash.FromAnonymousObject model) + return! htmlString view next ctx + } + +module User = + + open System.Security.Cryptography + open System.Text + + /// Hash a password for a given user + let hashedPassword (plainText : string) (email : string) (salt : Guid) = + let allSalt = Array.concat [ salt.ToByteArray(); (Encoding.UTF8.GetBytes email) ] + use alg = new Rfc2898DeriveBytes (plainText, allSalt, 2_048) + Convert.ToBase64String(alg.GetBytes(64)) + + +module CatchAll = + + let catchAll : HttpHandler = fun next ctx -> task { + let testPage = { Page.empty with text = "Howdy, folks!" } + return! themedView "single-page" { page = testPage; webLog = WebLogCache.getByCtx ctx } next ctx + } + +open Giraffe.EndpointRouting + +/// The endpoints defined in the above handlers +let endpoints = [ + GET [ + route "" CatchAll.catchAll + ] +] + \ No newline at end of file diff --git a/src/MyWebLog/MyWebLog.fsproj b/src/MyWebLog/MyWebLog.fsproj new file mode 100644 index 0000000..8344369 --- /dev/null +++ b/src/MyWebLog/MyWebLog.fsproj @@ -0,0 +1,32 @@ + + + + Exe + net6.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MyWebLog/Program.fs b/src/MyWebLog/Program.fs new file mode 100644 index 0000000..6f89575 --- /dev/null +++ b/src/MyWebLog/Program.fs @@ -0,0 +1,150 @@ +open Giraffe.EndpointRouting +open Microsoft.AspNetCore.Authentication.Cookies +open Microsoft.AspNetCore.Builder +open Microsoft.AspNetCore.Http +open Microsoft.Extensions.Configuration +open Microsoft.Extensions.Hosting +open Microsoft.Extensions.DependencyInjection +open Microsoft.Extensions.Logging +open MyWebLog +open RethinkDb.Driver.FSharp +open RethinkDb.Driver.Net +open System + +/// Middleware to derive the current web log +type WebLogMiddleware (next : RequestDelegate) = + + member this.InvokeAsync (ctx : HttpContext) = task { + let host = ctx.Request.Host.ToUriComponent () + match WebLogCache.exists host with + | true -> return! next.Invoke ctx + | false -> + let conn = ctx.RequestServices.GetRequiredService () + match! Data.WebLog.findByHost host conn with + | Some webLog -> + WebLogCache.set host webLog + return! next.Invoke ctx + | None -> ctx.Response.StatusCode <- 404 + } + + +/// Initialize a new database +let initDbValidated (args : string[]) (sp : IServiceProvider) = task { + + let conn = sp.GetRequiredService () + + let timeZone = + let local = TimeZoneInfo.Local.Id + match TimeZoneInfo.Local.HasIanaId with + | true -> local + | false -> + match TimeZoneInfo.TryConvertWindowsIdToIanaId local with + | true, ianaId -> ianaId + | false, _ -> raise <| TimeZoneNotFoundException $"Cannot find IANA timezone for {local}" + + // Create the web log + let webLogId = WebLogId.create () + let userId = WebLogUserId.create () + let homePageId = PageId.create () + + do! Data.WebLog.add + { WebLog.empty with + id = webLogId + name = args[2] + urlBase = args[1] + defaultPage = PageId.toString homePageId + timeZone = timeZone + } conn + + // Create the admin user + let salt = Guid.NewGuid () + + do! Data.WebLogUser.add + { WebLogUser.empty with + id = userId + webLogId = webLogId + userName = args[3] + firstName = "Admin" + lastName = "User" + preferredName = "Admin" + passwordHash = Handlers.User.hashedPassword args[4] args[3] salt + salt = salt + authorizationLevel = Administrator + } conn + + // Create the default home page + do! Data.Page.add + { Page.empty with + id = homePageId + webLogId = webLogId + authorId = userId + title = "Welcome to myWebLog!" + permalink = Permalink "welcome-to-myweblog.html" + publishedOn = DateTime.UtcNow + updatedOn = DateTime.UtcNow + text = "

This is your default home page.

" + revisions = [ + { asOf = DateTime.UtcNow + sourceType = Html + text = "

This is your default home page.

" + } + ] + } conn + + Console.WriteLine($"Successfully initialized database for {args[2]} with URL base {args[1]}"); +} + +/// Initialize a new database +let initDb args sp = task { + match args |> Array.length with + | 5 -> return! initDbValidated args sp + | _ -> + Console.WriteLine "Usage: MyWebLog init [url] [name] [admin-email] [admin-pw]" + return! System.Threading.Tasks.Task.CompletedTask +} + + +[] +let main args = + + let builder = WebApplication.CreateBuilder(args) + let _ = + builder.Services + .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(fun opts -> + opts.ExpireTimeSpan <- TimeSpan.FromMinutes 20. + opts.SlidingExpiration <- true + opts.AccessDeniedPath <- "/forbidden") + let _ = builder.Services.AddLogging () + let _ = builder.Services.AddAuthorization() + + // Configure RethinkDB's connection + JsonConverters.all () |> Seq.iter Converter.Serializer.Converters.Add + let sp = builder.Services.BuildServiceProvider () + let config = sp.GetRequiredService () + let loggerFac = sp.GetRequiredService () + let rethinkCfg = DataConfig.FromConfiguration (config.GetSection "RethinkDB") + let conn = + task { + let! conn = rethinkCfg.CreateConnectionAsync () + do! Data.Startup.ensureDb rethinkCfg (loggerFac.CreateLogger (nameof Data.Startup)) conn + return conn + } |> Async.AwaitTask |> Async.RunSynchronously + let _ = builder.Services.AddSingleton conn + + let app = builder.Build () + + match args |> Array.tryHead with + | Some it when it = "init" -> initDb args app.Services |> Async.AwaitTask |> Async.RunSynchronously + | _ -> + let _ = app.UseCookiePolicy (CookiePolicyOptions (MinimumSameSitePolicy = SameSiteMode.Strict)) + let _ = app.UseMiddleware () + let _ = app.UseAuthentication () + let _ = app.UseStaticFiles () + let _ = app.UseRouting () + let _ = app.UseEndpoints (fun endpoints -> endpoints.MapGiraffeEndpoints Handlers.endpoints) + + app.Run() + + 0 // Exit code + diff --git a/src/MyWebLog/WebLogCache.fs b/src/MyWebLog/WebLogCache.fs new file mode 100644 index 0000000..8c03d21 --- /dev/null +++ b/src/MyWebLog/WebLogCache.fs @@ -0,0 +1,24 @@ +/// +/// In-memory cache of web log details +/// +/// This is filled by the middleware via the first request for each host, and can be updated via the web log +/// settings update page +module MyWebLog.WebLogCache + +open Microsoft.AspNetCore.Http +open System.Collections.Concurrent + +/// The cache of web log details +let private _cache = ConcurrentDictionary () + +/// Does a host exist in the cache? +let exists host = _cache.ContainsKey host + +/// Get the details for a web log via its host +let get host = _cache[host] + +/// Get the details for a web log via its host +let getByCtx (ctx : HttpContext) = _cache[ctx.Request.Host.ToUriComponent ()] + +/// Set the details for a particular host +let set host details = _cache[host] <- details diff --git a/src/MyWebLog/appsettings.json b/src/MyWebLog/appsettings.json index 10f68b8..faf242d 100644 --- a/src/MyWebLog/appsettings.json +++ b/src/MyWebLog/appsettings.json @@ -1,9 +1,6 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" +{ + "RethinkDB": { + "hostname": "data02.bitbadger.solutions", + "database": "myWebLog-dev" + } } diff --git a/src/MyWebLog/themes/default/_html-head.liquid b/src/MyWebLog/themes/default/_html-head.liquid new file mode 100644 index 0000000..68400c0 --- /dev/null +++ b/src/MyWebLog/themes/default/_html-head.liquid @@ -0,0 +1,11 @@ + + + + + + + + + {{ title | escape }} « {{ web_log_name | escape }} + diff --git a/src/MyWebLog/themes/default/_page-foot.liquid b/src/MyWebLog/themes/default/_page-foot.liquid new file mode 100644 index 0000000..f96fc6f --- /dev/null +++ b/src/MyWebLog/themes/default/_page-foot.liquid @@ -0,0 +1,6 @@ +
+
+
+ myWebLog +
+
diff --git a/src/MyWebLog/themes/default/_page-head.liquid b/src/MyWebLog/themes/default/_page-head.liquid new file mode 100644 index 0000000..7a3ebcd --- /dev/null +++ b/src/MyWebLog/themes/default/_page-head.liquid @@ -0,0 +1,18 @@ +
+ +
diff --git a/src/MyWebLog/themes/default/single-page.liquid b/src/MyWebLog/themes/default/single-page.liquid new file mode 100644 index 0000000..9b6f6a4 --- /dev/null +++ b/src/MyWebLog/themes/default/single-page.liquid @@ -0,0 +1,14 @@ + + + {{ render "_html-head", title: title, web_log_name: web_log.name }} + + {{ render "_page-head", web_log: web_log }} +
+

{{ page.title }}

+
+ {{ page.text }} +
+
+ {{ render "_page-foot" }} + + diff --git a/src/MyWebLog/wwwroot/admin/admin.css b/src/MyWebLog/wwwroot/admin/admin.css new file mode 100644 index 0000000..f720fda --- /dev/null +++ b/src/MyWebLog/wwwroot/admin/admin.css @@ -0,0 +1,5 @@ +footer { + background-color: #808080; + border-top: solid 1px black; + color: white; +}