Convert API to .NET 6

This commit is contained in:
Daniel J. Summers 2021-09-17 21:17:26 -04:00
parent bf12867602
commit c1f6054e15
5 changed files with 47 additions and 51 deletions

View File

@ -79,7 +79,6 @@ module Indexes =
/// All data manipulations within myPrayerJournal
module Data =
open FSharp.Control.Tasks.V2.ContextInsensitive
open Indexes
open Microsoft.FSharpLu
open Raven.Client.Documents

View File

@ -2,6 +2,8 @@
/// The data model for myPrayerJournal
module MyPrayerJournal.Domain
// fsharplint:disable RecordFieldNames
open Cuid
/// Request ID is a CUID
@ -9,9 +11,9 @@ type RequestId =
| RequestId of Cuid
module RequestId =
/// The string representation of the request ID
let toString x = match x with RequestId y -> (Cuid.toString >> sprintf "Requests/%s") y
let toString = function RequestId x -> $"Requests/{Cuid.toString x}"
/// Create a request ID from a string representation
let fromIdString (y : string) = (Cuid >> RequestId) <| y.Replace("Requests/", "")
let fromIdString (x : string) = x.Replace ("Requests/", "") |> (Cuid >> RequestId)
/// User ID is a string (the "sub" part of the JWT)
@ -19,7 +21,7 @@ type UserId =
| UserId of string
module UserId =
/// The string representation of the user ID
let toString x = match x with UserId y -> y
let toString = function UserId x -> x
/// A long integer representing seconds since the epoch
@ -27,7 +29,7 @@ type Ticks =
| Ticks of int64
module Ticks =
/// The int64 (long) representation of ticks
let toLong x = match x with Ticks y -> y
let toLong = function Ticks x -> x
/// How frequently a request should reappear after it is marked "Prayed"
@ -38,16 +40,16 @@ type Recurrence =
| Weeks
module Recurrence =
/// Create a recurrence value from a string
let fromString x =
match x with
let fromString =
function
| "Immediate" -> Immediate
| "Hours" -> Hours
| "Days" -> Days
| "Weeks" -> Weeks
| _ -> invalidOp (sprintf "%s is not a valid recurrence" x)
| it -> invalidOp $"{it} is not a valid recurrence"
/// The duration of the recurrence
let duration x =
match x with
let duration =
function
| Immediate -> 0L
| Hours -> 3600000L
| Days -> 86400000L
@ -62,13 +64,13 @@ type RequestAction =
| Answered
module RequestAction =
/// Create a RequestAction from a string
let fromString x =
match x with
let fromString =
function
| "Created" -> Created
| "Prayed" -> Prayed
| "Updated" -> Updated
| "Answered" -> Answered
| _ -> (sprintf "Bad request action %s" >> invalidOp) x
| it -> invalidOp $"Bad request action {it}"
/// History is a record of action taken on a prayer request, including updates to its text

View File

