mostly housekeeping
- App - some package clean-up - API - removed commented code that is not needed, postured for JSON outputs - Build - modified the scripts to build Vue into API's wwwroot folder, which will get copied on publish; adjusted FAKE task dependencies to be more granular
This commit is contained in:
parent
196db30cc5
commit
5a7a74c167
3
.gitignore
vendored
3
.gitignore
vendored
@ -253,8 +253,7 @@ paket-files/
|
|||||||
*.sln.iml
|
*.sln.iml
|
||||||
|
|
||||||
# Compiled files / application
|
# Compiled files / application
|
||||||
**/vendor-bundle.js
|
|
||||||
**/app-bundle.js*
|
|
||||||
src/api/wwwroot/index.html
|
src/api/wwwroot/index.html
|
||||||
|
src/api/wwwroot/static
|
||||||
src/api/appsettings.json
|
src/api/appsettings.json
|
||||||
build/
|
build/
|
@ -1,5 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
cd .\src\app
|
cd .\src\app
|
||||||
au build
|
npm run build prod
|
||||||
cd ..\..
|
cd ..\..
|
||||||
exit %errorlevel%
|
exit %errorlevel%
|
55
build.fsx
55
build.fsx
@ -4,7 +4,7 @@ open System
|
|||||||
|
|
||||||
let buildDir = "./build/"
|
let buildDir = "./build/"
|
||||||
|
|
||||||
/// Path to the Aurelia app
|
/// Path to the Vue app
|
||||||
let appPath = "src" @@ "app"
|
let appPath = "src" @@ "app"
|
||||||
|
|
||||||
/// Path to the Suave API
|
/// Path to the Suave API
|
||||||
@ -14,27 +14,15 @@ let apiPath = "src" @@ "api"
|
|||||||
|
|
||||||
Target "Clean" (fun _ ->
|
Target "Clean" (fun _ ->
|
||||||
CleanDir buildDir
|
CleanDir buildDir
|
||||||
|
CleanDir (apiPath @@ "wwwroot")
|
||||||
)
|
)
|
||||||
|
|
||||||
Target "BuildApp" (fun _ ->
|
Target "BuildApp" (fun _ ->
|
||||||
let result =
|
let result =
|
||||||
ExecProcessAndReturnMessages (fun info ->
|
ExecProcessAndReturnMessages (fun info ->
|
||||||
info.UseShellExecute <- false
|
info.UseShellExecute <- false
|
||||||
info.FileName <- "." @@ "build-au.bat") (TimeSpan.FromMinutes 2.)
|
info.FileName <- "build-vue.bat") (TimeSpan.FromMinutes 2.)
|
||||||
match result.ExitCode with
|
match result.ExitCode with 0 -> Log "AppBuild-Output: " result.Messages | _ -> failwith "Vue build failed"
|
||||||
| 0 -> Log "AppBuild-Output: " result.Messages
|
|
||||||
| _ -> failwith "Aurelia build failed"
|
|
||||||
)
|
|
||||||
|
|
||||||
Target "CopyApp" (fun _ ->
|
|
||||||
let apiWebPath = apiPath @@ "wwwroot"
|
|
||||||
[ "scripts" @@ "app-bundle.js"
|
|
||||||
"scripts" @@ "vendor-bundle.js"
|
|
||||||
"index.html"
|
|
||||||
]
|
|
||||||
|> List.iter (fun file ->
|
|
||||||
IO.File.Copy (appPath @@ file, apiWebPath @@ file, true)
|
|
||||||
Log "CopyApp--Output: " (Seq.singleton file))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Target "BuildApi" (fun _ ->
|
Target "BuildApi" (fun _ ->
|
||||||
@ -43,26 +31,24 @@ Target "BuildApi" (fun _ ->
|
|||||||
info.UseShellExecute <- false
|
info.UseShellExecute <- false
|
||||||
info.FileName <- "dotnet"
|
info.FileName <- "dotnet"
|
||||||
info.Arguments <- "build"
|
info.Arguments <- "build"
|
||||||
info.WorkingDirectory <- "src" @@ "api") (TimeSpan.FromMinutes 2.)
|
info.WorkingDirectory <- apiPath) (TimeSpan.FromMinutes 2.)
|
||||||
Log "AppBuild-Output: " result.Messages
|
Log "AppBuild-Output: " result.Messages
|
||||||
match result.ExitCode with
|
match result.ExitCode with 0 -> () | _ -> failwith "API build failed"
|
||||||
| 0 -> ()
|
)
|
||||||
| _ -> failwith "API build failed"
|
|
||||||
(*!! "src/api/*.fsproj"
|
Target "Publish" (fun _ ->
|
||||||
|> MSBuildRelease buildDir "Build"
|
ExecProcess (fun info ->
|
||||||
|> Log "ApiBuild-Output: " *)
|
info.FileName <- "dotnet"
|
||||||
|
info.Arguments <- """publish -o ..\..\build"""
|
||||||
|
info.WorkingDirectory <- apiPath) TimeSpan.MaxValue
|
||||||
|
|> ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
Target "Run" (fun _ ->
|
Target "Run" (fun _ ->
|
||||||
ExecProcess (fun info ->
|
|
||||||
info.FileName <- "dotnet"
|
|
||||||
info.Arguments <- """publish -o ..\..\build"""
|
|
||||||
info.WorkingDirectory <- "src" @@ "api") TimeSpan.MaxValue
|
|
||||||
|> ignore
|
|
||||||
ExecProcess (fun info ->
|
ExecProcess (fun info ->
|
||||||
info.FileName <- "dotnet"
|
info.FileName <- "dotnet"
|
||||||
info.Arguments <- "myPrayerJournal.dll"
|
info.Arguments <- "myPrayerJournal.dll"
|
||||||
info.WorkingDirectory <- "build") TimeSpan.MaxValue
|
info.WorkingDirectory <- buildDir) TimeSpan.MaxValue
|
||||||
|> ignore
|
|> ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,11 +60,18 @@ Target "Default" (fun _ ->
|
|||||||
|
|
||||||
"Clean"
|
"Clean"
|
||||||
==> "BuildApp"
|
==> "BuildApp"
|
||||||
==> "CopyApp"
|
|
||||||
|
"BuildApp"
|
||||||
==> "BuildApi"
|
==> "BuildApi"
|
||||||
==> "Default"
|
|
||||||
|
|
||||||
"BuildApi"
|
"BuildApi"
|
||||||
|
==> "Publish"
|
||||||
|
|
||||||
|
"Publish"
|
||||||
==> "Run"
|
==> "Run"
|
||||||
|
|
||||||
|
"BuildApi"
|
||||||
|
==> "Default"
|
||||||
|
|
||||||
|
|
||||||
RunTargetOrDefault "Default"
|
RunTargetOrDefault "Default"
|
233
src/api/App.fs
233
src/api/App.fs
@ -1,76 +1,81 @@
|
|||||||
/// Main server module for myPrayerJournal
|
/// Main server module for myPrayerJournal
|
||||||
module MyPrayerJournal.App
|
module MyPrayerJournal.App
|
||||||
|
|
||||||
open Auth0.AuthenticationApi
|
|
||||||
open Auth0.AuthenticationApi.Models
|
|
||||||
open Microsoft.EntityFrameworkCore
|
open Microsoft.EntityFrameworkCore
|
||||||
open Newtonsoft.Json
|
open Newtonsoft.Json
|
||||||
open Newtonsoft.Json.Linq
|
open Newtonsoft.Json.Linq
|
||||||
open Reader
|
|
||||||
open System
|
open System
|
||||||
open System.IO
|
open System.IO
|
||||||
open Suave
|
open Suave
|
||||||
open Suave.Filters
|
open Suave.Filters
|
||||||
open Suave.Operators
|
open Suave.Operators
|
||||||
open Suave.Redirection
|
|
||||||
open Suave.RequestErrors
|
|
||||||
open Suave.State.CookieStateStore
|
|
||||||
open Suave.Successful
|
|
||||||
|
|
||||||
let utf8 = System.Text.Encoding.UTF8
|
// --- Types ---
|
||||||
|
|
||||||
type JsonNetCookieSerializer () =
|
|
||||||
interface CookieSerialiser with
|
|
||||||
member x.serialise m =
|
|
||||||
utf8.GetBytes (JsonConvert.SerializeObject m)
|
|
||||||
member x.deserialise m =
|
|
||||||
JsonConvert.DeserializeObject<Map<string, obj>> (utf8.GetString m)
|
|
||||||
|
|
||||||
|
/// Auth0 settings
|
||||||
type Auth0Config = {
|
type Auth0Config = {
|
||||||
|
/// The domain used with Auth0
|
||||||
Domain : string
|
Domain : string
|
||||||
|
/// The client Id
|
||||||
ClientId : string
|
ClientId : string
|
||||||
|
/// The base64-encoded client secret
|
||||||
ClientSecret : string
|
ClientSecret : string
|
||||||
}
|
/// The URL-safe base64-encoded client secret
|
||||||
|
ClientSecretJwt : string
|
||||||
|
}
|
||||||
with
|
with
|
||||||
|
/// An empty set of Auth0 settings
|
||||||
static member empty =
|
static member empty =
|
||||||
{ Domain = ""
|
{ Domain = ""
|
||||||
ClientId = ""
|
ClientId = ""
|
||||||
ClientSecret = ""
|
ClientSecret = ""
|
||||||
|
ClientSecretJwt = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Application configuration
|
||||||
type Config = {
|
type Config = {
|
||||||
|
/// PostgreSQL connection string
|
||||||
Conn : string
|
Conn : string
|
||||||
|
/// Auth0 settings
|
||||||
Auth0 : Auth0Config
|
Auth0 : Auth0Config
|
||||||
}
|
}
|
||||||
with
|
with
|
||||||
static member empty =
|
static member empty =
|
||||||
{ Conn = ""
|
{ Conn = ""
|
||||||
Auth0 = Auth0Config.empty
|
Auth0 = Auth0Config.empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A JSON response as a data property
|
||||||
|
type JsonOkResponse<'a> = {
|
||||||
|
data : 'a
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A JSON response indicating an error occurred
|
||||||
|
type JsonErrorResponse = {
|
||||||
|
error : string
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Support ---
|
||||||
|
|
||||||
|
/// Configuration instance
|
||||||
let cfg =
|
let cfg =
|
||||||
try
|
try
|
||||||
use sr = File.OpenText "appsettings.json"
|
use sr = File.OpenText "appsettings.json"
|
||||||
let settings = JToken.ReadFrom(new JsonTextReader(sr)) :?> JObject
|
use tr = new JsonTextReader (sr)
|
||||||
|
let settings = JToken.ReadFrom tr
|
||||||
|
let secret = settings.["auth0"].["client-secret"].ToObject<string>()
|
||||||
{ Conn = settings.["conn"].ToObject<string>()
|
{ Conn = settings.["conn"].ToObject<string>()
|
||||||
Auth0 =
|
Auth0 =
|
||||||
{ Domain = settings.["auth0"].["domain"].ToObject<string>()
|
{ Domain = settings.["auth0"].["domain"].ToObject<string>()
|
||||||
ClientId = settings.["auth0"].["client-id"].ToObject<string>()
|
ClientId = settings.["auth0"].["client-id"].ToObject<string>()
|
||||||
ClientSecret = settings.["auth0"].["client-secret"].ToObject<string>()
|
ClientSecret = secret
|
||||||
|
ClientSecretJwt = secret.TrimEnd('=').Replace("-", "+").Replace("_", "/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
with _ -> Config.empty
|
with _ -> Config.empty
|
||||||
|
|
||||||
/// Data Configuration singleton
|
|
||||||
//let lazyCfg = lazy (DataConfig.FromJson <| try File.ReadAllText "data-config.json" with _ -> "{}")
|
|
||||||
/// RethinkDB connection singleton
|
|
||||||
//let lazyConn = lazy lazyCfg.Force().CreateConnection ()
|
|
||||||
/// Application dependencies
|
|
||||||
//let deps = {
|
|
||||||
// new IDependencies with
|
|
||||||
// member __.Conn with get () = lazyConn.Force ()
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Get the scheme, host, and port of the URL
|
/// Get the scheme, host, and port of the URL
|
||||||
let schemeHostPort (req : HttpRequest) =
|
let schemeHostPort (req : HttpRequest) =
|
||||||
sprintf "%s://%s" req.url.Scheme (req.headers |> List.filter (fun x -> fst x = "host") |> List.head |> snd)
|
sprintf "%s://%s" req.url.Scheme (req.headers |> List.filter (fun x -> fst x = "host") |> List.head |> snd)
|
||||||
@ -78,120 +83,46 @@ let schemeHostPort (req : HttpRequest) =
|
|||||||
/// Authorization functions
|
/// Authorization functions
|
||||||
module Auth =
|
module Auth =
|
||||||
|
|
||||||
(*
|
/// Shorthand for Console.WriteLine
|
||||||
let exchangeCodeForToken code = context (fun ctx ->
|
|
||||||
async {
|
|
||||||
let client = AuthenticationApiClient (Uri (sprintf "https://%s" cfg.Auth0.Domain))
|
|
||||||
let! req =
|
|
||||||
client.ExchangeCodeForAccessTokenAsync
|
|
||||||
(ExchangeCodeRequest
|
|
||||||
(AuthorizationCode = code,
|
|
||||||
ClientId = cfg.Auth0.ClientId,
|
|
||||||
ClientSecret = cfg.Auth0.ClientSecret,
|
|
||||||
RedirectUri = sprintf "%s/user/log-on" (schemeHostPort ctx.request)))
|
|
||||||
let! user = client.GetUserInfoAsync ((req : AccessToken).AccessToken)
|
|
||||||
return
|
|
||||||
ctx
|
|
||||||
|> HttpContext.state
|
|
||||||
|> function
|
|
||||||
| None -> FORBIDDEN "Cannot sign in without state"
|
|
||||||
| Some state ->
|
|
||||||
state.set "auth-token" req.IdToken
|
|
||||||
>=> Writers.setUserData "user" user
|
|
||||||
}
|
|
||||||
|> Async.RunSynchronously
|
|
||||||
)
|
|
||||||
|
|
||||||
/// Handle the sign-in callback from Auth0
|
|
||||||
let handleSignIn =
|
|
||||||
context (fun ctx ->
|
|
||||||
GET
|
|
||||||
>=> match ctx.request.queryParam "code" with
|
|
||||||
| Choice1Of2 authCode ->
|
|
||||||
exchangeCodeForToken authCode
|
|
||||||
>=> FOUND (sprintf "%s/journal" (schemeHostPort ctx.request))
|
|
||||||
| Choice2Of2 msg -> BAD_REQUEST msg
|
|
||||||
)
|
|
||||||
|
|
||||||
/// Handle signing out a user
|
|
||||||
let handleSignOut =
|
|
||||||
context (fun ctx ->
|
|
||||||
match ctx |> HttpContext.state with
|
|
||||||
| Some state -> state.set "auth-key" null
|
|
||||||
| _ -> succeed
|
|
||||||
>=> FOUND (sprintf "%s/" (schemeHostPort ctx.request))) *)
|
|
||||||
|
|
||||||
let cw (x : string) = Console.WriteLine x
|
let cw (x : string) = Console.WriteLine x
|
||||||
|
|
||||||
/// Convert microtime to ticks, add difference from 1/1/1 to 1/1/1970
|
/// Convert microtime to ticks, add difference from 1/1/1 to 1/1/1970
|
||||||
let jsDate jsTicks =
|
let jsDate jsTicks =
|
||||||
DateTime(jsTicks * 10000000L).AddTicks(DateTime(1970, 1, 1).Ticks)
|
DateTime(jsTicks * 10000000L).AddTicks(DateTime(1970, 1, 1).Ticks)
|
||||||
|
|
||||||
let getIdFromToken token =
|
/// Get the user Id (sub) from a JSON Web Token
|
||||||
match token with
|
let getIdFromToken jwt =
|
||||||
| Some jwt ->
|
try
|
||||||
try
|
let payload = Jose.JWT.Decode<JObject>(jwt, cfg.Auth0.ClientSecretJwt)
|
||||||
let key = Convert.FromBase64String(cfg.Auth0.ClientSecret.Replace("-", "+").Replace("_", "/"))
|
let tokenExpires = jsDate (payload.["exp"].ToObject<int64>())
|
||||||
let payload = Jose.JWT.Decode<JObject>(jwt, key)
|
match tokenExpires > DateTime.UtcNow with
|
||||||
let tokenExpires = jsDate (payload.["exp"].ToObject<int64>())
|
| true -> Some (payload.["sub"].ToObject<string>())
|
||||||
match tokenExpires > DateTime.UtcNow with
|
| _ -> None
|
||||||
| true -> Some (payload.["sub"].ToObject<string>())
|
with ex ->
|
||||||
| _ -> None
|
sprintf "Token Deserialization Exception - %s" (ex.GetType().FullName) |> cw
|
||||||
with ex ->
|
sprintf "Message - %s" ex.Message |> cw
|
||||||
sprintf "Token Deserialization Exception - %s" (ex.GetType().FullName) |> cw
|
ex.StackTrace |> cw
|
||||||
sprintf "Message - %s" ex.Message |> cw
|
None
|
||||||
ex.StackTrace |> cw
|
|
||||||
None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
/// Add the logged on user Id to the context if it exists
|
/// Add the logged on user Id to the context if it exists
|
||||||
let loggedOn = warbler (fun ctx ->
|
let loggedOn =
|
||||||
match HttpContext.state ctx with
|
warbler (fun ctx ->
|
||||||
| Some state -> Writers.setUserData "user" (state.get "auth-token" |> getIdFromToken)
|
match ctx.request.header "Authorization" with
|
||||||
|
| Choice1Of2 bearer -> Writers.setUserData "user" ((bearer.Split(' ').[1]) |> getIdFromToken)
|
||||||
| _ -> Writers.setUserData "user" None)
|
| _ -> Writers.setUserData "user" None)
|
||||||
|
|
||||||
/// Create a user context for the currently assigned user
|
|
||||||
//let userCtx ctx = { Id = ctx.userState.["user"] :?> string option }
|
/// Serialize an object to JSON
|
||||||
|
let toJson = JsonConvert.SerializeObject
|
||||||
|
|
||||||
/// Read an item from the user state, downcast to the expected type
|
/// Read an item from the user state, downcast to the expected type
|
||||||
let read ctx key : 'value =
|
let read ctx key : 'value =
|
||||||
ctx.userState |> Map.tryFind key |> Option.map (fun x -> x :?> 'value) |> Option.get
|
ctx.userState |> Map.tryFind key |> Option.map (fun x -> x :?> 'value) |> Option.get
|
||||||
|
|
||||||
/// Create a new data context
|
/// Create a new data context
|
||||||
let dataCtx () =
|
let dataCtx () =
|
||||||
new DataContext (((DbContextOptionsBuilder<DataContext>()).UseNpgsql cfg.Conn).Options)
|
new DataContext (((DbContextOptionsBuilder<DataContext>()).UseNpgsql cfg.Conn).Options)
|
||||||
|
|
||||||
/// Return an HTML page
|
|
||||||
let html ctx content =
|
|
||||||
""//Views.page (Auth.userCtx ctx) content
|
|
||||||
|
|
||||||
/// Home page
|
|
||||||
let viewHome = warbler (fun ctx -> OK ("" (*Views.home*) |> html ctx))
|
|
||||||
|
|
||||||
/// Journal page
|
|
||||||
let viewJournal =
|
|
||||||
context (fun ctx ->
|
|
||||||
use dataCtx = dataCtx ()
|
|
||||||
let reqs = Data.Requests.allForUser (defaultArg (read ctx "user") "") dataCtx
|
|
||||||
OK ("" (*Views.journal reqs*) |> html ctx))
|
|
||||||
|
|
||||||
let idx =
|
|
||||||
context (fun ctx ->
|
|
||||||
Console.WriteLine "serving index"
|
|
||||||
succeed)
|
|
||||||
/// Suave application
|
|
||||||
let app =
|
|
||||||
statefulForSession
|
|
||||||
>=> Auth.loggedOn
|
|
||||||
>=> choose [
|
|
||||||
path Route.home >=> Files.browseFileHome "index.html"
|
|
||||||
path Route.journal >=> viewJournal
|
|
||||||
//path Route.User.logOn >=> Auth.handleSignIn
|
|
||||||
//path Route.User.logOff >=> Auth.handleSignOut
|
|
||||||
Writers.setHeader "Cache-Control" "no-cache" >=> Files.browseHome
|
|
||||||
NOT_FOUND "Page not found."
|
|
||||||
]
|
|
||||||
|
|
||||||
/// Ensure the EF context is created in the right format
|
/// Ensure the EF context is created in the right format
|
||||||
let ensureDatabase () =
|
let ensureDatabase () =
|
||||||
async {
|
async {
|
||||||
@ -204,16 +135,54 @@ let suaveCfg =
|
|||||||
{ defaultConfig with
|
{ defaultConfig with
|
||||||
homeFolder = Some (Path.GetFullPath "./wwwroot/")
|
homeFolder = Some (Path.GetFullPath "./wwwroot/")
|
||||||
serverKey = Text.Encoding.UTF8.GetBytes("12345678901234567890123456789012")
|
serverKey = Text.Encoding.UTF8.GetBytes("12345678901234567890123456789012")
|
||||||
cookieSerialiser = JsonNetCookieSerializer ()
|
bindings = [ HttpBinding.createSimple HTTP "127.0.0.1" 8084 ]
|
||||||
}
|
}
|
||||||
open Suave.Utils
|
|
||||||
|
// --- Routes ---
|
||||||
|
|
||||||
|
/// URL routes for myPrayerJournal
|
||||||
|
module Route =
|
||||||
|
|
||||||
|
/// /api/journal ~ All active prayer requests for a user
|
||||||
|
let journal = "/api/journal"
|
||||||
|
|
||||||
|
|
||||||
|
// --- WebParts ---
|
||||||
|
|
||||||
|
/// All WebParts that compose the public API
|
||||||
|
module WebParts =
|
||||||
|
|
||||||
|
let jsonMimeType =
|
||||||
|
warbler (fun ctx -> Writers.setMimeType "application/json; charset=utf8")
|
||||||
|
|
||||||
|
/// WebPart to return a JSON response
|
||||||
|
let JSON payload =
|
||||||
|
jsonMimeType
|
||||||
|
>=> Successful.OK (toJson { data = payload })
|
||||||
|
|
||||||
|
/// WebPart to return an JSON error response
|
||||||
|
let errorJSON code error =
|
||||||
|
jsonMimeType
|
||||||
|
>=> Writers.setStatus code
|
||||||
|
>=> Response.response code ((toJson >> UTF8.bytes) { error = error })
|
||||||
|
|
||||||
|
/// Journal page
|
||||||
|
let viewJournal =
|
||||||
|
context (fun ctx ->
|
||||||
|
use dataCtx = dataCtx ()
|
||||||
|
let reqs = Data.Requests.allForUser (defaultArg (read ctx "user") "") dataCtx
|
||||||
|
JSON reqs)
|
||||||
|
|
||||||
|
/// Suave application
|
||||||
|
let app =
|
||||||
|
Auth.loggedOn
|
||||||
|
>=> choose [
|
||||||
|
path Route.journal >=> viewJournal
|
||||||
|
errorJSON HttpCode.HTTP_404 "Page not found"
|
||||||
|
]
|
||||||
|
|
||||||
[<EntryPoint>]
|
[<EntryPoint>]
|
||||||
let main argv =
|
let main argv =
|
||||||
// Establish the data environment
|
|
||||||
//liftDep getConn (Data.establishEnvironment >> Async.RunSynchronously)
|
|
||||||
//|> run deps
|
|
||||||
|
|
||||||
ensureDatabase ()
|
ensureDatabase ()
|
||||||
startWebServer suaveCfg app
|
startWebServer suaveCfg WebParts.app
|
||||||
0
|
0
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
<Compile Include="Data.fs" />
|
<Compile Include="Data.fs" />
|
||||||
<Compile Include="Migrations/20170104023341_InitialDb.fs" />
|
<Compile Include="Migrations/20170104023341_InitialDb.fs" />
|
||||||
<Compile Include="Migrations/DataContextModelSnapshot.fs" />
|
<Compile Include="Migrations/DataContextModelSnapshot.fs" />
|
||||||
<Compile Include="Route.fs" />
|
|
||||||
<Compile Include="App.fs" />
|
<Compile Include="App.fs" />
|
||||||
<None Update="appsettings.json">
|
<None Update="appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
@ -28,9 +27,6 @@
|
|||||||
|
|
||||||
<!-- Import Project="..\..\.paket\Paket.Restore.targets" / -->
|
<!-- Import Project="..\..\.paket\Paket.Restore.targets" / -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Auth0.AuthenticationApi">
|
|
||||||
<Version>4.1.0</Version>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="FSharp.Core">
|
<PackageReference Include="FSharp.Core">
|
||||||
<Version>4.1.17</Version>
|
<Version>4.1.17</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@ -38,16 +34,16 @@
|
|||||||
<Version>1.0.5</Version>
|
<Version>1.0.5</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="jose-jwt">
|
<PackageReference Include="jose-jwt">
|
||||||
<Version>2.3.0</Version>
|
<Version>2.*</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Newtonsoft.Json">
|
<PackageReference Include="Newtonsoft.Json">
|
||||||
<Version>10.0.2</Version>
|
<Version>10.*</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL">
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL">
|
||||||
<Version>1.1.0</Version>
|
<Version>1.*</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Suave">
|
<PackageReference Include="Suave">
|
||||||
<Version>2.1.0</Version>
|
<Version>2.*</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
/// URL routes for myPrayerJournal
|
|
||||||
module MyPrayerJournal.Route
|
|
||||||
|
|
||||||
/// The home page
|
|
||||||
let home = "/"
|
|
||||||
|
|
||||||
/// The main journal page
|
|
||||||
let journal = "/journal"
|
|
||||||
|
|
||||||
/// Routes dealing with users
|
|
||||||
module User =
|
|
||||||
/// The route for user log on response from Auth0
|
|
||||||
let logOn = "/user/log-on"
|
|
||||||
let logOff = "/user/log-off"
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
body {
|
|
||||||
padding-top: 50px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapping element */
|
|
||||||
/* Set some basic padding to keep content from hitting the edges */
|
|
||||||
.body-content {
|
|
||||||
padding-left: 15px;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
.material-icons.md-18 {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.material-icons.md-24 {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
.material-icons.md-36 {
|
|
||||||
font-size: 36px;
|
|
||||||
}
|
|
||||||
.material-icons.md-48 {
|
|
||||||
font-size: 48px;
|
|
||||||
}
|
|
||||||
.material-icons {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.mpj-page-title {
|
|
||||||
border-bottom: solid 1px lightgray;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.mpj-footer {
|
|
||||||
border-top: solid 1px lightgray;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* myPrayerJournal script file
|
|
||||||
*/
|
|
||||||
var mpj = {
|
|
||||||
lock: new Auth0Lock('Of2s0RQCQ3mt3dwIkOBY5h85J9sXbF2n', 'djs-consulting.auth0.com', {
|
|
||||||
auth: {
|
|
||||||
redirectUrl: 'http://localhost:8080/user/log-on',
|
|
||||||
allowSignUp: false
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
signIn: function() {
|
|
||||||
this.lock.show()
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,8 +4,8 @@ var path = require('path')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
build: {
|
build: {
|
||||||
env: require('./prod.env'),
|
env: require('./prod.env'),
|
||||||
index: path.resolve(__dirname, '../dist/index.html'),
|
index: path.resolve(__dirname, '../../api/wwwroot/index.html'),
|
||||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
assetsRoot: path.resolve(__dirname, '../../api/wwwroot'),
|
||||||
assetsSubDirectory: 'static',
|
assetsSubDirectory: 'static',
|
||||||
assetsPublicPath: '/',
|
assetsPublicPath: '/',
|
||||||
productionSourceMap: true,
|
productionSourceMap: true,
|
||||||
|
1027
src/app/package-lock.json
generated
1027
src/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"auth0-js": "^8.8.0",
|
"auth0-js": "^8.8.0",
|
||||||
|
"axios": "^0.16.2",
|
||||||
"element-ui": "^1.4.1",
|
"element-ui": "^1.4.1",
|
||||||
"pug": "^2.0.0-rc.2",
|
"pug": "^2.0.0-rc.2",
|
||||||
"vue": "^2.3.3",
|
"vue": "^2.3.3",
|
||||||
|
@ -19,9 +19,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import url('../node_modules/bootstrap/dist/css/bootstrap.css');
|
|
||||||
@import url('../node_modules/bootstrap-vue/dist/bootstrap-vue.css');
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
padding-top: 60px;
|
padding-top: 60px;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const http = axios.create({
|
||||||
|
baseURL: 'http://localhost:8084'
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
something: http.get('/blah')
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user