IT LIVES! (on dotnet core)
Commented out RSS feed stuff dependent on SyndicationFeed; revamped bootstrapper to make everything work in the proper order; qualified resource name in Resources project
This commit is contained in:
parent
1c3e84f5ec
commit
3f9665a2e6
@ -18,7 +18,7 @@ open Nancy.Owin
|
|||||||
open Nancy.Security
|
open Nancy.Security
|
||||||
open Nancy.Session.Persistable
|
open Nancy.Session.Persistable
|
||||||
//open Nancy.Session.Relational
|
//open Nancy.Session.Relational
|
||||||
open Nancy.Session.RethinkDb
|
open Nancy.Session.RethinkDB
|
||||||
open Nancy.TinyIoc
|
open Nancy.TinyIoc
|
||||||
open Nancy.ViewEngines.SuperSimpleViewEngine
|
open Nancy.ViewEngines.SuperSimpleViewEngine
|
||||||
open NodaTime
|
open NodaTime
|
||||||
@ -26,16 +26,14 @@ open RethinkDb.Driver.Net
|
|||||||
open System
|
open System
|
||||||
open System.IO
|
open System.IO
|
||||||
open System.Reflection
|
open System.Reflection
|
||||||
|
open System.Security.Claims
|
||||||
open System.Text.RegularExpressions
|
open System.Text.RegularExpressions
|
||||||
|
|
||||||
/// Establish the configuration for this instance
|
/// Establish the configuration for this instance
|
||||||
let cfg = try AppConfig.FromJson (System.IO.File.ReadAllText "config.json")
|
let cfg = try AppConfig.FromJson (System.IO.File.ReadAllText "config.json")
|
||||||
with ex -> raise <| Exception (Strings.get "ErrBadAppConfig", ex)
|
with ex -> raise <| Exception (Strings.get "ErrBadAppConfig", ex)
|
||||||
|
|
||||||
let data : IMyWebLogData = upcast RethinkMyWebLogData(cfg.DataConfig.Conn, cfg.DataConfig)
|
let data = lazy (RethinkMyWebLogData(cfg.DataConfig.Conn, cfg.DataConfig) :> IMyWebLogData)
|
||||||
|
|
||||||
do
|
|
||||||
data.SetUp ()
|
|
||||||
|
|
||||||
/// Support RESX lookup via the @Translate SSVE alias
|
/// Support RESX lookup via the @Translate SSVE alias
|
||||||
type TranslateTokenViewEngineMatcher() =
|
type TranslateTokenViewEngineMatcher() =
|
||||||
@ -48,7 +46,7 @@ type TranslateTokenViewEngineMatcher() =
|
|||||||
|
|
||||||
/// Handle forms authentication
|
/// Handle forms authentication
|
||||||
type MyWebLogUser(name, claims) =
|
type MyWebLogUser(name, claims) =
|
||||||
interface IUserIdentity with
|
inherit ClaimsPrincipal()
|
||||||
member this.UserName with get() = name
|
member this.UserName with get() = name
|
||||||
member this.Claims with get() = claims
|
member this.Claims with get() = claims
|
||||||
|
|
||||||
@ -85,12 +83,12 @@ type MyWebLogBootstrapper() =
|
|||||||
Directory.EnumerateDirectories (Path.Combine [| "views"; "themes" |])
|
Directory.EnumerateDirectories (Path.Combine [| "views"; "themes" |])
|
||||||
|> Seq.iter addContentDir
|
|> Seq.iter addContentDir
|
||||||
|
|
||||||
override this.ApplicationStartup (container, pipelines) =
|
override this.ConfigureApplicationContainer (container) =
|
||||||
base.ApplicationStartup (container, pipelines)
|
base.ConfigureApplicationContainer container
|
||||||
// Application configuration
|
|
||||||
container.Register<AppConfig>(cfg)
|
container.Register<AppConfig>(cfg)
|
||||||
|> ignore
|
|> ignore
|
||||||
container.Register<IMyWebLogData>(data)
|
data.Force().SetUp ()
|
||||||
|
container.Register<IMyWebLogData>(data.Force ())
|
||||||
|> ignore
|
|> ignore
|
||||||
// NodaTime
|
// NodaTime
|
||||||
container.Register<IClock>(SystemClock.Instance)
|
container.Register<IClock>(SystemClock.Instance)
|
||||||
@ -99,12 +97,15 @@ type MyWebLogBootstrapper() =
|
|||||||
container.Register<seq<ISuperSimpleViewEngineMatcher>>(fun _ _ ->
|
container.Register<seq<ISuperSimpleViewEngineMatcher>>(fun _ _ ->
|
||||||
Seq.singleton (TranslateTokenViewEngineMatcher() :> ISuperSimpleViewEngineMatcher))
|
Seq.singleton (TranslateTokenViewEngineMatcher() :> ISuperSimpleViewEngineMatcher))
|
||||||
|> ignore
|
|> ignore
|
||||||
|
|
||||||
|
override this.ApplicationStartup (container, pipelines) =
|
||||||
|
base.ApplicationStartup (container, pipelines)
|
||||||
// Forms authentication configuration
|
// Forms authentication configuration
|
||||||
let auth =
|
let auth =
|
||||||
FormsAuthenticationConfiguration(
|
FormsAuthenticationConfiguration(
|
||||||
CryptographyConfiguration =
|
CryptographyConfiguration =
|
||||||
CryptographyConfiguration(
|
CryptographyConfiguration(
|
||||||
RijndaelEncryptionProvider(PassphraseKeyGenerator(cfg.AuthEncryptionPassphrase, cfg.AuthSalt)),
|
AesEncryptionProvider(PassphraseKeyGenerator(cfg.AuthEncryptionPassphrase, cfg.AuthSalt)),
|
||||||
DefaultHmacProvider(PassphraseKeyGenerator(cfg.AuthHmacPassphrase, cfg.AuthSalt))),
|
DefaultHmacProvider(PassphraseKeyGenerator(cfg.AuthHmacPassphrase, cfg.AuthSalt))),
|
||||||
RedirectUrl = "~/user/logon",
|
RedirectUrl = "~/user/logon",
|
||||||
UserMapper = container.Resolve<IUserMapper>())
|
UserMapper = container.Resolve<IUserMapper>())
|
||||||
@ -112,12 +113,16 @@ type MyWebLogBootstrapper() =
|
|||||||
// CSRF
|
// CSRF
|
||||||
Csrf.Enable pipelines
|
Csrf.Enable pipelines
|
||||||
// Sessions
|
// Sessions
|
||||||
let sessions = RethinkDbSessionConfiguration(cfg.DataConfig.Conn)
|
let sessions = RethinkDBSessionConfiguration(cfg.DataConfig.Conn)
|
||||||
sessions.Database <- cfg.DataConfig.Database
|
sessions.Database <- cfg.DataConfig.Database
|
||||||
//let sessions = RelationalSessionConfiguration(ConfigurationManager.ConnectionStrings.["SessionStore"].ConnectionString)
|
//let sessions = RelationalSessionConfiguration(ConfigurationManager.ConnectionStrings.["SessionStore"].ConnectionString)
|
||||||
PersistableSessions.Enable (pipelines, sessions)
|
PersistableSessions.Enable (pipelines, sessions)
|
||||||
()
|
()
|
||||||
|
|
||||||
|
override this.Configure (environment) =
|
||||||
|
base.Configure environment
|
||||||
|
environment.Tracing(true, true)
|
||||||
|
|
||||||
|
|
||||||
let version =
|
let version =
|
||||||
let v = typeof<AppConfig>.GetType().GetTypeInfo().Assembly.GetName().Version
|
let v = typeof<AppConfig>.GetType().GetTypeInfo().Assembly.GetName().Version
|
||||||
@ -132,7 +137,7 @@ type RequestEnvironment() =
|
|||||||
member this.Initialize (pipelines, context) =
|
member this.Initialize (pipelines, context) =
|
||||||
let establishEnv (ctx : NancyContext) =
|
let establishEnv (ctx : NancyContext) =
|
||||||
ctx.Items.[Keys.RequestStart] <- DateTime.Now.Ticks
|
ctx.Items.[Keys.RequestStart] <- DateTime.Now.Ticks
|
||||||
match tryFindWebLogByUrlBase data ctx.Request.Url.HostName with
|
match tryFindWebLogByUrlBase (data.Force ()) ctx.Request.Url.HostName with
|
||||||
| Some webLog -> ctx.Items.[Keys.WebLog] <- webLog
|
| Some webLog -> ctx.Items.[Keys.WebLog] <- webLog
|
||||||
| None -> // TODO: redirect to domain set up page
|
| None -> // TODO: redirect to domain set up page
|
||||||
Exception (sprintf "%s %s" ctx.Request.Url.HostName (Strings.get "ErrNotConfigured"))
|
Exception (sprintf "%s %s" ctx.Request.Url.HostName (Strings.get "ErrNotConfigured"))
|
||||||
@ -144,7 +149,9 @@ type RequestEnvironment() =
|
|||||||
|
|
||||||
type Startup() =
|
type Startup() =
|
||||||
member this.Configure (app : IApplicationBuilder) =
|
member this.Configure (app : IApplicationBuilder) =
|
||||||
app.UseOwin(fun x -> x.UseNancy() |> ignore) |> ignore
|
let opt = NancyOptions()
|
||||||
|
opt.Bootstrapper <- new MyWebLogBootstrapper()
|
||||||
|
app.UseOwin(fun x -> x.UseNancy(opt) |> ignore) |> ignore
|
||||||
|
|
||||||
|
|
||||||
let Run () =
|
let Run () =
|
||||||
|
@ -28,7 +28,7 @@ type CategoryModule(data : IMyWebLogData) as this =
|
|||||||
upcast this.View.["/admin/category/list", model]
|
upcast this.View.["/admin/category/list", model]
|
||||||
|
|
||||||
/// Edit a category
|
/// Edit a category
|
||||||
member this.EditCategory (parameters : DynamicDictionary) =
|
member this.EditCategory (parameters : DynamicDictionary) : obj =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let catId = parameters.["id"].ToString ()
|
let catId = parameters.["id"].ToString ()
|
||||||
match (match catId with
|
match (match catId with
|
||||||
@ -42,7 +42,7 @@ type CategoryModule(data : IMyWebLogData) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a category
|
/// Save a category
|
||||||
member this.SaveCategory (parameters : DynamicDictionary) =
|
member this.SaveCategory (parameters : DynamicDictionary) : obj =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let catId = parameters.["id"].ToString ()
|
let catId = parameters.["id"].ToString ()
|
||||||
@ -75,7 +75,7 @@ type CategoryModule(data : IMyWebLogData) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Delete a category
|
/// Delete a category
|
||||||
member this.DeleteCategory (parameters : DynamicDictionary) =
|
member this.DeleteCategory (parameters : DynamicDictionary) : obj =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let catId = parameters.["id"].ToString ()
|
let catId = parameters.["id"].ToString ()
|
||||||
|
@ -4,6 +4,8 @@ module MyWebLog.ModuleExtensions
|
|||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open Nancy
|
open Nancy
|
||||||
open Nancy.Security
|
open Nancy.Security
|
||||||
|
open System
|
||||||
|
open System.Security.Claims
|
||||||
|
|
||||||
/// Parent class for all myWebLog Nancy modules
|
/// Parent class for all myWebLog Nancy modules
|
||||||
type NancyModule with
|
type NancyModule with
|
||||||
@ -27,5 +29,6 @@ type NancyModule with
|
|||||||
|
|
||||||
/// Require a specific level of access for the current web log
|
/// Require a specific level of access for the current web log
|
||||||
member this.RequiresAccessLevel level =
|
member this.RequiresAccessLevel level =
|
||||||
|
let findClaim = new Predicate<Claim>(fun claim -> claim.Type = ClaimTypes.Role && claim.Value = sprintf "%s|%s" this.WebLog.Id level)
|
||||||
this.RequiresAuthentication()
|
this.RequiresAuthentication()
|
||||||
this.RequiresClaims [| sprintf "%s|%s" this.WebLog.Id level |]
|
this.RequiresClaims [| findClaim |]
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
namespace MyWebLog
|
namespace MyWebLog
|
||||||
|
|
||||||
open FSharp.Markdown
|
|
||||||
open MyWebLog.Data
|
open MyWebLog.Data
|
||||||
open MyWebLog.Entities
|
open MyWebLog.Entities
|
||||||
open MyWebLog.Logic.Page
|
open MyWebLog.Logic.Page
|
||||||
@ -22,15 +21,15 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
this.Delete("/page/{id}/delete", fun parms -> this.DeletePage (downcast parms))
|
this.Delete("/page/{id}/delete", fun parms -> this.DeletePage (downcast parms))
|
||||||
|
|
||||||
/// List all pages
|
/// List all pages
|
||||||
member this.PageList () =
|
member this.PageList () : obj =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let model = PagesModel(this.Context, this.WebLog, (findAllPages data this.WebLog.Id
|
let model = PagesModel(this.Context, this.WebLog, (findAllPages data this.WebLog.Id
|
||||||
|> List.map (fun p -> PageForDisplay(this.WebLog, p))))
|
|> List.map (fun p -> PageForDisplay(this.WebLog, p))))
|
||||||
model.PageTitle <- Resources.Pages
|
model.PageTitle <- Strings.get "Pages"
|
||||||
upcast this.View.["admin/page/list", model]
|
upcast this.View.["admin/page/list", model]
|
||||||
|
|
||||||
/// Edit a page
|
/// Edit a page
|
||||||
member this.EditPage (parameters : DynamicDictionary) =
|
member this.EditPage (parameters : DynamicDictionary) : obj =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let pageId = parameters.["id"].ToString ()
|
let pageId = parameters.["id"].ToString ()
|
||||||
match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId
|
match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId
|
||||||
@ -46,12 +45,12 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a page
|
/// Save a page
|
||||||
member this.SavePage (parameters : DynamicDictionary) =
|
member this.SavePage (parameters : DynamicDictionary) : obj =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let pageId = parameters.["id"].ToString ()
|
let pageId = parameters.["id"].ToString ()
|
||||||
let form = this.Bind<EditPageForm> ()
|
let form = this.Bind<EditPageForm> ()
|
||||||
let now = clock.Now.Ticks
|
let now = clock.GetCurrentInstant().ToUnixTimeTicks()
|
||||||
match (match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId) with
|
match (match pageId with "new" -> Some Page.Empty | _ -> tryFindPage data this.WebLog.Id pageId) with
|
||||||
| Some p -> let page = match pageId with "new" -> { p with WebLogId = this.WebLog.Id } | _ -> p
|
| Some p -> let page = match pageId with "new" -> { p with WebLogId = this.WebLog.Id } | _ -> p
|
||||||
let pId = { p with
|
let pId = { p with
|
||||||
@ -60,7 +59,7 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
PublishedOn = match pageId with "new" -> now | _ -> page.PublishedOn
|
PublishedOn = match pageId with "new" -> now | _ -> page.PublishedOn
|
||||||
UpdatedOn = now
|
UpdatedOn = now
|
||||||
Text = match form.Source with
|
Text = match form.Source with
|
||||||
| RevisionSource.Markdown -> Markdown.TransformHtml form.Text
|
| RevisionSource.Markdown -> (* Markdown.TransformHtml *) form.Text
|
||||||
| _ -> form.Text
|
| _ -> form.Text
|
||||||
Revisions = { AsOf = now
|
Revisions = { AsOf = now
|
||||||
SourceType = form.Source
|
SourceType = form.Source
|
||||||
@ -77,7 +76,7 @@ type PageModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Delete a page
|
/// Delete a page
|
||||||
member this.DeletePage (parameters : DynamicDictionary) =
|
member this.DeletePage (parameters : DynamicDictionary) : obj =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let pageId = parameters.["id"].ToString ()
|
let pageId = parameters.["id"].ToString ()
|
||||||
|
@ -13,7 +13,7 @@ open Nancy.Session.Persistable
|
|||||||
open NodaTime
|
open NodaTime
|
||||||
open RethinkDb.Driver.Net
|
open RethinkDb.Driver.Net
|
||||||
open System
|
open System
|
||||||
open System.ServiceModel.Syndication
|
//open System.ServiceModel.Syndication
|
||||||
|
|
||||||
/// Routes dealing with posts (including the home page, /tag, /category, RSS, and catch-all routes)
|
/// Routes dealing with posts (including the home page, /tag, /category, RSS, and catch-all routes)
|
||||||
type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
||||||
@ -28,7 +28,8 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
|
|
||||||
/// Generate an RSS/Atom feed of the latest posts
|
/// Generate an RSS/Atom feed of the latest posts
|
||||||
let generateFeed format : obj =
|
let generateFeed format : obj =
|
||||||
let posts = findFeedPosts data this.WebLog.Id 10
|
this.NotFound ()
|
||||||
|
(* let posts = findFeedPosts data this.WebLog.Id 10
|
||||||
let feed =
|
let feed =
|
||||||
SyndicationFeed(
|
SyndicationFeed(
|
||||||
this.WebLog.Name, defaultArg this.WebLog.Subtitle null,
|
this.WebLog.Name, defaultArg this.WebLog.Subtitle null,
|
||||||
@ -55,7 +56,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
Xml.XmlWriter.Create(stream)
|
Xml.XmlWriter.Create(stream)
|
||||||
|> match format with "atom" -> feed.SaveAsAtom10 | _ -> feed.SaveAsRss20
|
|> match format with "atom" -> feed.SaveAsAtom10 | _ -> feed.SaveAsRss20
|
||||||
stream.Position <- int64 0
|
stream.Position <- int64 0
|
||||||
upcast this.Response.FromStream(stream, sprintf "application/%s+xml" format)
|
upcast this.Response.FromStream(stream, sprintf "application/%s+xml" format) *)
|
||||||
|
|
||||||
do
|
do
|
||||||
this.Get ("/", fun _ -> this.HomePage ())
|
this.Get ("/", fun _ -> this.HomePage ())
|
||||||
@ -74,7 +75,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
// ---- Display posts to users ----
|
// ---- Display posts to users ----
|
||||||
|
|
||||||
/// Display a page of published posts
|
/// Display a page of published posts
|
||||||
member this.PublishedPostsPage pageNbr =
|
member this.PublishedPostsPage pageNbr : obj =
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
model.PageNbr <- pageNbr
|
model.PageNbr <- pageNbr
|
||||||
model.Posts <- findPageOfPublishedPosts data this.WebLog.Id pageNbr 10 |> forDisplay
|
model.Posts <- findPageOfPublishedPosts data this.WebLog.Id pageNbr 10 |> forDisplay
|
||||||
@ -91,7 +92,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
this.ThemedView "index" model
|
this.ThemedView "index" model
|
||||||
|
|
||||||
/// Display either the newest posts or the configured home page
|
/// Display either the newest posts or the configured home page
|
||||||
member this.HomePage () =
|
member this.HomePage () : obj =
|
||||||
match this.WebLog.DefaultPage with
|
match this.WebLog.DefaultPage with
|
||||||
| "posts" -> this.PublishedPostsPage 1
|
| "posts" -> this.PublishedPostsPage 1
|
||||||
| pageId -> match tryFindPageWithoutRevisions data this.WebLog.Id pageId with
|
| pageId -> match tryFindPageWithoutRevisions data this.WebLog.Id pageId with
|
||||||
@ -101,7 +102,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Derive a post or page from the URL, or redirect from a prior URL to the current one
|
/// Derive a post or page from the URL, or redirect from a prior URL to the current one
|
||||||
member this.CatchAll (parameters : DynamicDictionary) =
|
member this.CatchAll (parameters : DynamicDictionary) : obj =
|
||||||
let url = parameters.["permalink"].ToString ()
|
let url = parameters.["permalink"].ToString ()
|
||||||
match tryFindPostByPermalink data this.WebLog.Id url with
|
match tryFindPostByPermalink data this.WebLog.Id url with
|
||||||
| Some post -> // Hopefully the most common result; the permalink is a permalink!
|
| Some post -> // Hopefully the most common result; the permalink is a permalink!
|
||||||
@ -124,7 +125,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Display categorized posts
|
/// Display categorized posts
|
||||||
member this.CategorizedPosts (parameters : DynamicDictionary) =
|
member this.CategorizedPosts (parameters : DynamicDictionary) : obj =
|
||||||
let slug = parameters.["slug"].ToString ()
|
let slug = parameters.["slug"].ToString ()
|
||||||
match tryFindCategoryBySlug data this.WebLog.Id slug with
|
match tryFindCategoryBySlug data this.WebLog.Id slug with
|
||||||
| Some cat -> let pageNbr = getPage parameters
|
| Some cat -> let pageNbr = getPage parameters
|
||||||
@ -149,7 +150,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Display tagged posts
|
/// Display tagged posts
|
||||||
member this.TaggedPosts (parameters : DynamicDictionary) =
|
member this.TaggedPosts (parameters : DynamicDictionary) : obj =
|
||||||
let tag = parameters.["tag"].ToString ()
|
let tag = parameters.["tag"].ToString ()
|
||||||
let pageNbr = getPage parameters
|
let pageNbr = getPage parameters
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
@ -167,7 +168,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
this.ThemedView "index" model
|
this.ThemedView "index" model
|
||||||
|
|
||||||
/// Generate an RSS feed
|
/// Generate an RSS feed
|
||||||
member this.Feed () =
|
member this.Feed () : obj =
|
||||||
let query = this.Request.Query :?> DynamicDictionary
|
let query = this.Request.Query :?> DynamicDictionary
|
||||||
match query.ContainsKey "format" with
|
match query.ContainsKey "format" with
|
||||||
| true -> match query.["format"].ToString () with
|
| true -> match query.["format"].ToString () with
|
||||||
@ -179,7 +180,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
// ---- Administer posts ----
|
// ---- Administer posts ----
|
||||||
|
|
||||||
/// Display a page of posts in the admin area
|
/// Display a page of posts in the admin area
|
||||||
member this.PostList pageNbr =
|
member this.PostList pageNbr : obj =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let model = PostsModel(this.Context, this.WebLog)
|
let model = PostsModel(this.Context, this.WebLog)
|
||||||
model.PageNbr <- pageNbr
|
model.PageNbr <- pageNbr
|
||||||
@ -191,7 +192,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
upcast this.View.["admin/post/list", model]
|
upcast this.View.["admin/post/list", model]
|
||||||
|
|
||||||
/// Edit a post
|
/// Edit a post
|
||||||
member this.EditPost (parameters : DynamicDictionary) =
|
member this.EditPost (parameters : DynamicDictionary) : obj =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
let postId = parameters.["postId"].ToString ()
|
let postId = parameters.["postId"].ToString ()
|
||||||
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId) with
|
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId) with
|
||||||
@ -211,12 +212,12 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a post
|
/// Save a post
|
||||||
member this.SavePost (parameters : DynamicDictionary) =
|
member this.SavePost (parameters : DynamicDictionary) : obj =
|
||||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
let postId = parameters.["postId"].ToString ()
|
let postId = parameters.["postId"].ToString ()
|
||||||
let form = this.Bind<EditPostForm>()
|
let form = this.Bind<EditPostForm>()
|
||||||
let now = clock.Now.Ticks
|
let now = clock.GetCurrentInstant().ToUnixTimeTicks()
|
||||||
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId) with
|
match (match postId with "new" -> Some Post.Empty | _ -> tryFindPost data this.WebLog.Id postId) with
|
||||||
| Some p -> let justPublished = p.PublishedOn = int64 0 && form.PublishNow
|
| Some p -> let justPublished = p.PublishedOn = int64 0 && form.PublishNow
|
||||||
let post = match postId with
|
let post = match postId with
|
||||||
@ -234,7 +235,7 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
PublishedOn = match justPublished with true -> now | _ -> int64 0
|
PublishedOn = match justPublished with true -> now | _ -> int64 0
|
||||||
UpdatedOn = now
|
UpdatedOn = now
|
||||||
Text = match form.Source with
|
Text = match form.Source with
|
||||||
| RevisionSource.Markdown -> Markdown.TransformHtml form.Text
|
| RevisionSource.Markdown -> (* Markdown.TransformHtml *) form.Text
|
||||||
| _ -> form.Text
|
| _ -> form.Text
|
||||||
CategoryIds = Array.toList form.Categories
|
CategoryIds = Array.toList form.Categories
|
||||||
Tags = form.Tags.Split ','
|
Tags = form.Tags.Split ','
|
||||||
|
@ -28,14 +28,14 @@ type UserModule(data : IMyWebLogData, cfg : AppConfig) as this =
|
|||||||
this.Get ("/logoff", fun _ -> this.LogOff ())
|
this.Get ("/logoff", fun _ -> this.LogOff ())
|
||||||
|
|
||||||
/// Show the log on page
|
/// Show the log on page
|
||||||
member this.ShowLogOn () =
|
member this.ShowLogOn () : obj =
|
||||||
let model = LogOnModel(this.Context, this.WebLog)
|
let model = LogOnModel(this.Context, this.WebLog)
|
||||||
let query = this.Request.Query :?> DynamicDictionary
|
let query = this.Request.Query :?> DynamicDictionary
|
||||||
model.Form.ReturnUrl <- match query.ContainsKey "returnUrl" with true -> query.["returnUrl"].ToString () | _ -> ""
|
model.Form.ReturnUrl <- match query.ContainsKey "returnUrl" with true -> query.["returnUrl"].ToString () | _ -> ""
|
||||||
upcast this.View.["admin/user/logon", model]
|
upcast this.View.["admin/user/logon", model]
|
||||||
|
|
||||||
/// Process a user log on
|
/// Process a user log on
|
||||||
member this.DoLogOn (parameters : DynamicDictionary) =
|
member this.DoLogOn (parameters : DynamicDictionary) : obj =
|
||||||
this.ValidateCsrfToken ()
|
this.ValidateCsrfToken ()
|
||||||
let form = this.Bind<LogOnForm> ()
|
let form = this.Bind<LogOnForm> ()
|
||||||
let model = MyWebLogModel(this.Context, this.WebLog)
|
let model = MyWebLogModel(this.Context, this.WebLog)
|
||||||
@ -54,7 +54,7 @@ type UserModule(data : IMyWebLogData, cfg : AppConfig) as this =
|
|||||||
this.Redirect (sprintf "/user/logon?returnUrl=%s" form.ReturnUrl) model
|
this.Redirect (sprintf "/user/logon?returnUrl=%s" form.ReturnUrl) model
|
||||||
|
|
||||||
/// Log a user off
|
/// Log a user off
|
||||||
member this.LogOff () =
|
member this.LogOff () : obj =
|
||||||
// FIXME: why are we getting the user here if we don't do anything with it?
|
// FIXME: why are we getting the user here if we don't do anything with it?
|
||||||
let user = this.Request.PersistableSession.GetOrDefault<User> (Keys.User, User.Empty)
|
let user = this.Request.PersistableSession.GetOrDefault<User> (Keys.User, User.Empty)
|
||||||
this.Session.DeleteAll ()
|
this.Session.DeleteAll ()
|
||||||
|
@ -71,7 +71,7 @@ with
|
|||||||
module FormatDateTime =
|
module FormatDateTime =
|
||||||
|
|
||||||
/// Convert ticks to a zoned date/time
|
/// Convert ticks to a zoned date/time
|
||||||
let zonedTime timeZone ticks = Instant(ticks).InZone(DateTimeZoneProviders.Tzdb.[timeZone])
|
let zonedTime timeZone ticks = Instant.FromUnixTimeTicks(ticks).InZone(DateTimeZoneProviders.Tzdb.[timeZone])
|
||||||
|
|
||||||
/// Display a long date
|
/// Display a long date
|
||||||
let longDate timeZone ticks =
|
let longDate timeZone ticks =
|
||||||
|
@ -13,7 +13,7 @@ let private fallbackLocale = "en-US"
|
|||||||
let private getEmbedded locale =
|
let private getEmbedded locale =
|
||||||
use rdr =
|
use rdr =
|
||||||
new System.IO.StreamReader
|
new System.IO.StreamReader
|
||||||
(MyWebLog.Resources.AssemblyInfo.HorribleHack().Assembly.GetManifestResourceStream(sprintf "%s.json" locale))
|
(AssemblyInfo.HorribleHack().Assembly.GetManifestResourceStream(sprintf "MyWebLog.Resources.%s.json" locale))
|
||||||
rdr.ReadToEnd()
|
rdr.ReadToEnd()
|
||||||
|
|
||||||
/// The dictionary of localized strings
|
/// The dictionary of localized strings
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
"emitEntryPoint": true
|
"emitEntryPoint": true,
|
||||||
|
"copyToOutput": {
|
||||||
|
"include": "views"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"MyWebLog.App": "0.9.2",
|
"MyWebLog.App": "0.9.2",
|
||||||
|
10
src/global.json
Normal file
10
src/global.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"projects":[
|
||||||
|
"MyWebLog",
|
||||||
|
"MyWebLog.App",
|
||||||
|
"MyWebLog.Data.RethinkDB",
|
||||||
|
"MyWebLog.Entities",
|
||||||
|
"MyWebLog.Logic",
|
||||||
|
"MyWebLog.Resources"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user