@ -2,6 +2,8 @@
[<RequireQualifiedAccess>]
module MyPrayerJournal.Handlers
// fsharplint:disable RecordFieldNames
open Giraffe
/// Handler to return Vue files
@ -60,11 +62,10 @@ module private Helpers =
/// Create a request ID from a string
let toReqId x =
let reqId =
match Cuid.ofString x with
| Ok cuid -> cuid
| Error msg -> invalidOp msg
RequestId reqId
match Cuid.ofString x with
| Ok cuid -> cuid
| Error msg -> invalidOp msg
|> RequestId
/// Return a 201 CREATED response
let created next ctx =
@ -88,12 +89,12 @@ module private Helpers =
/// Work-around to let the Json.NET serializer synchronously deserialize from the request stream
// TODO: Remove this once there is an async serializer
let allowSyncIO : HttpHandler =
fun next ctx ->
match ctx.Features.Get<Features.IHttpBodyControlFeature>() with
| null -> ()
| f -> f.AllowSynchronousIO <- true
next ctx
// let allowSyncIO : HttpHandler =
// fun next ctx ->
// match ctx.Features.Get<Features.IHttpBodyControlFeature>() with
// | null -> ()
// | f -> f.AllowSynchronousIO <- true
// next ctx
/// Strongly-typed models for post requests
@ -142,8 +143,6 @@ module Models =
until : int64
}
open FSharp.Control.Tasks.V2.ContextInsensitive
/// /api/journal URLs
module Journal =
@ -165,7 +164,7 @@ module Request =
/// POST /api/request
let add : HttpHandler =
authorize
>=> allowSyncIO
// >=> allowSyncIO
>=> fun next ctx ->
task {
let! r = ctx.BindJsonAsync<Models.Request> ()
@ -197,7 +196,7 @@ module Request =
/// POST /api/request/[req-id]/history
let addHistory requestId : HttpHandler =
authorize
>=> allowSyncIO
// >=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@ -229,7 +228,7 @@ module Request =
/// POST /api/request/[req-id]/note
let addNote requestId : HttpHandler =
authorize
>=> allowSyncIO
// >=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@ -309,7 +308,7 @@ module Request =
/// PATCH /api/request/[req-id]/snooze
let snooze requestId : HttpHandler =
authorize
>=> allowSyncIO
// >=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@ -327,7 +326,7 @@ module Request =
/// PATCH /api/request/[req-id]/recurrence
let updateRecurrence requestId : HttpHandler =
authorize
>=> allowSyncIO
// >=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@ -344,12 +343,11 @@ module Request =
| None -> return! Error.notFound next ctx
}
open Giraffe.TokenRouter
open Giraffe.EndpointRouting
/// The routes for myPrayerJournal
let webApp : HttpHandler =
router Error.notFound [
route "/" Vue.app
let routes =
[ route "/" Vue.app
subRoute "/api/" [
GET [
route "journal" Journal.journal

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<Version>3.0.0.0</Version>
</PropertyGroup>
@ -14,17 +14,12 @@
<ItemGroup>
<PackageReference Include="FunctionalCuid" Version="1.0.0" />
<PackageReference Include="Giraffe" Version="4.1.0" />
<PackageReference Include="Giraffe.TokenRouter" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.3" />
<PackageReference Include="Microsoft.FSharpLu" Version="0.11.6" />
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.6" />
<PackageReference Include="Giraffe" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.10" />
<PackageReference Include="Microsoft.FSharpLu" Version="0.11.7" />
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.7" />
<PackageReference Include="RavenDb.Client" Version="4.2.102" />
<PackageReference Include="TaskBuilder.fs" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.7.1" />
<PackageReference Include="RethinkDb.Driver" Version="2.3.150" />
</ItemGroup>
<ItemGroup>

View File

@ -36,7 +36,6 @@ module Configure =
(Path.Combine >> bldr.UseWebRoot) pathSegments
open Giraffe
open Giraffe.Serialization
open Microsoft.AspNetCore.Authentication.JwtBearer
open Microsoft.Extensions.DependencyInjection
open MyPrayerJournal.Indexes
@ -51,7 +50,7 @@ module Configure =
let svcs (sc : IServiceCollection) =
/// Custom settings for the JSON serializer (uses compact representation for options and DUs)
let jsonSettings =
let x = NewtonsoftJsonSerializer.DefaultSettings
let x = NewtonsoftJson.Serializer.DefaultSettings
Converters.all |> List.ofSeq |> List.iter x.Converters.Add
x.NullValueHandling <- NullValueHandling.Ignore
x.MissingMemberHandling <- MissingMemberHandling.Error
@ -61,7 +60,8 @@ module Configure =
use sp = sc.BuildServiceProvider ()
let cfg = sp.GetRequiredService<IConfiguration> ()
sc.AddGiraffe()
sc.AddRouting()
.AddGiraffe()
.AddAuthentication(
/// Use HTTP "Bearer" authentication with JWTs
fun opts ->
@ -75,7 +75,7 @@ module Configure =
opts.Audience <- jwtCfg.["Id"]
)
|> ignore
sc.AddSingleton<IJsonSerializer> (NewtonsoftJsonSerializer jsonSettings)
sc.AddSingleton<Json.ISerializer> (NewtonsoftJson.Serializer jsonSettings)
|> ignore
let config = sc.BuildServiceProvider().GetRequiredService<IConfiguration>().GetSection "RavenDB"
let store = new DocumentStore ()
@ -104,6 +104,7 @@ module Configure =
bldr.ConfigureLogging logz
open System
open Giraffe.EndpointRouting
/// Configure the web application
let application (bldr : IWebHostBuilder) =
@ -118,7 +119,8 @@ module Configure =
| a ->
a.UseAuthentication()
.UseStaticFiles()
.UseGiraffe Handlers.webApp
.UseRouting()
.UseEndpoints (fun e -> e.MapGiraffeEndpoints Handlers.routes)
|> ignore)
bldr.Configure appConfig